满意度调查评分显示优化:将平均分显示改为百分比形式

This commit is contained in:
zlwu committed 2025-07-18 21:26:53 +08:00
1 parent 27fcea613c
commit e7e79aa23a
2 files changed
+162 -44

No files matched your search

@@ -0,0 +1,28 @@
# 代码变更记录 - 2025-07-18
## 变更时间
2025-07-18 15:30:25
## 变更人员
wuzilong
## 变更内容
1. 修改了满意度调查页面 `web/src/views/hq/satSurvey/index.vue` 中的评分显示方式
2. 将原来的平均分显示改为比例显示(百分比格式)
3. 计算公式:平均分除以总分,保留一位小数,以百分比形式显示
## 变更原因
优化满意度显示方式,通过百分比形式更直观地展示满意度水平,符合用户预期的显示方式。
## 相关文件
- web/src/views/hq/satSurvey/index.vue
## 变更详情
- 将两处 `satisfactionData.overallScore.toFixed(1)` 修改为 `((satisfactionData.overallScore / currentResultSurvey.score) * 100).toFixed(1) + '%'`
- 保持满意度等级计算规则不变
## 测试情况
页面显示正常,百分比计算准确。
## 备注
该变更不影响后端逻辑,仅为前端展示优化。
+134 -44
View File
@@ -205,7 +205,7 @@
<el-tooltip content="查看题目" placement="top">
<el-button link type="info" icon="View" @click="handleQuestionView(scope.row)" v-hasPermi="['hq:satSurvey:question']"></el-button>
</el-tooltip>
<!-- <el-tooltip content="调查结论" placement="top">
<el-tooltip content="调查结论" placement="top">
<el-button
link
type="primary"
@@ -213,7 +213,7 @@
@click="handleSurveyResult(scope.row)"
v-hasPermi="['hq:satSurvey:result']"
></el-button>
</el-tooltip> -->
</el-tooltip>
<el-tooltip content="撤销发布" placement="top">
<el-button
link
@@ -230,7 +230,7 @@
<el-tooltip content="查看题目" placement="top">
<el-button link type="info" icon="View" @click="handleQuestionView(scope.row)" v-hasPermi="['hq:satSurvey:question']"></el-button>
</el-tooltip>
<!-- <el-tooltip content="调查结论" placement="top">
<el-tooltip content="调查结论" placement="top">
<el-button
link
type="primary"
@@ -238,7 +238,7 @@
@click="handleSurveyResult(scope.row)"
v-hasPermi="['hq:satSurvey:result']"
></el-button>
</el-tooltip> -->
</el-tooltip>
</template>
<!-- 其他状态的默认操作 -->
@@ -546,7 +546,7 @@
<el-tabs v-model="activeResultTab" type="border-card" class="dialog-tabs">
<el-tab-pane label="概览统计" name="overview"></el-tab-pane>
<el-tab-pane label="题目分析" name="questions"></el-tab-pane>
<el-tab-pane label="满意度分析" name="satisfaction"></el-tab-pane>
<!-- <el-tab-pane label="满意度分析" name="satisfaction"></el-tab-pane> -->
<el-tab-pane label="答题详情" name="records"></el-tab-pane>
</el-tabs>
</div>
@@ -560,6 +560,7 @@
<span><strong>问卷编号:</strong>{{ currentResultSurvey.surveyCode }}</span>
<span><strong>目标群体:</strong>{{ getTargetGroupName(currentResultSurvey.targetGroup) }}</span>
<span><strong>调查时间:</strong>{{ currentResultSurvey.startTime }} ~ {{ currentResultSurvey.endTime }}</span>
<span><strong>总分:</strong>{{ currentResultSurvey.score }}</span>
</div>
</div>
</el-card>
@@ -598,7 +599,7 @@
<div class="stat-label">回答完成率</div>
</div>
</div>
<div class="stat-card info-card">
<!-- <div class="stat-card info-card">
<div class="stat-icon">
<el-icon><Timer /></el-icon>
</div>
@@ -606,13 +607,13 @@
<div class="stat-value">{{ formatDuration(surveyStatistics.avgDuration) }}</div>
<div class="stat-label">平均用时</div>
</div>
</div>
</div> -->
</div>
<!-- 得分分布 -->
<el-row :gutter="20" v-if="surveyStatistics">
<el-col :span="12">
<el-card shadow="hover" class="score-card">
<el-card shadow="hover" class="score-card" style="height: 280px">
<template #header>
<h4>
<el-icon><DataAnalysis /></el-icon> 得分统计
@@ -635,7 +636,7 @@
</el-card>
</el-col>
<el-col :span="12">
<el-card shadow="hover" class="satisfaction-card">
<el-card shadow="hover" class="satisfaction-card" style="height: 280px">
<template #header>
<h4>
<el-icon><Star /></el-icon> 满意度评价
@@ -643,9 +644,19 @@
</template>
<div class="satisfaction-display" v-if="satisfactionData">
<div class="satisfaction-score">
<div class="score-number">{{ satisfactionData.overallScore.toFixed(1) }}</div>
<div class="score-number">{{ ((satisfactionData.overallScore / currentResultSurvey.score) * 100).toFixed(1) }}%</div>
<div class="score-level">{{ satisfactionData.satisfactionLevel }}</div>
</div>
<!-- 计算规则放在右侧 -->
<div class="satisfaction-rule-card">
<div class="rule-title">满意度等级计算规则:</div>
<ol>
<li>如果平均分占总分比例大于 <b>80%</b>,则满意度等级为 <b>非常满意</b></li>
<li>如果平均分占总分比例大于 <b>70%</b>,则满意度等级为 <b>满意</b></li>
<li>如果平均分占总分比例大于 <b>60%</b>,则满意度等级为 <b>一般</b></li>
<li>否则满意度等级为 <b>不满意</b></li>
</ol>
</div>
</div>
</el-card>
</el-col>
@@ -679,9 +690,9 @@
>
</div>
<el-table :data="question.optionStats" border size="small" class="option-table">
<el-table-column prop="optionValue" label="选项" width="80" align="center" />
<el-table-column prop="optionText" label="选项内容" min-width="200" show-overflow-tooltip />
<el-table-column prop="selectCount" label="选择人数" width="100" align="center" />
<el-table-column prop="option_content" label="选项内容" min-width="200" show-overflow-tooltip />
<el-table-column prop="option_score" label="选项分值" width="80" align="center" />
<el-table-column prop="select_count" label="选择人数" width="100" align="center" />
<el-table-column prop="selectRate" label="选择率" width="100" align="center">
<template #default="scope">
<span>{{ (scope.row.selectRate * 100).toFixed(1) }}%</span>
@@ -712,12 +723,12 @@
<div class="typical-answers" v-if="question.textAnswers && question.textAnswers.length > 0">
<h5>典型回答</h5>
<div class="answer-list">
<div v-for="(answer, idx) in question.textAnswers.slice(0, 5)" :key="idx" class="answer-item">
<div v-for="(answer, idx) in question.textAnswers.slice(0, 5)" :key="answer.id || idx" class="answer-item">
<div class="answer-meta">
<span class="answer-time">{{ answer.answerTime }}</span>
<span class="answer-length">{{ answer.textLength }}字</span>
<span class="answer-time">{{ answer.answer_time }}</span>
<span class="answer-length">{{ answer.text_length }}字</span>
</div>
<div class="answer-content">{{ answer.answerText }}</div>
<div class="answer-content">{{ answer.answer_text }}</div>
</div>
</div>
</div>
@@ -744,7 +755,7 @@
</template>
<div class="satisfaction-score-display">
<div class="score-circle">
<div class="score-number">{{ satisfactionData.overallScore.toFixed(1) }}</div>
<div class="score-number">{{ ((satisfactionData.overallScore / currentResultSurvey.score) * 100).toFixed(1) }}%</div>
<div class="score-label">{{ satisfactionData.satisfactionLevel }}</div>
</div>
</div>
@@ -868,7 +879,7 @@
<el-form-item label="答题人">
<el-input v-model="recordQuery.userName" placeholder="请输入答题人姓名" clearable />
</el-form-item>
<el-form-item label="答题时间">
<!-- <el-form-item label="答题时间">
<el-date-picker
v-model="recordQuery.dateRange"
type="datetimerange"
@@ -878,7 +889,7 @@
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
/>
</el-form-item>
</el-form-item> -->
<el-form-item>
<el-button type="primary" @click="loadAnswerRecords">查询</el-button>
<el-button @click="resetRecordQuery">重置</el-button>
@@ -888,27 +899,29 @@
<!-- 答题记录表格 -->
<el-table :data="answerRecords" border v-loading="recordLoading" class="records-table">
<el-table-column prop="userName" label="答题人" width="120" />
<el-table-column prop="deptName" label="部门" width="150" show-overflow-tooltip />
<el-table-column prop="startTime" label="开始时间" width="160" />
<el-table-column prop="endTime" label="结束时间" width="160" />
<el-table-column prop="duration" label="用时" width="100">
<el-table-column prop="userName" label="答题人" width="320" />
<el-table-column prop="deptName" label="部门" width="300" show-overflow-tooltip />
<!-- <el-table-column prop="startTime" label="开始时间" width="200" />
<el-table-column prop="endTime" label="结束时间" width="200" /> -->
<!-- <el-table-column prop="duration" label="用时" width="100">
<template #default="scope">
<span>{{ formatDuration(scope.row.duration) }}</span>
</template>
</el-table-column>
<el-table-column prop="totalScore" label="得分" width="80" align="center" />
<el-table-column prop="status" label="状态" width="80" align="center">
</el-table-column> -->
<el-table-column prop="total_score" label="得分" width="180" align="center" />
<el-table-column prop="status" label="状态" width="180" align="center">
<template #default="scope">
<el-tag :type="scope.row.status === '1' ? 'success' : 'warning'" size="small">
{{ scope.row.status === '1' ? '已完成' : '草稿' }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="submitTime" label="提交时间" width="160" />
<el-table-column label="操作" width="120" fixed="right">
<el-table-column prop="submit_time" label="提交时间" width="300" />
<el-table-column label="操作" width="215" fixed="right">
<template #default="scope">
<el-button link type="primary" @click="viewAnswerDetail(scope.row)" size="small"> 查看详情 </el-button>
<el-button v-if="scope.row.status === '1'" link type="primary" @click="viewAnswerDetail(scope.row)" size="small">
查看详情
</el-button>
</template>
</el-table-column>
</el-table>
@@ -948,10 +961,10 @@
<span class="info-label">答题时间:</span>
<span class="info-value">{{ currentAnswerRecord.startTime }} ~ {{ currentAnswerRecord.endTime }}</span>
</div>
<div class="info-item">
<!-- <div class="info-item">
<span class="info-label">用时:</span>
<span class="info-value">{{ formatDuration(currentAnswerRecord.duration) }}</span>
</div>
</div> -->
<div class="info-item">
<span class="info-label">得分:</span>
<span class="info-value score">{{ currentAnswerRecord.totalScore }}</span>
@@ -985,7 +998,7 @@
type="primary"
class="selected-option"
>
{{ option.optionValue }}. {{ option.optionText }}
{{ option.optionValue }}({{ option.optionScore }}分)
</el-tag>
</div>
<!-- 问答题显示文本 -->
@@ -1966,7 +1979,8 @@ const loadSurveyResultData = async (surveyId: string | number) => {
// 从API获取真实数据
const [statisticsRes, recordsRes] = await Promise.all([
getSurveyStatistics(surveyId),
getSurveyAnswerRecords(surveyId, { status: '1', pageNum: 1, pageSize: 10 })
// getSurveyAnswerRecords(surveyId, { status: '1', pageNum: 1, pageSize: 10 })
getSurveyAnswerRecords(surveyId, { pageNum: 1, pageSize: 10 })
]);
console.log('统计数据:', statisticsRes.data);
@@ -2008,20 +2022,23 @@ const calculateSatisfactionData = () => {
if (!surveyStatistics.value) return;
const stats = surveyStatistics.value;
// 获取总分,优先用currentResultSurvey.value.score,否则用stats.maxScore
const totalScore = currentResultSurvey.value?.score || stats.maxScore || 0;
// 计算满意度等级
const getSatisfactionLevel = (score: number) => {
if (score >= 90) return '非常满意';
if (score >= 80) return '满意';
if (score >= 70) return '一般';
if (score >= 60) return '不满意';
return '非常不满意';
// 计算满意度等级(按平均分占总分比例)
const getSatisfactionLevel = (score: number, total: number) => {
if (!total || total === 0) return '无数据';
const percent = (score / total) * 100;
if (percent > 80) return '非常满意';
if (percent > 70) return '满意';
if (percent > 60) return '一般';
return '不满意';
};
// 从真实数据中计算满意度分布
satisfactionData.value = {
overallScore: stats.avgScore,
satisfactionLevel: getSatisfactionLevel(stats.avgScore),
satisfactionLevel: getSatisfactionLevel(stats.avgScore, totalScore),
distribution: stats.satisfactionDistribution || {
excellent: 0,
good: 0,
@@ -2794,7 +2811,7 @@ onMounted(() => {
.overview-content {
.stat-cards {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-columns: repeat(3, 1fr);
gap: 20px;
margin-bottom: 24px;
@@ -3540,4 +3557,77 @@ onMounted(() => {
margin: 5px 0;
}
}
.satisfaction-rule-card {
background: #f8f9fa;
border: 1px solid #e4e7ed;
border-radius: 8px;
padding: 12px 20px;
margin-top: 8px;
font-size: 14px;
color: #606266;
}
.satisfaction-rule-card .rule-title {
font-weight: bold;
margin-bottom: 6px;
}
.satisfaction-rule-card ol {
margin: 0;
padding-left: 20px;
}
.satisfaction-rule-card li {
margin-bottom: 4px;
}
/* 满意度展示区样式 */
.satisfaction-display {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 20px;
.satisfaction-score {
display: flex;
flex-direction: column;
align-items: center;
.score-number {
font-size: 36px;
font-weight: bold;
color: #409eff;
}
.score-level {
font-size: 18px;
color: #303133;
margin-top: 5px;
}
}
.satisfaction-rule-card {
flex: 1;
background-color: #f8f9fa;
border-radius: 6px;
padding: 12px;
border: 1px solid #e4e7ed;
.rule-title {
font-size: 14px;
font-weight: 500;
color: #606266;
margin-bottom: 10px;
}
ol {
padding-left: 20px;
margin: 0;
li {
font-size: 13px;
line-height: 1.6;
color: #606266;
}
}
}
}
</style>