From e06cd3953ba8a6e0eee11c235bce9ced419a2800 Mon Sep 17 00:00:00 2001
From: WXL (wul) <wl_5969728@163.com>
Date: 星期三, 03 六月 2026 14:05:08 +0800
Subject: [PATCH] 测试完成
---
src/views/Satisfaction/sfstatistics/components/SatisfactionStatistics.vue | 1451 ++++++++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 1,159 insertions(+), 292 deletions(-)
diff --git a/src/views/Satisfaction/sfstatistics/components/SatisfactionStatistics.vue b/src/views/Satisfaction/sfstatistics/components/SatisfactionStatistics.vue
index a6463e6..3ff1958 100644
--- a/src/views/Satisfaction/sfstatistics/components/SatisfactionStatistics.vue
+++ b/src/views/Satisfaction/sfstatistics/components/SatisfactionStatistics.vue
@@ -11,29 +11,30 @@
label-width="100px"
class="query-form"
>
- <el-form-item label="鎮h�呮潵婧�" prop="patientSource">
+ <el-form-item label="缁熻绫诲瀷" prop="patientSource">
<el-select
- v-model="queryParams.patientSource"
- placeholder="璇烽�夋嫨鎮h�呮潵婧�"
+ v-model="queryParams.type"
+ placeholder="璇烽�夋嫨缁熻绫诲瀷"
clearable
- style="width: 200px"
+ style="width: 100%"
>
- <el-option
- v-for="source in patientSourceList"
- :key="source.value"
- :label="source.label"
- :value="source.value"
- />
+ <el-option label="闂嵎绫诲瀷" :value="2" />
+ <el-option label="璇煶绫诲瀷" :value="1" />
+ <el-option label="鍏ㄩ儴" :value="null" />
</el-select>
</el-form-item>
- <el-form-item label="绉戝" prop="deptCode">
+ <!-- 绉戝閫夋嫨 -->
+ <el-form-item label="绉戝" prop="deptCodes">
<el-select
- v-model="queryParams.deptCode"
+ v-model="queryParams.deptCodes"
placeholder="璇烽�夋嫨绉戝"
clearable
filterable
- style="width: 200px"
+ multiple
+ collapse-tags
+ style="width: 300px"
+ @change="handleDeptChange"
>
<el-option
v-for="dept in deptList"
@@ -44,13 +45,17 @@
</el-select>
</el-form-item>
- <el-form-item label="鐥呭尯" prop="wardCode">
+ <!-- 鐥呭尯閫夋嫨 -->
+ <el-form-item label="鐥呭尯" prop="wardCodes">
<el-select
- v-model="queryParams.wardCode"
+ v-model="queryParams.wardCodes"
placeholder="璇烽�夋嫨鐥呭尯"
clearable
filterable
- style="width: 200px"
+ multiple
+ collapse-tags
+ style="width: 300px"
+ @change="handleWardChange"
>
<el-option
v-for="ward in wardList"
@@ -96,7 +101,7 @@
<el-card shadow="never">
<div class="chart-container">
<div class="chart-header">
- <h3 class="chart-title">婊℃剰搴︾被鍨嬪~鎶ユ瘮渚嬬粺璁�</h3>
+ <h3 class="chart-title">{{ getChartTitle() }}</h3>
<div class="statistic-info">
<div class="statistic-item">
<span class="statistic-label">鍙戦�侀棶鍗锋�婚噺锛�</span>
@@ -118,6 +123,20 @@
</div>
</div>
</div>
+
+ <!-- 鏍囩椤靛垏鎹� -->
+ <el-tabs
+ v-model="activeChartTab"
+ @tab-click="handleChartTabClick"
+ class="chart-tabs"
+ >
+ <el-tab-pane
+ label="婊℃剰搴︾被鍨�"
+ name="satisfactionType"
+ ></el-tab-pane>
+ <el-tab-pane label="缁村害缁熻" name="dimension"></el-tab-pane>
+ </el-tabs>
+
<div
id="satisfactionBarChart"
style="width: 100%; height: 400px"
@@ -190,7 +209,7 @@
min-width="300"
>
<template slot-scope="{ row }">
- <span>{{ row.scriptContent }}?</span>
+ <span>{{ row.scriptContent }}</span>
<el-tag
:type="row.scriptType === 1 ? 'primary' : 'success'"
size="mini"
@@ -254,7 +273,7 @@
width="100"
>
<template slot-scope="{ row }">
- {{ row.totalCount - row.answerCount }}
+ {{ row.noAnswerPerson }}
</template>
</el-table-column>
@@ -265,7 +284,7 @@
width="100"
>
<template slot-scope="{ row }">
- {{ formatPercent(row.answerCount / row.totalCount) }}
+ {{ formatPercent(row.answerRate) }}
</template>
</el-table-column>
</el-table>
@@ -273,10 +292,6 @@
<!-- 缁煎悎寰楀垎琛� -->
<div class="summary-row">
<div class="summary-content">
- <div class="summary-item">
- <span class="label">缁煎悎寰楀垎锛�</span>
- <span class="value">{{ totalScore.toFixed(1) }}</span>
- </div>
<div class="summary-item">
<span class="label">鎬荤瓟棰樹汉鏁帮細</span>
<span class="value">{{ totalAnswerCount }}</span>
@@ -305,6 +320,179 @@
@size-change="handleDetailSizeChange"
@current-change="handleDetailPageChange"
/>
+ </div>
+ </div>
+ </el-tab-pane>
+
+ <el-tab-pane label="缁村害棰樼洰鏄庣粏" name="dimensionDetail">
+ <!-- 缁村害棰樼洰鏄庣粏琛ㄦ牸 -->
+ <div class="dimension-detail-section">
+ <el-table
+ v-loading="dimensionDetailLoading"
+ :data="dimensionDetailData"
+ :border="true"
+ style="width: 100%"
+ row-class-name="dimension-row"
+ >
+ <el-table-column type="expand" width="60">
+ <template slot-scope="{ row }">
+ <div class="option-detail">
+ <el-table
+ :data="row.options"
+ :border="true"
+ style="width: 100%"
+ class="inner-table"
+ >
+ <el-table-column
+ label="閫夐」"
+ prop="optionText"
+ align="center"
+ min-width="200"
+ />
+ <el-table-column
+ label="閫夋嫨浜烘暟"
+ prop="chosenQuantity"
+ align="center"
+ min-width="120"
+ />
+ <el-table-column
+ label="閫夋嫨姣斾緥"
+ prop="chosenPercentage"
+ align="center"
+ min-width="120"
+ >
+ <template slot-scope="{ row: option }">
+ {{ formatPercent(option.chosenPercentage) }}
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+ </template>
+ </el-table-column>
+
+ <el-table-column
+ label="搴忓彿"
+ type="index"
+ align="center"
+ width="60"
+ />
+
+ <el-table-column
+ label="棰樼洰"
+ prop="scriptContent"
+ align="center"
+ min-width="300"
+ >
+ <template slot-scope="{ row }">
+ <span>{{ row.scriptContent }}</span>
+ <el-tag
+ :type="row.scriptType === 1 ? 'primary' : 'success'"
+ size="mini"
+ style="margin-left: 5px"
+ >
+ {{ row.scriptType === 1 ? "鍗曢�夐" : "澶氶�夐" }}
+ </el-tag>
+ </template>
+ </el-table-column>
+
+ <el-table-column
+ label="缁村害"
+ prop="dimensionName"
+ align="center"
+ width="120"
+ >
+ <template slot-scope="{ row }">
+ <el-tag type="info" size="small">
+ {{ getDimensionLabel(row.dimension) }}
+ </el-tag>
+ </template>
+ </el-table-column>
+
+ <el-table-column
+ label="骞冲潎寰楀垎"
+ prop="averageScore"
+ align="center"
+ width="120"
+ >
+ <template slot-scope="{ row }">
+ <span class="score-text">{{
+ row.averageScore.toFixed(1)
+ }}</span>
+ </template>
+ </el-table-column>
+
+ <el-table-column
+ label="鏈�楂樺緱鍒�"
+ prop="maxScore"
+ align="center"
+ width="120"
+ >
+ <template slot-scope="{ row }">
+ <span class="score-text">{{
+ row.maxScore.toFixed(1)
+ }}</span>
+ </template>
+ </el-table-column>
+
+ <el-table-column
+ label="鏈�浣庡緱鍒�"
+ prop="minScore"
+ align="center"
+ width="120"
+ >
+ <template slot-scope="{ row }">
+ <span class="score-text">{{
+ row.minScore.toFixed(1)
+ }}</span>
+ </template>
+ </el-table-column>
+
+ <el-table-column
+ label="绛旈浜烘暟"
+ prop="answerPerson"
+ align="center"
+ width="100"
+ />
+
+ <el-table-column
+ label="鏈瓟棰樹汉鏁�"
+ prop="noAnswerPerson"
+ align="center"
+ width="100"
+ />
+
+ <el-table-column
+ label="绛旈鐜�"
+ prop="answerRate"
+ align="center"
+ width="100"
+ >
+ <template slot-scope="{ row }">
+ {{ formatPercent(row.answerRate) }}
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <!-- 缁村害缁熻姹囨�� -->
+ <div class="dimension-summary-row">
+ <div class="dimension-summary-content">
+ <div class="dimension-summary-item">
+ <span class="label">棰樼洰鎬绘暟锛�</span>
+ <span class="value">{{ dimensionDetailData.length }}</span>
+ </div>
+ <div class="dimension-summary-item">
+ <span class="label">缁村害骞冲潎鍒嗭細</span>
+ <span class="value">{{
+ dimensionAverageScore.toFixed(1)
+ }}</span>
+ </div>
+ <div class="dimension-summary-item">
+ <span class="label">鎬讳綋绛旈鐜囷細</span>
+ <span class="value">{{
+ formatPercent(dimensionTotalAnswerRate)
+ }}</span>
+ </div>
+ </div>
</div>
</div>
</el-tab-pane>
@@ -403,32 +591,6 @@
</el-table-column>
<el-table-column
- label="鏈�楂樺垎"
- prop="maxScore"
- align="center"
- width="120"
- >
- <template slot-scope="{ row }">
- <span class="score-text">{{
- row.maxScore.toFixed(1)
- }}</span>
- </template>
- </el-table-column>
-
- <el-table-column
- label="鏈�浣庡垎"
- prop="minScore"
- align="center"
- width="120"
- >
- <template slot-scope="{ row }">
- <span class="score-text">{{
- row.minScore.toFixed(1)
- }}</span>
- </template>
- </el-table-column>
-
- <el-table-column
label="婊℃剰搴︾瓑绾�"
prop="satisfactionLevel"
align="center"
@@ -442,40 +604,6 @@
>
{{ row.satisfactionLevel }}
</el-tag>
- </template>
- </el-table-column>
-
- <el-table-column
- label="瓒嬪娍"
- prop="trend"
- align="center"
- width="120"
- >
- <template slot-scope="{ row }">
- <div class="trend-cell">
- <i
- v-if="row.trend === 'up'"
- class="el-icon-top trend-up"
- :style="{ color: '#67C23A' }"
- />
- <i
- v-else-if="row.trend === 'down'"
- class="el-icon-bottom trend-down"
- :style="{ color: '#F56C6C' }"
- />
- <i
- v-else
- class="el-icon-minus trend-stable"
- :style="{ color: '#909399' }"
- />
- <span class="trend-text">{{
- row.trend === "up"
- ? "涓婂崌"
- : row.trend === "down"
- ? "涓嬮檷"
- : "绋冲畾"
- }}</span>
- </div>
</template>
</el-table-column>
@@ -539,22 +667,31 @@
<script>
import * as echarts from "echarts";
+import {
+ statistics,
+ satisfactionGraph,
+ statisticsByDimension,
+ satisfactionGraphDimension,
+} from "@/api/system/user";
+import store from "@/store";
export default {
name: "SatisfactionStatistics",
+ dicts: ["dimensionality_type"],
data() {
return {
// 鏌ヨ鍙傛暟
queryParams: {
+ type: 2,
patientSource: "",
- deptCode: "",
- wardCode: "",
+ deptCodes: [], // 鏀逛负鏁扮粍锛屾敮鎸佸閫�
+ wardCodes: [], // 鏀逛负鏁扮粍锛屾敮鎸佸閫�
dateRange: [],
},
-
// 褰撳墠婵�娲荤殑tab
activeTab: "questionDetail",
-
+ // 褰撳墠婵�娲荤殑鍥捐〃tab
+ activeChartTab: "satisfactionType",
// 鎮h�呮潵婧愰�夐」
patientSourceList: [
{ value: "1", label: "闂ㄨ瘖" },
@@ -576,9 +713,13 @@
loading: false,
detailLoading: false,
typeDetailLoading: false,
+ dimensionDetailLoading: false,
// 棰樼洰鏄庣粏鏁版嵁
questionDetailData: [],
+
+ // 缁村害棰樼洰鏄庣粏鏁版嵁
+ dimensionDetailData: [],
// 棰樼洰鏄庣粏鏌ヨ鍙傛暟
detailQueryParams: {
@@ -589,17 +730,34 @@
// 棰樼洰鏄庣粏鎬绘暟
detailTotal: 0,
+ // 缁村害鏄庣粏鏌ヨ鍙傛暟
+ dimensionQueryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ },
+
+ // 缁村害鏄庣粏鎬绘暟
+ dimensionTotal: 0,
+
// 缁煎悎寰楀垎
totalScore: 0,
totalAnswerCount: 0,
totalAnswerRate: 0,
+ // 缁村害缁熻姹囨��
+ dimensionTotalAnswerCount: 0,
+ dimensionTotalAnswerRate: 0,
+ dimensionAverageScore: 0,
+
// 鍚勭被鍨嬬粺璁℃槑缁嗘暟鎹�
typeDetailData: [],
+ // 鏌辩姸鍥炬暟鎹�
+ chartData: [],
+
// 缁熻淇℃伅
- totalSendCount: 12560,
- totalReceiveCount: 10240,
+ totalSendCount: 0,
+ totalReceiveCount: 0,
overallRecoveryRate: 0,
// 绫诲瀷缁熻姹囨��
@@ -650,7 +808,54 @@
{ id: 403, name: "闂ㄨ瘖婊℃剰搴�", color: "#409EFF" },
{ id: 404, name: "甯哥敤婊℃剰搴�", color: "#FF9D4D" },
],
+
+ // 鏂板锛氶粯璁ゆ湇鍔$被鍨嬫暟缁�
+ defaultServiceTypes: ["6", "14", "15", "16"],
+
+ // 鏂板锛氬熀纭�妯℃澘闂ID闆嗗悎
+ scriptIds: [],
+
+ // 鏂板锛氭ā鏉縄D
+ templateId: null,
};
+ },
+
+ computed: {
+ // 璁$畻鏌ヨ寮�濮嬫椂闂�
+ startTime() {
+ if (this.queryParams.dateRange && this.queryParams.dateRange[0]) {
+ return this.queryParams.dateRange[0];
+ }
+ // 榛樿鏈�杩�7澶�
+ const date = new Date();
+ date.setDate(date.getDate() - 7);
+ return this.formatDate(date);
+ },
+
+ // 璁$畻鏌ヨ缁撴潫鏃堕棿
+ endTime() {
+ if (this.queryParams.dateRange && this.queryParams.dateRange[1]) {
+ return this.queryParams.dateRange[1];
+ }
+ // 榛樿浠婂ぉ
+ return this.formatDate(new Date());
+ },
+
+ // 璁$畻绉戝缂栫爜鏁扮粍
+ deptCodes() {
+ if (this.queryParams.deptCodes && this.queryParams.deptCodes.length > 0) {
+ return this.queryParams.deptCodes;
+ }
+ return this.deptList.map((dept) => dept.value);
+ },
+
+ // 璁$畻鐥呭尯缂栫爜鏁扮粍
+ hospitalDistrictCodes() {
+ if (this.queryParams.wardCodes && this.queryParams.wardCodes.length > 0) {
+ return this.queryParams.wardCodes;
+ }
+ return this.wardList.map((ward) => ward.value);
+ },
},
mounted() {
@@ -665,6 +870,14 @@
},
methods: {
+ // 鏍煎紡鍖栨棩鏈�
+ formatDate(date) {
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, "0");
+ const day = String(date.getDate()).padStart(2, "0");
+ return `${year}-${month}-${day}`;
+ },
+
// 鍒濆鍖栨暟鎹�
async initData() {
await this.getDeptList();
@@ -676,35 +889,34 @@
// 鑾峰彇绉戝鍒楄〃
getDeptList() {
return new Promise((resolve) => {
- setTimeout(() => {
- this.deptList = [
- { value: "dept001", label: "蹇冭绠″唴绉�" },
- { value: "dept002", label: "绁炵粡鍐呯" },
- { value: "dept003", label: "鏅绉�" },
- { value: "dept004", label: "楠ㄧ" },
- { value: "dept005", label: "濡囦骇绉�" },
- { value: "dept006", label: "鍎跨" },
- ];
- resolve();
- }, 100);
+ this.deptList = (this.$store.getters.belongDepts || []).map((dept) => {
+ return {
+ label: dept.deptName,
+ value: dept.deptCode,
+ };
+ });
+ resolve();
});
},
// 鑾峰彇鐥呭尯鍒楄〃
getWardList() {
return new Promise((resolve) => {
- setTimeout(() => {
- this.wardList = [
- { value: "ward001", label: "鍐呯涓�鐥呭尯" },
- { value: "ward002", label: "鍐呯浜岀梾鍖�" },
- { value: "ward003", label: "澶栫涓�鐥呭尯" },
- { value: "ward004", label: "澶栫浜岀梾鍖�" },
- { value: "ward005", label: "濡囦骇绉戠梾鍖�" },
- { value: "ward006", label: "鍎跨鐥呭尯" },
- ];
- resolve();
- }, 100);
+ this.wardList = (this.$store.getters.belongWards || []).map((ward) => {
+ return {
+ label: ward.districtName,
+ value: ward.districtCode,
+ };
+ });
+ resolve();
});
+ },
+
+ // 鑾峰彇鍥捐〃鏍囬
+ getChartTitle() {
+ return this.activeChartTab === "satisfactionType"
+ ? "婊℃剰搴︾被鍨嬪~鎶ユ瘮渚嬬粺璁�"
+ : "缁村害濉姤姣斾緥缁熻";
},
// 鍔犺浇鏁版嵁
@@ -720,21 +932,190 @@
async loadChartData() {
this.loading = true;
try {
- // 妯℃嫙API璋冪敤
- const chartData = await this.generateChartData();
- this.renderChart(chartData);
-
- // 璁$畻鎬讳綋鍥炴敹鐜�
- this.overallRecoveryRate = this.totalReceiveCount / this.totalSendCount;
+ if (this.activeChartTab === "satisfactionType") {
+ await this.loadSatisfactionTypeChartData();
+ } else {
+ await this.loadDimensionChartData();
+ }
+ } catch (error) {
+ console.error("鑾峰彇鍥捐〃鏁版嵁鍑洪敊:", error);
+ this.$message.error("鑾峰彇鍥捐〃鏁版嵁澶辫触");
+ // 閿欒鏃朵娇鐢╩ock鏁版嵁
+ await this.generateMockChartData();
} finally {
this.loading = false;
}
+ },
+
+ // 鍔犺浇婊℃剰搴︾被鍨嬪浘琛ㄦ暟鎹�
+ async loadSatisfactionTypeChartData() {
+ const params = {
+ type: this.queryParams.type,
+ startTime: this.startTime,
+ endTime: this.endTime,
+ deptcodes: this.deptCodes, // 浣跨敤璁$畻灞炴��
+ hospitaldistrictcodes: this.hospitalDistrictCodes, // 浣跨敤璁$畻灞炴��
+ templateid: this.templateId,
+ };
+
+ const response = await satisfactionGraph(params);
+ if (response.code === 200) {
+ this.processSatisfactionTypeChartData(response);
+ } else {
+ this.$message.error(response.msg || "鑾峰彇鍥捐〃鏁版嵁澶辫触");
+ await this.generateMockChartData();
+ }
+ },
+
+ // 鍔犺浇缁村害鍥捐〃鏁版嵁
+ async loadDimensionChartData() {
+ const params = {
+ type: this.queryParams.type,
+ startTime: this.startTime,
+ endTime: this.endTime,
+ deptcodes: this.deptCodes, // 浣跨敤璁$畻灞炴��
+ hospitaldistrictcodes: this.hospitalDistrictCodes, // 浣跨敤璁$畻灞炴��
+ templateid: this.templateId,
+ };
+
+ const response = await satisfactionGraphDimension(params);
+ if (response.code === 200) {
+ this.processDimensionChartData(response);
+ } else {
+ this.$message.error(response.msg || "鑾峰彇缁村害鍥捐〃鏁版嵁澶辫触");
+ await this.generateMockDimensionChartData();
+ }
+ },
+
+ // 澶勭悊婊℃剰搴︾被鍨嬪浘琛ㄦ暟鎹�
+ processSatisfactionTypeChartData(apiData) {
+ if (!apiData || !apiData.rows || Object.keys(apiData.rows).length === 0) {
+ this.chartData = [];
+ this.totalSendCount = 0;
+ this.totalReceiveCount = 0;
+ this.overallRecoveryRate = 0;
+ this.renderChart([], "satisfactionType");
+ return;
+ }
+
+ const chartData = [];
+ let totalSend = 0;
+ let totalReceive = 0;
+ let index = 0;
+
+ // 澶勭悊鎺ュ彛杩斿洖鐨勬弧鎰忓害绫诲瀷缁熻
+ Object.entries(apiData.rows).forEach(([typeName, typeStat]) => {
+ const sendCount = typeStat.subidAll || 0;
+ const receiveCount = typeStat.fillCountAll || 0;
+ const recoveryRate = typeStat.receiveRate.toFixed(2) || 0;
+
+ chartData.push({
+ name: typeName,
+ value: (recoveryRate * 100).toFixed(2), // 杞崲涓虹櫨鍒嗘瘮
+ sendCount: sendCount,
+ receiveCount: receiveCount,
+ averageScore: typeStat.averageScore || 0,
+ itemStyle: { color: this.getChartColor(index) },
+ });
+
+ totalSend += sendCount;
+ totalReceive += receiveCount;
+ index++;
+ });
+
+ this.totalSendCount = totalSend;
+ this.totalReceiveCount = totalReceive;
+ this.overallRecoveryRate = totalSend > 0 ? totalReceive / totalSend : 0;
+ this.chartData = chartData;
+
+ this.renderChart(chartData, "satisfactionType");
+ },
+
+ // 澶勭悊缁村害鍥捐〃鏁版嵁
+ processDimensionChartData(apiData) {
+ if (!apiData || !apiData.rows || Object.keys(apiData.rows).length === 0) {
+ this.chartData = [];
+ this.totalSendCount = 0;
+ this.totalReceiveCount = 0;
+ this.overallRecoveryRate = 0;
+ this.renderChart([], "dimension");
+ return;
+ }
+
+ const chartData = [];
+ let totalSend = 0;
+ let totalReceive = 0;
+ let index = 0;
+
+ // 澶勭悊鎺ュ彛杩斿洖鐨勭淮搴︾粺璁�
+ Object.entries(apiData.rows).forEach(([dimensionCode, dimensionStat]) => {
+ const sendCount = dimensionStat.subidAll || 0;
+ const receiveCount = dimensionStat.fillCountAll || 0;
+ const recoveryRate = dimensionStat.receiveRate || 0;
+
+ // 鑾峰彇缁村害鏍囩
+ const dimensionName = this.getDimensionLabel(dimensionCode);
+
+ chartData.push({
+ name: dimensionName,
+ value: (recoveryRate * 100).toFixed(2), // 杞崲涓虹櫨鍒嗘瘮
+ sendCount: sendCount,
+ receiveCount: receiveCount,
+ averageScore: dimensionStat.averageScore || 0,
+ dimension: dimensionCode,
+ itemStyle: { color: this.getChartColor(index) },
+ });
+
+ totalSend += sendCount;
+ totalReceive += receiveCount;
+ index++;
+ });
+
+ this.totalSendCount = totalSend;
+ this.totalReceiveCount = totalReceive;
+ this.overallRecoveryRate = totalSend > 0 ? totalReceive / totalSend : 0;
+ this.chartData = chartData;
+
+ this.renderChart(chartData, "dimension");
+ },
+
+ // 鑾峰彇缁村害鏍囩
+ getDimensionLabel(dimensionCode) {
+ if (!this.dict.type.dimensionality_type) return dimensionCode;
+ const dimension = this.dict.type.dimensionality_type.find(
+ (item) => item.value.toString() === dimensionCode.toString()
+ );
+ return dimension ? dimension.label : dimensionCode;
},
// 鍔犺浇棰樼洰鏄庣粏鏁版嵁
async loadQuestionDetailData() {
this.detailLoading = true;
try {
+ const params = {
+ type: this.queryParams.type,
+ startTime: this.startTime,
+ endTime: this.endTime,
+ scriptids: this.scriptIds,
+ deptcodes: this.deptCodes, // 浣跨敤璁$畻灞炴��
+ hospitaldistrictcodes: this.hospitalDistrictCodes, // 浣跨敤璁$畻灞炴��
+ templateid: this.templateId,
+ };
+
+ const response = await statistics(params);
+
+ if (response.code === 200) {
+ this.processQuestionDetailData(response.rows);
+ } else {
+ this.$message.error(response.msg || "鑾峰彇棰樼洰鏄庣粏鏁版嵁澶辫触");
+ const mockData = await this.generateMockQuestionDetail();
+ this.questionDetailData = mockData.list;
+ this.detailTotal = mockData.total;
+ this.calculateSummary(mockData);
+ }
+ } catch (error) {
+ console.error("鑾峰彇棰樼洰鏄庣粏鏁版嵁鍑洪敊:", error);
+ this.$message.error("鑾峰彇棰樼洰鏄庣粏鏁版嵁澶辫触");
const mockData = await this.generateMockQuestionDetail();
this.questionDetailData = mockData.list;
this.detailTotal = mockData.total;
@@ -744,18 +1125,209 @@
}
},
+ // 澶勭悊鎺ュ彛杩斿洖鐨勯鐩槑缁嗘暟鎹�
+ processQuestionDetailData(apiData) {
+ if (!apiData || !apiData.patSatisfactionDetailEntities) {
+ this.questionDetailData = [];
+ this.detailTotal = 0;
+ this.totalAnswerCount = 0;
+ this.totalAnswerRate = 0;
+ return;
+ }
+
+ const detailData = apiData.patSatisfactionDetailEntities.map((item) => {
+ const options = [];
+ if (item.matchedtextStats) {
+ Object.keys(item.matchedtextStats).forEach((key) => {
+ const stat = item.matchedtextStats[key];
+ options.push({
+ optionText: key,
+ chosenQuantity: stat.count || 0,
+ chosenPercentage: (stat.ratio || 0) / 100,
+ });
+ });
+ }
+
+ return {
+ scriptContent: item.scriptContent || "",
+ scriptType: 1,
+ answerPerson: item.answerPerson || 0,
+ noAnswerPerson: item.noAnswerPerson || 0,
+ answerCount: item.answerPerson || 0,
+ averageScore: item.averageScore || 0,
+ maxScore: item.maxScore || 0,
+ minScore: item.minScore || 0,
+ answerRate: item.answerRate || 0,
+ totalCount: (item.answerPerson || 0) + (item.noAnswerPerson || 0),
+ options: options,
+ };
+ });
+
+ const startIndex =
+ (this.detailQueryParams.pageNum - 1) * this.detailQueryParams.pageSize;
+ const endIndex = startIndex + this.detailQueryParams.pageSize;
+ const paginatedData = detailData.slice(startIndex, endIndex);
+
+ this.questionDetailData = paginatedData;
+ this.detailTotal = detailData.length;
+ this.totalAnswerCount = apiData.totalPerson || 0;
+ this.totalAnswerRate = apiData.totalAnswerRate || 0;
+ },
+
+ // 鍔犺浇缁村害鏄庣粏鏁版嵁
+ async loadDimensionDetailData() {
+ this.dimensionDetailLoading = true;
+ try {
+ const params = {
+ type: this.queryParams.type,
+ startTime: this.startTime,
+ endTime: this.endTime,
+ deptcodes: this.deptCodes, // 浣跨敤璁$畻灞炴��
+ hospitaldistrictcodes: this.hospitalDistrictCodes, // 浣跨敤璁$畻灞炴��
+ templateid: this.templateId,
+ questionType: this.queryParams.type || null,
+ serviceTypes: this.defaultServiceTypes,
+ };
+
+ const response = await statisticsByDimension(params);
+
+ if (response.code === 200) {
+ this.processDimensionDetailData(response.rows);
+ } else {
+ this.$message.error(response.msg || "鑾峰彇缁村害鏄庣粏鏁版嵁澶辫触");
+ const mockData = await this.generateMockDimensionDetail();
+ this.dimensionDetailData = mockData;
+ this.calculateDimensionSummary(mockData);
+ }
+ } catch (error) {
+ console.error("鑾峰彇缁村害鏄庣粏鏁版嵁鍑洪敊:", error);
+ this.$message.error("鑾峰彇缁村害鏄庣粏鏁版嵁澶辫触");
+ const mockData = await this.generateMockDimensionDetail();
+ this.dimensionDetailData = mockData;
+ this.calculateDimensionSummary(mockData);
+ } finally {
+ this.dimensionDetailLoading = false;
+ }
+ },
+
+ // 澶勭悊缁村害鏄庣粏鏁版嵁
+ processDimensionDetailData(apiData) {
+ if (!apiData || !apiData.patSatisfactionDetailEntities) {
+ this.dimensionDetailData = [];
+ this.calculateDimensionSummary([]);
+ return;
+ }
+
+ const detailData = apiData.patSatisfactionDetailEntities.map((item) => {
+ const options = [];
+ if (item.matchedtextStats) {
+ Object.keys(item.matchedtextStats).forEach((key) => {
+ const stat = item.matchedtextStats[key];
+ options.push({
+ optionText: key,
+ chosenQuantity: stat.count || 0,
+ chosenPercentage: (stat.ratio || 0) / 100,
+ });
+ });
+ }
+
+ return {
+ scriptContent: item.scriptContent || "",
+ dimension: item.dimension || "0", // 缁村害浠g爜
+ dimensionName: this.getDimensionLabel(item.dimension || "0"), // 缁村害鍚嶇О
+ scriptType: 1,
+ answerPerson: item.answerPerson || 0,
+ noAnswerPerson: item.noAnswerPerson || 0,
+ answerCount: item.answerPerson || 0,
+ averageScore: item.averageScore || 0,
+ maxScore: item.maxScore || 0,
+ minScore: item.minScore || 0,
+ answerRate: item.answerRate || 0,
+ totalCount: (item.answerPerson || 0) + (item.noAnswerPerson || 0),
+ options: options,
+ };
+ });
+
+ this.dimensionDetailData = detailData;
+ this.dimensionTotal = detailData.length;
+ this.calculateDimensionSummary(detailData);
+ },
+
// 鍔犺浇绫诲瀷鏄庣粏鏁版嵁
async loadTypeDetailData() {
this.typeDetailLoading = true;
try {
+ const params = {
+ type: this.queryParams.type,
+ startTime: this.startTime,
+ endTime: this.endTime,
+ deptcodes: this.deptCodes, // 浣跨敤璁$畻灞炴��
+ hospitaldistrictcodes: this.hospitalDistrictCodes, // 浣跨敤璁$畻灞炴��
+ templateid: this.templateId,
+ };
+
+ const response = await satisfactionGraph(params);
+
+ if (response.code === 200) {
+ this.processTypeDetailData(response);
+ } else {
+ this.$message.error(response.msg || "鑾峰彇绫诲瀷鏄庣粏鏁版嵁澶辫触");
+ const mockData = await this.generateMockTypeDetail();
+ this.typeDetailData = mockData;
+ this.calculateTypeSummary(mockData);
+ }
+ } catch (error) {
+ console.error("鑾峰彇绫诲瀷鏄庣粏鏁版嵁鍑洪敊:", error);
+ this.$message.error("鑾峰彇绫诲瀷鏄庣粏鏁版嵁澶辫触");
const mockData = await this.generateMockTypeDetail();
this.typeDetailData = mockData;
-
- // 璁$畻绫诲瀷缁熻姹囨��
this.calculateTypeSummary(mockData);
} finally {
this.typeDetailLoading = false;
}
+ },
+
+ // 澶勭悊绫诲瀷鏄庣粏鏁版嵁
+ processTypeDetailData(apiData) {
+ if (!apiData || !apiData.rows || Object.keys(apiData.rows).length === 0) {
+ this.typeDetailData = [];
+ this.calculateTypeSummary([]);
+ return;
+ }
+
+ const typeDetail = [];
+ Object.entries(apiData.rows).forEach(([typeName, typeStat], index) => {
+ const sendCount = typeStat.subidAll || 0;
+ const receiveCount = typeStat.fillCountAll || 0;
+ const recoveryRate = typeStat.receiveRate.toFixed(2) || 0;
+ const averageScore = typeStat.averageScore || 0;
+
+ typeDetail.push({
+ id: index + 1,
+ typeName: typeName,
+ isSpecial: false, // 鏍规嵁瀹為檯鎯呭喌鍒ゆ柇
+ sendCount: sendCount,
+ receiveCount: receiveCount,
+ recoveryRate: recoveryRate,
+ averageScore: averageScore,
+ maxScore: 5, // 榛樿鍊�
+ minScore: 0, // 榛樿鍊�
+ satisfactionLevel: this.getSatisfactionLevel(averageScore),
+ trend: "stable", // 榛樿绋冲畾
+ });
+ });
+
+ this.typeDetailData = typeDetail;
+ this.calculateTypeSummary(typeDetail);
+ },
+
+ // 鏍规嵁骞冲潎鍒嗚幏鍙栨弧鎰忓害绛夌骇
+ getSatisfactionLevel(score) {
+ if (score >= 4.5) return "浼樼";
+ if (score >= 4.0) return "鑹ソ";
+ if (score >= 3.0) return "涓�鑸�";
+ if (score >= 2.0) return "杈冨樊";
+ return "鏈煡";
},
// 璁$畻缁煎悎寰楀垎
@@ -774,6 +1346,32 @@
data.list.length > 0 ? totalScore / data.list.length : 0;
this.totalAnswerCount = totalAnswerCount;
this.totalAnswerRate = totalCount > 0 ? totalAnswerCount / totalCount : 0;
+ },
+
+ // 璁$畻缁村害缁熻姹囨��
+ calculateDimensionSummary(data) {
+ if (data.length === 0) {
+ this.dimensionTotalAnswerCount = 0;
+ this.dimensionTotalAnswerRate = 0;
+ this.dimensionAverageScore = 0;
+ return;
+ }
+
+ let totalScore = 0;
+ let totalAnswerCount = 0;
+ let totalCount = 0;
+
+ data.forEach((item) => {
+ totalScore += item.averageScore;
+ totalAnswerCount += item.answerPerson;
+ totalCount += item.answerPerson + item.noAnswerPerson;
+ });
+
+ this.dimensionAverageScore =
+ data.length > 0 ? totalScore / data.length : 0;
+ this.dimensionTotalAnswerCount = totalAnswerCount;
+ this.dimensionTotalAnswerRate =
+ totalCount > 0 ? totalAnswerCount / totalCount : 0;
},
// 璁$畻绫诲瀷缁熻姹囨��
@@ -814,49 +1412,34 @@
window.addEventListener("resize", this.handleChartResize);
},
- // 鐢熸垚鍥捐〃鏁版嵁
- generateChartData() {
- return new Promise((resolve) => {
- setTimeout(() => {
- const data = this.satisfactionTypes.map((type) => ({
- name: type.name,
- recoveryRate: Math.random() * 0.3 + 0.6, // 60%-90%鐨勫洖鏀剁巼
- sendCount: Math.floor(Math.random() * 3000) + 1500, // 1500-4500
- receiveCount: 0,
- color: type.color,
- }));
-
- // 璁$畻鍥炴敹鏁伴噺
- data.forEach((item) => {
- item.receiveCount = Math.floor(item.sendCount * item.recoveryRate);
- });
-
- // 鏇存柊鎬婚噺
- this.totalSendCount = data.reduce(
- (sum, item) => sum + item.sendCount,
- 0
- );
- this.totalReceiveCount = data.reduce(
- (sum, item) => sum + item.receiveCount,
- 0
- );
-
- resolve({
- data: data.map((item) => ({
- name: item.name,
- value: item.recoveryRate * 100, // 杞崲涓虹櫨鍒嗘瘮
- sendCount: item.sendCount,
- receiveCount: item.receiveCount,
- itemStyle: { color: item.color },
- })),
- });
- }, 300);
- });
- },
-
// 娓叉煋鍥捐〃
- renderChart(chartData) {
+ renderChart(chartData, chartType = "satisfactionType") {
if (!this.barChart) return;
+ if (!chartData || chartData.length === 0) {
+ const emptyOption = {
+ title: {
+ text: "鏆傛棤鏁版嵁",
+ left: "center",
+ top: "center",
+ textStyle: {
+ color: "#999",
+ fontSize: 16,
+ fontWeight: "normal",
+ },
+ },
+ xAxis: { show: false },
+ yAxis: { show: false },
+ };
+ this.barChart.setOption(emptyOption);
+ return;
+ }
+
+ const yAxisName =
+ chartType === "satisfactionType" ? "濉姤姣斾緥 (%)" : "濉姤姣斾緥 (%)";
+ const tooltipFormatter =
+ chartType === "satisfactionType"
+ ? this.getSatisfactionTypeTooltipFormatter
+ : this.getDimensionTooltipFormatter;
const option = {
title: {
@@ -868,28 +1451,7 @@
axisPointer: {
type: "shadow",
},
- formatter: (params) => {
- const data = params[0];
- return `
- <div style="margin-bottom: 5px; font-weight: bold; color: #333;">
- ${data.name}
- </div>
- <div style="margin: 2px 0;">
- <span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:${
- data.color
- };margin-right:5px;"></span>
- 濉姤姣斾緥: <strong>${data.value.toFixed(1)}%</strong>
- </div>
- <div style="margin: 2px 0;">
- <span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:#eee;margin-right:5px;"></span>
- 鍙戦�侀棶鍗�: <strong>${data.data.sendCount.toLocaleString()}</strong>
- </div>
- <div style="margin: 2px 0;">
- <span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:#eee;margin-right:5px;"></span>
- 鍥炴敹闂嵎: <strong>${data.data.receiveCount.toLocaleString()}</strong>
- </div>
- `;
- },
+ formatter: tooltipFormatter,
},
grid: {
left: "3%",
@@ -900,7 +1462,7 @@
},
xAxis: {
type: "category",
- data: chartData.data.map((item) => item.name),
+ data: chartData.map((item) => item.name),
axisLabel: {
interval: 0,
rotate: 0,
@@ -918,7 +1480,7 @@
},
yAxis: {
type: "value",
- name: "濉姤姣斾緥 (%)",
+ name: yAxisName,
min: 0,
max: 100,
axisLabel: {
@@ -942,7 +1504,7 @@
name: "濉姤姣斾緥",
type: "bar",
barWidth: 40,
- data: chartData.data,
+ data: chartData,
itemStyle: {
color: (params) => {
return params.data.itemStyle.color;
@@ -962,19 +1524,218 @@
this.barChart.setOption(option);
},
+ // 婊℃剰搴︾被鍨媡ooltip鏍煎紡鍖�
+ getSatisfactionTypeTooltipFormatter(params) {
+ const data = params[0];
+ return `
+ <div style="margin-bottom: 5px; font-weight: bold; color: #333;">
+ ${data.name}
+ </div>
+ <div style="margin: 2px 0;">
+ <span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:${
+ data.color
+ };margin-right:5px;"></span>
+ 濉姤姣斾緥: <strong>${data.value}%</strong>
+ </div>
+ <div style="margin: 2px 0;">
+ <span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:#eee;margin-right:5px;"></span>
+ 鍙戦�侀棶鍗�: <strong>${data.data.sendCount.toLocaleString()}</strong>
+ </div>
+ <div style="margin: 2px 0;">
+ <span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:#eee;margin-right:5px;"></span>
+ 鍥炴敹闂嵎: <strong>${data.data.receiveCount.toLocaleString()}</strong>
+ </div>
+ <div style="margin: 2px 0;">
+ <span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:#eee;margin-right:5px;"></span>
+ 骞冲潎鍒�: <strong>${data.data.averageScore.toFixed(1)}</strong>
+ </div>
+ `;
+ },
+
+ // 缁村害tooltip鏍煎紡鍖�
+ getDimensionTooltipFormatter(params) {
+ const data = params[0];
+ return `
+ <div style="margin-bottom: 5px; font-weight: bold; color: #333;">
+ ${data.name}
+ </div>
+ <div style="margin: 2px 0;">
+ <span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:${
+ data.color
+ };margin-right:5px;"></span>
+ 濉姤姣斾緥: <strong>${data.value}%</strong>
+ </div>
+ <div style="margin: 2px 0;">
+ <span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:#eee;margin-right:5px;"></span>
+ 鍙戦�侀棶鍗�: <strong>${data.data.sendCount.toLocaleString()}</strong>
+ </div>
+ <div style="margin: 2px 0;">
+ <span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:#eee;margin-right:5px;"></span>
+ 鍥炴敹闂嵎: <strong>${data.data.receiveCount.toLocaleString()}</strong>
+ </div>
+ <div style="margin: 2px 0;">
+ <span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:#eee;margin-right:5px;"></span>
+ 骞冲潎鍒�: <strong>${data.data.averageScore.toFixed(1)}</strong>
+ </div>
+ <div style="margin: 2px 0;">
+ <span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:#eee;margin-right:5px;"></span>
+ 缁村害浠g爜: <strong>${data.data.dimension}</strong>
+ </div>
+ `;
+ },
+
+ // 鐢熸垚Mock鍥捐〃鏁版嵁
+ generateMockChartData() {
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ const data = this.satisfactionTypes.map((type, index) => ({
+ name: type.name,
+ recoveryRate: Math.random() * 0.3 + 0.6,
+ sendCount: Math.floor(Math.random() * 3000) + 1500,
+ receiveCount: 0,
+ color: type.color,
+ }));
+
+ data.forEach((item) => {
+ item.receiveCount = Math.floor(item.sendCount * item.recoveryRate);
+ });
+
+ this.totalSendCount = data.reduce(
+ (sum, item) => sum + item.sendCount,
+ 0
+ );
+ this.totalReceiveCount = data.reduce(
+ (sum, item) => sum + item.receiveCount,
+ 0
+ );
+ this.overallRecoveryRate =
+ this.totalSendCount > 0
+ ? this.totalReceiveCount / this.totalSendCount
+ : 0;
+
+ const chartData = data.map((item) => ({
+ name: item.name,
+ value: item.recoveryRate * 100,
+ sendCount: item.sendCount,
+ receiveCount: item.receiveCount,
+ averageScore: 4.2 + Math.random() * 0.8,
+ itemStyle: { color: item.color },
+ }));
+
+ this.chartData = chartData;
+ this.renderChart(chartData, "satisfactionType");
+ resolve();
+ }, 300);
+ });
+ },
+
+ // 鐢熸垚Mock缁村害鍥捐〃鏁版嵁
+ generateMockDimensionChartData() {
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ // 妯℃嫙缁村害鏁版嵁
+ const dimensionLabels = this.dict.type.dimensionality_type || [
+ { value: "1", label: "缁村害1" },
+ { value: "2", label: "缁村害2" },
+ { value: "3", label: "缁村害3" },
+ { value: "4", label: "缁村害4" },
+ { value: "5", label: "缁村害5" },
+ ];
+
+ const data = dimensionLabels.map((dim, index) => ({
+ name: dim.label,
+ recoveryRate: Math.random() * 0.3 + 0.6,
+ sendCount: Math.floor(Math.random() * 2000) + 1000,
+ receiveCount: 0,
+ averageScore: 3.5 + Math.random() * 1.5,
+ dimension: dim.value,
+ color: this.getChartColor(index),
+ }));
+
+ data.forEach((item) => {
+ item.receiveCount = Math.floor(item.sendCount * item.recoveryRate);
+ });
+
+ this.totalSendCount = data.reduce(
+ (sum, item) => sum + item.sendCount,
+ 0
+ );
+ this.totalReceiveCount = data.reduce(
+ (sum, item) => sum + item.receiveCount,
+ 0
+ );
+ this.overallRecoveryRate =
+ this.totalSendCount > 0
+ ? this.totalReceiveCount / this.totalSendCount
+ : 0;
+
+ const chartData = data.map((item) => ({
+ name: item.name,
+ value: item.recoveryRate * 100,
+ sendCount: item.sendCount,
+ receiveCount: item.receiveCount,
+ averageScore: item.averageScore,
+ dimension: item.dimension,
+ itemStyle: { color: item.color },
+ }));
+
+ this.chartData = chartData;
+ this.renderChart(chartData, "dimension");
+ resolve();
+ }, 300);
+ });
+ },
+
// 鐢熸垚Mock棰樼洰璇︽儏鏁版嵁
generateMockQuestionDetail() {
return new Promise((resolve) => {
setTimeout(() => {
const questions = [
{
- scriptContent: "鎮ㄥ鍖绘姢浜哄憳鐨勬湇鍔℃�佸害鏄惁婊℃剰",
+ scriptContent: "鎮ㄥ鏈灏卞尰鐨勬暣浣撴弧鎰忕▼搴︼紵",
scriptType: 1,
- totalCount: 156,
+ answerPerson: 120,
+ noAnswerPerson: 30,
+ answerCount: 120,
+ totalCount: 150,
+ averageScore: 4.2,
+ maxScore: 5.0,
+ minScore: 1.0,
+ answerRate: 0.8,
+ options: [
+ {
+ optionText: "闈炲父婊℃剰",
+ chosenQuantity: 60,
+ chosenPercentage: 0.5,
+ },
+ {
+ optionText: "婊℃剰",
+ chosenQuantity: 36,
+ chosenPercentage: 0.3,
+ },
+ {
+ optionText: "涓�鑸�",
+ chosenQuantity: 18,
+ chosenPercentage: 0.15,
+ },
+ {
+ optionText: "涓嶆弧鎰�",
+ chosenQuantity: 6,
+ chosenPercentage: 0.05,
+ },
+ ],
+ },
+ {
+ scriptContent: "鎮ㄥ鍖绘姢浜哄憳鐨勬湇鍔℃�佸害鏄惁婊℃剰锛�",
+ scriptType: 1,
+ answerPerson: 145,
+ noAnswerPerson: 11,
answerCount: 145,
+ totalCount: 156,
averageScore: 4.5,
maxScore: 5,
minScore: 3,
+ answerRate: 0.93,
options: [
{
optionText: "闈炲父婊℃剰",
@@ -1003,78 +1764,6 @@
},
],
},
- {
- scriptContent: "鎮ㄥ鍖荤敓鐨勮瘖鐤楁按骞冲拰鎶�鏈兘鍔涜瘎浠峰浣�",
- scriptType: 1,
- totalCount: 156,
- answerCount: 142,
- averageScore: 4.7,
- maxScore: 5,
- minScore: 3,
- options: [
- {
- optionText: "闈炲父涓撲笟",
- chosenQuantity: 95,
- chosenPercentage: 0.67,
- },
- {
- optionText: "姣旇緝涓撲笟",
- chosenQuantity: 40,
- chosenPercentage: 0.28,
- },
- {
- optionText: "涓�鑸�",
- chosenQuantity: 5,
- chosenPercentage: 0.04,
- },
- {
- optionText: "涓嶅涓撲笟",
- chosenQuantity: 2,
- chosenPercentage: 0.01,
- },
- {
- optionText: "闈炲父涓嶄笓涓�",
- chosenQuantity: 0,
- chosenPercentage: 0,
- },
- ],
- },
- {
- scriptContent: "鎮ㄥ鍖婚櫌鐨勭幆澧冨拰鍗敓鐘跺喌鏄惁婊℃剰",
- scriptType: 1,
- totalCount: 156,
- answerCount: 138,
- averageScore: 4.3,
- maxScore: 5,
- minScore: 2,
- options: [
- {
- optionText: "闈炲父婊℃剰",
- chosenQuantity: 75,
- chosenPercentage: 0.54,
- },
- {
- optionText: "婊℃剰",
- chosenQuantity: 50,
- chosenPercentage: 0.36,
- },
- {
- optionText: "涓�鑸�",
- chosenQuantity: 10,
- chosenPercentage: 0.07,
- },
- {
- optionText: "涓嶆弧鎰�",
- chosenQuantity: 3,
- chosenPercentage: 0.02,
- },
- {
- optionText: "闈炲父涓嶆弧鎰�",
- chosenQuantity: 0,
- chosenPercentage: 0,
- },
- ],
- },
];
const startIndex =
@@ -1091,11 +1780,115 @@
});
},
+ // 鐢熸垚Mock缁村害璇︽儏鏁版嵁
+ generateMockDimensionDetail() {
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ const questions = [
+ {
+ scriptContent: "鍖绘姢浜哄憳鏈嶅姟鎬佸害",
+ dimension: "1",
+ dimensionName: "鏈嶅姟鎬佸害",
+ scriptType: 1,
+ answerPerson: 120,
+ noAnswerPerson: 30,
+ answerCount: 120,
+ totalCount: 150,
+ averageScore: 4.2,
+ maxScore: 5.0,
+ minScore: 1.0,
+ answerRate: 0.8,
+ options: [
+ {
+ optionText: "闈炲父婊℃剰",
+ chosenQuantity: 60,
+ chosenPercentage: 0.5,
+ },
+ {
+ optionText: "婊℃剰",
+ chosenQuantity: 36,
+ chosenPercentage: 0.3,
+ },
+ {
+ optionText: "涓�鑸�",
+ chosenQuantity: 18,
+ chosenPercentage: 0.15,
+ },
+ ],
+ },
+ {
+ scriptContent: "鍖荤枟鎶�鏈按骞�",
+ dimension: "2",
+ dimensionName: "鎶�鏈按骞�",
+ scriptType: 1,
+ answerPerson: 145,
+ noAnswerPerson: 11,
+ answerCount: 145,
+ totalCount: 156,
+ averageScore: 4.5,
+ maxScore: 5,
+ minScore: 3,
+ answerRate: 0.93,
+ options: [
+ {
+ optionText: "闈炲父婊℃剰",
+ chosenQuantity: 89,
+ chosenPercentage: 0.61,
+ },
+ {
+ optionText: "婊℃剰",
+ chosenQuantity: 45,
+ chosenPercentage: 0.31,
+ },
+ {
+ optionText: "涓�鑸�",
+ chosenQuantity: 8,
+ chosenPercentage: 0.06,
+ },
+ ],
+ },
+ {
+ scriptContent: "灏卞尰鐜璁炬柦",
+ dimension: "3",
+ dimensionName: "鐜璁炬柦",
+ scriptType: 1,
+ answerPerson: 98,
+ noAnswerPerson: 22,
+ answerCount: 98,
+ totalCount: 120,
+ averageScore: 4.0,
+ maxScore: 5,
+ minScore: 2,
+ answerRate: 0.82,
+ options: [
+ {
+ optionText: "闈炲父婊℃剰",
+ chosenQuantity: 45,
+ chosenPercentage: 0.46,
+ },
+ {
+ optionText: "婊℃剰",
+ chosenQuantity: 40,
+ chosenPercentage: 0.41,
+ },
+ {
+ optionText: "涓�鑸�",
+ chosenQuantity: 10,
+ chosenPercentage: 0.1,
+ },
+ ],
+ },
+ ];
+
+ resolve(questions);
+ }, 300);
+ });
+ },
+
// 鐢熸垚Mock绫诲瀷鏄庣粏鏁版嵁
generateMockTypeDetail() {
return new Promise((resolve) => {
setTimeout(() => {
- // 鍦� generateMockTypeDetail 鏂规硶涓浛鎹负锛�
const types = [
{
id: 401,
@@ -1156,6 +1949,25 @@
});
},
+ // 鑾峰彇鍥捐〃棰滆壊
+ getChartColor(index) {
+ const colors = [
+ "#36B37E",
+ "#4CAF50",
+ "#409EFF",
+ "#FF9D4D",
+ "#9B8DFF",
+ "#FF6B6B",
+ "#66C2A5",
+ "#FC8D62",
+ "#8DA0CB",
+ "#E78AC3",
+ "#A6D854",
+ "#FFD92F",
+ ];
+ return colors[index % colors.length];
+ },
+
// 澶勭悊鍥捐〃鍝嶅簲寮�
handleChartResize() {
if (this.barChart) {
@@ -1163,24 +1975,53 @@
}
},
+ // 澶勭悊鍥捐〃Tab鍒囨崲
+ handleChartTabClick(tab) {
+ this.activeChartTab = tab.name;
+ this.loadChartData();
+ },
+
// 澶勭悊鏌ヨ
handleSearch() {
this.detailQueryParams.pageNum = 1;
+ this.dimensionQueryParams.pageNum = 1;
this.loadData();
+ // 寮哄埗閲嶆柊娓叉煋鍥捐〃
+ setTimeout(() => {
+ if (this.chartData.length === 0) {
+ this.renderChart([], this.activeChartTab);
+ }
+ }, 100);
},
// 澶勭悊閲嶇疆
handleReset() {
this.$refs.queryForm.resetFields();
this.queryParams.dateRange = [];
+ this.queryParams.deptCodes = []; // 閲嶇疆涓烘暟缁�
+ this.queryParams.wardCodes = []; // 閲嶇疆涓烘暟缁�
this.detailQueryParams.pageNum = 1;
+ this.dimensionQueryParams.pageNum = 1;
this.loadData();
},
// 澶勭悊Tab鍒囨崲
handleTabClick(tab) {
- if (tab.name === "typeDetail" && this.typeDetailData.length === 0) {
+ if (
+ tab.name === "dimensionDetail" &&
+ this.dimensionDetailData.length === 0
+ ) {
+ this.loadDimensionDetailData();
+ } else if (
+ tab.name === "typeDetail" &&
+ this.typeDetailData.length === 0
+ ) {
this.loadTypeDetailData();
+ } else if (
+ tab.name === "questionDetail" &&
+ this.questionDetailData.length === 0
+ ) {
+ this.loadQuestionDetailData();
}
},
@@ -1197,16 +2038,27 @@
this.loadQuestionDetailData();
},
+ // 澶勭悊缁村害鏄庣粏鍒嗛〉澶у皬鍙樺寲
+ handleDimensionSizeChange(size) {
+ this.dimensionQueryParams.pageSize = size;
+ this.dimensionQueryParams.pageNum = 1;
+ this.loadDimensionDetailData();
+ },
+
+ // 澶勭悊缁村害鏄庣粏椤电爜鍙樺寲
+ handleDimensionPageChange(page) {
+ this.dimensionQueryParams.pageNum = page;
+ this.loadDimensionDetailData();
+ },
+
// 澶勭悊绫诲瀷璇︽儏
handleTypeDetail(row) {
this.$message.info(`鏌ョ湅绫诲瀷璇︽儏锛�${row.typeName}`);
- // 杩欓噷鍙互璺宠浆鍒拌鎯呴〉闈㈡垨鎵撳紑璇︽儏瀵硅瘽妗�
},
// 澶勭悊瀵煎嚭鏁版嵁
handleExportData(row) {
this.$message.success(`姝e湪瀵煎嚭 ${row.typeName} 鏁版嵁...`);
- // 杩欓噷鍙互瀹炵幇瀵煎嚭閫昏緫
},
// 鏍煎紡鍖栫櫨鍒嗘瘮
@@ -1214,7 +2066,9 @@
if (value === null || value === undefined) return "-";
const num = parseFloat(value);
if (isNaN(num)) return "-";
- return `${(num * 100).toFixed(2)}%`;
+ // 濡傛灉鍊煎皬浜�1锛岃涓烘槸灏忔暟姣斾緥锛岄渶瑕佷箻浠�100
+ const percentValue = num < 1 ? num * 100 : num;
+ return `${percentValue.toFixed(2)}%`;
},
// 鑾峰彇鍥炴敹鐜囨牱寮忕被
@@ -1231,9 +2085,19 @@
鑹ソ: "primary",
涓�鑸�: "warning",
杈冨樊: "danger",
- 宸�: "info",
+ 鏈煡: "info",
};
return levelMap[level] || "info";
+ },
+
+ // 澶勭悊绉戝閫夋嫨鍙樺寲
+ handleDeptChange() {
+ this.loadData();
+ },
+
+ // 澶勭悊鐥呭尯閫夋嫨鍙樺寲
+ handleWardChange() {
+ this.loadData();
},
},
};
@@ -1307,6 +2171,14 @@
}
}
}
+
+ .chart-tabs {
+ margin-bottom: 20px;
+
+ ::v-deep .el-tabs__header {
+ margin-bottom: 0;
+ }
+ }
}
.tab-section {
@@ -1319,7 +2191,8 @@
}
}
- .detail-table-section {
+ .detail-table-section,
+ .dimension-detail-section {
.option-detail {
padding: 15px;
background: #f8f9fa;
@@ -1339,7 +2212,8 @@
padding: 12px 0;
}
- .question-row {
+ .question-row,
+ .dimension-row {
td {
background-color: #fff;
}
@@ -1358,19 +2232,22 @@
font-size: 16px;
}
- .summary-row {
+ .summary-row,
+ .dimension-summary-row {
margin-top: 20px;
padding: 20px;
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
border-radius: 8px;
border: 1px solid #dee2e6;
- .summary-content {
+ .summary-content,
+ .dimension-summary-content {
display: flex;
justify-content: space-around;
align-items: center;
- .summary-item {
+ .summary-item,
+ .dimension-summary-item {
text-align: center;
.label {
@@ -1442,24 +2319,6 @@
color: #409eff;
font-size: 15px;
}
-
- .trend-cell {
- display: flex;
- align-items: center;
- justify-content: center;
- gap: 5px;
-
- .trend-up,
- .trend-down,
- .trend-stable {
- font-size: 16px;
- }
-
- .trend-text {
- font-size: 13px;
- color: #666;
- }
- }
}
.type-summary-row {
@@ -1521,7 +2380,13 @@
}
}
}
-
+/* 纭繚澶氶�変笅鎷夋鏍峰紡姝g‘ */
+::v-deep .el-select__tags {
+ max-width: 200px;
+ .el-tag {
+ margin: 2px 0 2px 6px;
+ }
+}
@media (max-width: 768px) {
.satisfaction-statistics {
padding: 10px;
@@ -1553,8 +2418,10 @@
}
}
- .detail-table-section {
- .summary-content {
+ .detail-table-section,
+ .dimension-detail-section {
+ .summary-content,
+ .dimension-summary-content {
flex-direction: column;
gap: 15px;
}
--
Gitblit v1.9.3