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