From 03348941a9c44e3b9706a3b6c25c8fb5ba25d9d5 Mon Sep 17 00:00:00 2001
From: WXL (wul) <wl_5969728@163.com>
Date: 星期一, 30 三月 2026 09:15:28 +0800
Subject: [PATCH] 测试完成

---
 src/views/Satisfaction/sfstatistics/components/SatisfactionStatistics.vue | 1789 +++++++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 1,185 insertions(+), 604 deletions(-)

diff --git a/src/views/Satisfaction/sfstatistics/components/SatisfactionStatistics.vue b/src/views/Satisfaction/sfstatistics/components/SatisfactionStatistics.vue
index 678ecfd..a6463e6 100644
--- a/src/views/Satisfaction/sfstatistics/components/SatisfactionStatistics.vue
+++ b/src/views/Satisfaction/sfstatistics/components/SatisfactionStatistics.vue
@@ -1,293 +1,566 @@
 <template>
   <div class="satisfaction-statistics">
+    <!-- 鏌ヨ鏉′欢鍖哄煙 -->
     <div class="query-section">
-      <el-form
-        :model="queryParams"
-        ref="queryForm"
-        size="medium"
-        :inline="true"
-        label-width="100px"
-        class="query-form"
-      >
-        <el-form-item label="鎮h�呮潵婧�" prop="patientSource">
-          <el-select
-            v-model="queryParams.patientSource"
-            placeholder="璇烽�夋嫨鎮h�呮潵婧�"
-            clearable
-            style="width: 200px"
-          >
-            <el-option
-              v-for="source in patientSourceList"
-              :key="source.value"
-              :label="source.label"
-              :value="source.value"
-            />
-          </el-select>
-        </el-form-item>
-
-        <el-form-item label="绉戝" prop="deptCode">
-          <el-select
-            v-model="queryParams.deptCode"
-            placeholder="璇烽�夋嫨绉戝"
-            clearable
-            filterable
-            style="width: 200px"
-          >
-            <el-option
-              v-for="dept in deptList"
-              :key="dept.value"
-              :label="dept.label"
-              :value="dept.value"
-            />
-          </el-select>
-        </el-form-item>
-
-        <el-form-item label="鐥呭尯" prop="wardCode">
-          <el-select
-            v-model="queryParams.wardCode"
-            placeholder="璇烽�夋嫨鐥呭尯"
-            clearable
-            filterable
-            style="width: 200px"
-          >
-            <el-option
-              v-for="ward in wardList"
-              :key="ward.value"
-              :label="ward.label"
-              :value="ward.value"
-            />
-          </el-select>
-        </el-form-item>
-
-        <el-form-item label="缁熻鏃堕棿" prop="dateRange">
-          <el-date-picker
-            v-model="queryParams.dateRange"
-            type="daterange"
-            range-separator="鑷�"
-            start-placeholder="寮�濮嬫棩鏈�"
-            end-placeholder="缁撴潫鏃ユ湡"
-            value-format="yyyy-MM-dd"
-            :picker-options="pickerOptions"
-            style="width: 380px"
-          />
-        </el-form-item>
-
-        <el-form-item>
-          <el-button
-            type="primary"
-            icon="el-icon-search"
-            @click="handleSearch"
-            :loading="loading"
-          >
-            鏌ヨ
-          </el-button>
-          <el-button icon="el-icon-refresh" @click="handleReset">
-            閲嶇疆
-          </el-button>
-        </el-form-item>
-      </el-form>
-    </div>
-
-    <!-- 婊℃剰搴﹀垎绫荤粺璁″浘琛� -->
-    <div class="chart-section">
-      <div class="chart-container">
-        <div class="chart-title">婊℃剰搴︾被鍨嬬粺璁�</div>
-        <div id="satisfactionBarChart" style="width: 100%; height: 400px"></div>
-      </div>
-    </div>
-
-    <!-- 棰樼洰鏄庣粏琛ㄦ牸 -->
-    <div class="detail-table-section">
-      <div class="section-title">棰樼洰鏄庣粏缁熻</div>
-
-      <el-table
-        v-loading="detailLoading"
-        :data="questionDetailData"
-        :border="true"
-        style="width: 100%"
-        row-class-name="question-row"
-      >
-        <el-table-column
-          type="expand"
-          width="60"
+      <el-card shadow="never">
+        <el-form
+          :model="queryParams"
+          ref="queryForm"
+          size="medium"
+          :inline="true"
+          label-width="100px"
+          class="query-form"
         >
-          <template slot-scope="{ row }">
-            <div class="option-detail">
+          <el-form-item label="鎮h�呮潵婧�" prop="patientSource">
+            <el-select
+              v-model="queryParams.patientSource"
+              placeholder="璇烽�夋嫨鎮h�呮潵婧�"
+              clearable
+              style="width: 200px"
+            >
+              <el-option
+                v-for="source in patientSourceList"
+                :key="source.value"
+                :label="source.label"
+                :value="source.value"
+              />
+            </el-select>
+          </el-form-item>
+
+          <el-form-item label="绉戝" prop="deptCode">
+            <el-select
+              v-model="queryParams.deptCode"
+              placeholder="璇烽�夋嫨绉戝"
+              clearable
+              filterable
+              style="width: 200px"
+            >
+              <el-option
+                v-for="dept in deptList"
+                :key="dept.value"
+                :label="dept.label"
+                :value="dept.value"
+              />
+            </el-select>
+          </el-form-item>
+
+          <el-form-item label="鐥呭尯" prop="wardCode">
+            <el-select
+              v-model="queryParams.wardCode"
+              placeholder="璇烽�夋嫨鐥呭尯"
+              clearable
+              filterable
+              style="width: 200px"
+            >
+              <el-option
+                v-for="ward in wardList"
+                :key="ward.value"
+                :label="ward.label"
+                :value="ward.value"
+              />
+            </el-select>
+          </el-form-item>
+
+          <el-form-item label="缁熻鏃堕棿" prop="dateRange">
+            <el-date-picker
+              v-model="queryParams.dateRange"
+              type="daterange"
+              range-separator="鑷�"
+              start-placeholder="寮�濮嬫棩鏈�"
+              end-placeholder="缁撴潫鏃ユ湡"
+              value-format="yyyy-MM-dd"
+              :picker-options="pickerOptions"
+              style="width: 380px"
+            />
+          </el-form-item>
+
+          <el-form-item>
+            <el-button
+              type="primary"
+              icon="el-icon-search"
+              @click="handleSearch"
+              :loading="loading"
+            >
+              鏌ヨ
+            </el-button>
+            <el-button icon="el-icon-refresh" @click="handleReset">
+              閲嶇疆
+            </el-button>
+          </el-form-item>
+        </el-form>
+      </el-card>
+    </div>
+
+    <!-- 婊℃剰搴︾被鍨嬬粺璁″浘琛� -->
+    <div class="chart-section">
+      <el-card shadow="never">
+        <div class="chart-container">
+          <div class="chart-header">
+            <h3 class="chart-title">婊℃剰搴︾被鍨嬪~鎶ユ瘮渚嬬粺璁�</h3>
+            <div class="statistic-info">
+              <div class="statistic-item">
+                <span class="statistic-label">鍙戦�侀棶鍗锋�婚噺锛�</span>
+                <span class="statistic-value">{{
+                  totalSendCount.toLocaleString()
+                }}</span>
+              </div>
+              <div class="statistic-item">
+                <span class="statistic-label">鍥炴敹闂嵎鎬婚噺锛�</span>
+                <span class="statistic-value">{{
+                  totalReceiveCount.toLocaleString()
+                }}</span>
+              </div>
+              <div class="statistic-item">
+                <span class="statistic-label">鎬讳綋鍥炴敹鐜囷細</span>
+                <span class="statistic-value">{{
+                  formatPercent(overallRecoveryRate)
+                }}</span>
+              </div>
+            </div>
+          </div>
+          <div
+            id="satisfactionBarChart"
+            style="width: 100%; height: 400px"
+          ></div>
+        </div>
+      </el-card>
+    </div>
+
+    <!-- Tab鏍囩椤� -->
+    <div class="tab-section">
+      <el-card shadow="never">
+        <el-tabs v-model="activeTab" @tab-click="handleTabClick">
+          <el-tab-pane label="棰樼洰鏄庣粏缁熻" name="questionDetail">
+            <!-- 棰樼洰鏄庣粏琛ㄦ牸 -->
+            <div class="detail-table-section">
               <el-table
-                :data="row.options"
+                v-loading="detailLoading"
+                :data="questionDetailData"
                 :border="true"
                 style="width: 100%"
-                class="inner-table"
+                row-class-name="question-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="閫夐」"
-                  prop="optionText"
+                  label="搴忓彿"
+                  type="index"
                   align="center"
-                  min-width="200"
+                  width="60"
                 />
+
                 <el-table-column
-                  label="閫夋嫨浜烘暟"
-                  prop="chosenQuantity"
+                  label="棰樼洰"
+                  prop="scriptContent"
                   align="center"
-                  min-width="120"
-                />
-                <el-table-column
-                  label="閫夋嫨姣斾緥"
-                  prop="chosenPercentage"
-                  align="center"
-                  min-width="120"
+                  min-width="300"
                 >
-                  <template slot-scope="{ row: option }">
-                    {{ formatPercent(option.chosenPercentage) }}
+                  <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="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="answerCount"
+                  align="center"
+                  width="100"
+                />
+
+                <el-table-column
+                  label="鏈瓟棰樹汉鏁�"
+                  prop="unanswerCount"
+                  align="center"
+                  width="100"
+                >
+                  <template slot-scope="{ row }">
+                    {{ row.totalCount - row.answerCount }}
+                  </template>
+                </el-table-column>
+
+                <el-table-column
+                  label="绛旈鐜�"
+                  prop="answerRate"
+                  align="center"
+                  width="100"
+                >
+                  <template slot-scope="{ row }">
+                    {{ formatPercent(row.answerCount / row.totalCount) }}
                   </template>
                 </el-table-column>
               </el-table>
+
+              <!-- 缁煎悎寰楀垎琛� -->
+              <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>
+                  </div>
+                  <div class="summary-item">
+                    <span class="label">鎬荤瓟棰樼巼锛�</span>
+                    <span class="value">{{
+                      formatPercent(totalAnswerRate)
+                    }}</span>
+                  </div>
+                </div>
+              </div>
+
+              <!-- 鍒嗛〉 -->
+              <div
+                class="pagination-section"
+                v-if="questionDetailData.length > 0"
+              >
+                <el-pagination
+                  background
+                  layout="total, sizes, prev, pager, next, jumper"
+                  :current-page="detailQueryParams.pageNum"
+                  :page-size="detailQueryParams.pageSize"
+                  :page-sizes="[10, 20, 30]"
+                  :total="detailTotal"
+                  @size-change="handleDetailSizeChange"
+                  @current-change="handleDetailPageChange"
+                />
+              </div>
             </div>
-          </template>
-        </el-table-column>
+          </el-tab-pane>
 
-        <el-table-column
-          label="搴忓彿"
-          type="index"
-          align="center"
-          width="60"
-        />
+          <el-tab-pane label="鍚勭被鍨嬬粺璁℃槑缁�" name="typeDetail">
+            <!-- 鍚勭被鍨嬬粺璁℃槑缁嗚〃鏍� -->
+            <div class="type-detail-section">
+              <el-table
+                v-loading="typeDetailLoading"
+                :data="typeDetailData"
+                :border="true"
+                style="width: 100%"
+                class="type-detail-table"
+              >
+                <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="typeName"
+                  align="center"
+                  min-width="150"
+                >
+                  <template slot-scope="{ row }">
+                    <div class="type-name-cell">
+                      <span class="type-name">{{ row.typeName }}</span>
+                      <el-tag
+                        v-if="row.isSpecial"
+                        type="warning"
+                        size="mini"
+                        style="margin-left: 5px"
+                      >
+                        鐗规畩
+                      </el-tag>
+                    </div>
+                  </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="sendCount"
+                  align="center"
+                  width="120"
+                >
+                  <template slot-scope="{ row }">
+                    <span class="number-text">{{
+                      row.sendCount.toLocaleString()
+                    }}</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="receiveCount"
+                  align="center"
+                  width="120"
+                >
+                  <template slot-scope="{ row }">
+                    <span class="number-text">{{
+                      row.receiveCount.toLocaleString()
+                    }}</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="recoveryRate"
+                  align="center"
+                  width="120"
+                >
+                  <template slot-scope="{ row }">
+                    <span
+                      class="rate-text"
+                      :class="getRateClass(row.recoveryRate)"
+                    >
+                      {{ formatPercent(row.recoveryRate) }}
+                    </span>
+                  </template>
+                </el-table-column>
 
-        <el-table-column
-          label="绛旈浜烘暟"
-          prop="answerCount"
-          align="center"
-          width="100"
-        />
+                <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="unanswerCount"
-          align="center"
-          width="100"
-        >
-          <template slot-scope="{ row }">
-            {{ row.totalCount - row.answerCount }}
-          </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="answerRate"
-          align="center"
-          width="100"
-        >
-          <template slot-scope="{ row }">
-            {{ formatPercent(row.answerCount / row.totalCount) }}
-          </template>
-        </el-table-column>
-      </el-table>
+                <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>
 
-      <!-- 缁煎悎寰楀垎琛� -->
-      <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>
-          </div>
-          <div class="summary-item">
-            <span class="label">鎬荤瓟棰樼巼锛�</span>
-            <span class="value">{{ formatPercent(totalAnswerRate) }}</span>
-          </div>
-        </div>
-      </div>
-    </div>
+                <el-table-column
+                  label="婊℃剰搴︾瓑绾�"
+                  prop="satisfactionLevel"
+                  align="center"
+                  width="120"
+                >
+                  <template slot-scope="{ row }">
+                    <el-tag
+                      :type="getLevelTagType(row.satisfactionLevel)"
+                      effect="dark"
+                      size="small"
+                    >
+                      {{ row.satisfactionLevel }}
+                    </el-tag>
+                  </template>
+                </el-table-column>
 
-    <!-- 鍒嗛〉 -->
-    <div class="pagination-section" v-if="questionDetailData.length > 0">
-      <el-pagination
-        background
-        layout="total, sizes, prev, pager, next, jumper"
-        :current-page="detailQueryParams.pageNum"
-        :page-size="detailQueryParams.pageSize"
-        :page-sizes="[10, 20, 30]"
-        :total="detailTotal"
-        @size-change="handleDetailSizeChange"
-        @current-change="handleDetailPageChange"
-      />
+                <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>
+
+                <el-table-column
+                  label="鎿嶄綔"
+                  align="center"
+                  width="120"
+                  fixed="right"
+                >
+                  <template slot-scope="{ row }">
+                    <el-button
+                      type="text"
+                      size="small"
+                      @click="handleTypeDetail(row)"
+                    >
+                      璇︽儏
+                    </el-button>
+                    <el-button
+                      type="text"
+                      size="small"
+                      @click="handleExportData(row)"
+                    >
+                      瀵煎嚭
+                    </el-button>
+                  </template>
+                </el-table-column>
+              </el-table>
+
+              <!-- 绫诲瀷缁熻姹囨�� -->
+              <div class="type-summary-row">
+                <div class="type-summary-content">
+                  <div class="type-summary-item">
+                    <span class="label">绫诲瀷鎬绘暟锛�</span>
+                    <span class="value">{{ typeDetailData.length }}</span>
+                  </div>
+                  <div class="type-summary-item">
+                    <span class="label">骞冲潎鍥炴敹鐜囷細</span>
+                    <span class="value">{{
+                      formatPercent(averageRecoveryRate)
+                    }}</span>
+                  </div>
+                  <div class="type-summary-item">
+                    <span class="label">绫诲瀷骞冲潎鍒嗭細</span>
+                    <span class="value">{{ averageTypeScore.toFixed(1) }}</span>
+                  </div>
+                  <div class="type-summary-item">
+                    <span class="label">楂樻弧鎰忓害绫诲瀷锛�</span>
+                    <span class="value high-count"
+                      >{{ highSatisfactionCount }} 涓�</span
+                    >
+                  </div>
+                </div>
+              </div>
+            </div>
+          </el-tab-pane>
+        </el-tabs>
+      </el-card>
     </div>
   </div>
 </template>
 
 <script>
+import * as echarts from "echarts";
+
 export default {
-  name: 'SatisfactionStatistics',
+  name: "SatisfactionStatistics",
   data() {
     return {
       // 鏌ヨ鍙傛暟
       queryParams: {
-        patientSource: '',
-        deptCode: '',
-        wardCode: '',
-        dateRange: []
+        patientSource: "",
+        deptCode: "",
+        wardCode: "",
+        dateRange: [],
       },
+
+      // 褰撳墠婵�娲荤殑tab
+      activeTab: "questionDetail",
 
       // 鎮h�呮潵婧愰�夐」
       patientSourceList: [
-        { value: '1', label: '闂ㄨ瘖' },
-        { value: '2', label: '浣忛櫌' },
-        { value: '3', label: '鎬ヨ瘖' },
-        { value: '4', label: '浣撴' }
+        { value: "1", label: "闂ㄨ瘖" },
+        { value: "2", label: "浣忛櫌" },
+        { value: "3", label: "鎬ヨ瘖" },
+        { value: "4", label: "鍑洪櫌" },
       ],
 
       // 绉戝鍒楄〃
@@ -302,6 +575,7 @@
       // 鍔犺浇鐘舵��
       loading: false,
       detailLoading: false,
+      typeDetailLoading: false,
 
       // 棰樼洰鏄庣粏鏁版嵁
       questionDetailData: [],
@@ -309,7 +583,7 @@
       // 棰樼洰鏄庣粏鏌ヨ鍙傛暟
       detailQueryParams: {
         pageNum: 1,
-        pageSize: 10
+        pageSize: 10,
       },
 
       // 棰樼洰鏄庣粏鎬绘暟
@@ -320,58 +594,67 @@
       totalAnswerCount: 0,
       totalAnswerRate: 0,
 
+      // 鍚勭被鍨嬬粺璁℃槑缁嗘暟鎹�
+      typeDetailData: [],
+
+      // 缁熻淇℃伅
+      totalSendCount: 12560,
+      totalReceiveCount: 10240,
+      overallRecoveryRate: 0,
+
+      // 绫诲瀷缁熻姹囨��
+      averageRecoveryRate: 0,
+      averageTypeScore: 0,
+      highSatisfactionCount: 0,
+
       // 鏃ユ湡閫夋嫨鍣ㄩ�夐」
       pickerOptions: {
         shortcuts: [
           {
-            text: '鏈�杩戜竴鍛�',
+            text: "鏈�杩戜竴鍛�",
             onClick(picker) {
               const end = new Date();
               const start = new Date();
               start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
-              picker.$emit('pick', [start, end]);
-            }
+              picker.$emit("pick", [start, end]);
+            },
           },
           {
-            text: '鏈�杩戜竴涓湀',
+            text: "鏈�杩戜竴涓湀",
             onClick(picker) {
               const end = new Date();
               const start = new Date();
               start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
-              picker.$emit('pick', [start, end]);
-            }
+              picker.$emit("pick", [start, end]);
+            },
           },
           {
-            text: '鏈�杩戜笁涓湀',
+            text: "鏈�杩戜笁涓湀",
             onClick(picker) {
               const end = new Date();
               const start = new Date();
               start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
-              picker.$emit('pick', [start, end]);
-            }
-          }
+              picker.$emit("pick", [start, end]);
+            },
+          },
         ],
         disabledDate(time) {
           return time.getTime() > Date.now();
-        }
+        },
       },
 
-      // Mock鏁版嵁 - 婊℃剰搴﹀垎绫�
-      mockSatisfactionCategories: ['鏈嶅姟鎬佸害', '鎶�鏈按骞�', '鐜璁炬柦', '娌熼�氭晥鏋�', '绛夊緟鏃堕棿', '鏀惰垂鍚堢悊鎬�'],
-      // Mock鏁版嵁 - 婊℃剰搴︾被鍨�
-      mockSatisfactionTypes: [
-        { name: '闈炲父婊℃剰', value: 85, color: '#36B37E' },
-        { name: '婊℃剰', value: 72, color: '#4CAF50' },
-        { name: '涓�鑸�', value: 60, color: '#FF9D4D' },
-        { name: '涓嶆弧鎰�', value: 15, color: '#FF5C5C' },
-        { name: '闈炲父涓嶆弧鎰�', value: 5, color: '#F44336' }
-      ]
+      // 婊℃剰搴︾被鍨嬫暟鎹�
+      satisfactionTypes: [
+        { id: 401, name: "鍑洪櫌婊℃剰搴�", color: "#36B37E" },
+        { id: 402, name: "浣忛櫌婊℃剰搴�", color: "#4CAF50" },
+        { id: 403, name: "闂ㄨ瘖婊℃剰搴�", color: "#409EFF" },
+        { id: 404, name: "甯哥敤婊℃剰搴�", color: "#FF9D4D" },
+      ],
     };
   },
 
   mounted() {
     this.initData();
-    this.initChart();
   },
 
   beforeDestroy() {
@@ -386,21 +669,21 @@
     async initData() {
       await this.getDeptList();
       await this.getWardList();
+      this.initChart();
       await this.loadData();
     },
 
     // 鑾峰彇绉戝鍒楄〃
     getDeptList() {
-      // 妯℃嫙API璋冪敤鑾峰彇绉戝鍒楄〃
       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: '鍎跨' }
+            { value: "dept001", label: "蹇冭绠″唴绉�" },
+            { value: "dept002", label: "绁炵粡鍐呯" },
+            { value: "dept003", label: "鏅绉�" },
+            { value: "dept004", label: "楠ㄧ" },
+            { value: "dept005", label: "濡囦骇绉�" },
+            { value: "dept006", label: "鍎跨" },
           ];
           resolve();
         }, 100);
@@ -409,16 +692,15 @@
 
     // 鑾峰彇鐥呭尯鍒楄〃
     getWardList() {
-      // 妯℃嫙API璋冪敤鑾峰彇鐥呭尯鍒楄〃
       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: '鍎跨鐥呭尯' }
+            { value: "ward001", label: "鍐呯涓�鐥呭尯" },
+            { value: "ward002", label: "鍐呯浜岀梾鍖�" },
+            { value: "ward003", label: "澶栫涓�鐥呭尯" },
+            { value: "ward004", label: "澶栫浜岀梾鍖�" },
+            { value: "ward005", label: "濡囦骇绉戠梾鍖�" },
+            { value: "ward006", label: "鍎跨鐥呭尯" },
           ];
           resolve();
         }, 100);
@@ -429,37 +711,51 @@
     async loadData() {
       await Promise.all([
         this.loadChartData(),
-        this.loadQuestionDetailData()
+        this.loadQuestionDetailData(),
+        this.loadTypeDetailData(),
       ]);
     },
 
     // 鍔犺浇鍥捐〃鏁版嵁
-    loadChartData() {
+    async loadChartData() {
       this.loading = true;
-      return new Promise((resolve) => {
-        setTimeout(() => {
-          this.renderChart(this.generateChartData());
-          this.loading = false;
-          resolve();
-        }, 500);
-      });
+      try {
+        // 妯℃嫙API璋冪敤
+        const chartData = await this.generateChartData();
+        this.renderChart(chartData);
+
+        // 璁$畻鎬讳綋鍥炴敹鐜�
+        this.overallRecoveryRate = this.totalReceiveCount / this.totalSendCount;
+      } finally {
+        this.loading = false;
+      }
     },
 
     // 鍔犺浇棰樼洰鏄庣粏鏁版嵁
-    loadQuestionDetailData() {
+    async loadQuestionDetailData() {
       this.detailLoading = true;
-      return new Promise((resolve) => {
-        setTimeout(() => {
-          const mockData = this.generateMockQuestionDetail();
-          this.questionDetailData = mockData.list;
-          this.detailTotal = mockData.total;
+      try {
+        const mockData = await this.generateMockQuestionDetail();
+        this.questionDetailData = mockData.list;
+        this.detailTotal = mockData.total;
+        this.calculateSummary(mockData);
+      } finally {
+        this.detailLoading = false;
+      }
+    },
 
-          // 璁$畻缁煎悎寰楀垎
-          this.calculateSummary(mockData);
-          this.detailLoading = false;
-          resolve();
-        }, 500);
-      });
+    // 鍔犺浇绫诲瀷鏄庣粏鏁版嵁
+    async loadTypeDetailData() {
+      this.typeDetailLoading = true;
+      try {
+        const mockData = await this.generateMockTypeDetail();
+        this.typeDetailData = mockData;
+
+        // 璁$畻绫诲瀷缁熻姹囨��
+        this.calculateTypeSummary(mockData);
+      } finally {
+        this.typeDetailLoading = false;
+      }
     },
 
     // 璁$畻缁煎悎寰楀垎
@@ -468,48 +764,94 @@
       let totalAnswerCount = 0;
       let totalCount = 0;
 
-      data.list.forEach(item => {
+      data.list.forEach((item) => {
         totalScore += item.averageScore;
         totalAnswerCount += item.answerCount;
         totalCount += item.totalCount;
       });
 
-      this.totalScore = data.list.length > 0 ? totalScore / data.list.length : 0;
+      this.totalScore =
+        data.list.length > 0 ? totalScore / data.list.length : 0;
       this.totalAnswerCount = totalAnswerCount;
       this.totalAnswerRate = totalCount > 0 ? totalAnswerCount / totalCount : 0;
     },
 
+    // 璁$畻绫诲瀷缁熻姹囨��
+    calculateTypeSummary(data) {
+      if (data.length === 0) {
+        this.averageRecoveryRate = 0;
+        this.averageTypeScore = 0;
+        this.highSatisfactionCount = 0;
+        return;
+      }
+
+      let totalRecoveryRate = 0;
+      let totalTypeScore = 0;
+      let highCount = 0;
+
+      data.forEach((item) => {
+        totalRecoveryRate += item.recoveryRate;
+        totalTypeScore += item.averageScore;
+        if (
+          item.satisfactionLevel === "浼樼" ||
+          item.satisfactionLevel === "鑹ソ"
+        ) {
+          highCount++;
+        }
+      });
+
+      this.averageRecoveryRate = totalRecoveryRate / data.length;
+      this.averageTypeScore = totalTypeScore / data.length;
+      this.highSatisfactionCount = highCount;
+    },
+
     // 鍒濆鍖栧浘琛�
     initChart() {
-      const echarts = require('echarts');
-      const chartDom = document.getElementById('satisfactionBarChart');
+      const chartDom = document.getElementById("satisfactionBarChart");
       if (!chartDom) return;
 
       this.barChart = echarts.init(chartDom);
-
-      // 鐩戝惉绐楀彛鍙樺寲
-      window.addEventListener('resize', this.handleChartResize);
+      window.addEventListener("resize", this.handleChartResize);
     },
 
     // 鐢熸垚鍥捐〃鏁版嵁
     generateChartData() {
-      const categories = this.mockSatisfactionCategories;
-      const series = this.mockSatisfactionTypes.map(type => ({
-        name: type.name,
-        type: 'bar',
-        barWidth: 25,
-        stack: '婊℃剰搴�',
-        data: categories.map(() => Math.floor(Math.random() * 20) + 10), // 闅忔満鏁版嵁
-        itemStyle: {
-          color: type.color
-        }
-      }));
+      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,
+          }));
 
-      return {
-        categories,
-        legend: this.mockSatisfactionTypes.map(type => type.name),
-        series
-      };
+          // 璁$畻鍥炴敹鏁伴噺
+          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);
+      });
     },
 
     // 娓叉煋鍥捐〃
@@ -518,92 +860,103 @@
 
       const option = {
         title: {
-          text: '婊℃剰搴︾被鍨嬬粺璁�',
-          left: 'center',
-          textStyle: {
-            fontSize: 16,
-            fontWeight: 'normal',
-            color: '#333'
-          }
+          text: "",
+          left: "center",
         },
         tooltip: {
-          trigger: 'axis',
+          trigger: "axis",
           axisPointer: {
-            type: 'shadow'
+            type: "shadow",
           },
           formatter: (params) => {
-            let result = `<div style="margin-bottom: 5px; font-weight: bold;">${params[0].name}</div>`;
-            let total = 0;
-
-            params.forEach(param => {
-              result += `<div style="margin: 2px 0;">
-                <span style="display:inline-block;width:10px;height:10px;border-radius:50%;background:${param.color};margin-right:5px;"></span>
-                ${param.seriesName}: <strong>${param.value}%</strong>
-              </div>`;
-              total += param.value;
-            });
-
-            result += `<div style="margin-top: 5px; padding-top: 5px; border-top: 1px solid #eee;">
-              <strong>鎬昏: ${total}%</strong>
-            </div>`;
-            return result;
-          }
-        },
-        legend: {
-          data: chartData.legend,
-          top: 20,
-          textStyle: {
-            fontSize: 12,
-            color: '#666'
-          }
+            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>
+            `;
+          },
         },
         grid: {
-          left: '3%',
-          right: '4%',
-          bottom: '3%',
-          top: 80,
-          containLabel: true
+          left: "3%",
+          right: "4%",
+          bottom: "3%",
+          top: 60,
+          containLabel: true,
         },
         xAxis: {
-          type: 'category',
-          data: chartData.categories,
+          type: "category",
+          data: chartData.data.map((item) => item.name),
           axisLabel: {
             interval: 0,
             rotate: 0,
             fontSize: 12,
-            color: '#666'
+            color: "#666",
           },
           axisLine: {
             lineStyle: {
-              color: '#DCDFE6'
-            }
+              color: "#DCDFE6",
+            },
           },
           axisTick: {
-            alignWithLabel: true
-          }
+            alignWithLabel: true,
+          },
         },
         yAxis: {
-          type: 'value',
-          name: '鐧惧垎姣� (%)',
+          type: "value",
+          name: "濉姤姣斾緥 (%)",
           min: 0,
           max: 100,
           axisLabel: {
-            formatter: '{value}%',
-            color: '#666'
+            formatter: "{value}%",
+            color: "#666",
           },
           axisLine: {
             lineStyle: {
-              color: '#DCDFE6'
-            }
+              color: "#DCDFE6",
+            },
           },
           splitLine: {
             lineStyle: {
-              type: 'dashed',
-              color: '#E4E7ED'
-            }
-          }
+              type: "dashed",
+              color: "#E4E7ED",
+            },
+          },
         },
-        series: chartData.series
+        series: [
+          {
+            name: "濉姤姣斾緥",
+            type: "bar",
+            barWidth: 40,
+            data: chartData.data,
+            itemStyle: {
+              color: (params) => {
+                return params.data.itemStyle.color;
+              },
+            },
+            label: {
+              show: true,
+              position: "top",
+              formatter: "{c}%",
+              fontSize: 12,
+              color: "#333",
+            },
+          },
+        ],
       };
 
       this.barChart.setOption(option);
@@ -611,180 +964,196 @@
 
     // 鐢熸垚Mock棰樼洰璇︽儏鏁版嵁
     generateMockQuestionDetail() {
-      const questions = [
-        {
-          scriptContent: '鎮ㄥ鍖绘姢浜哄憳鐨勬湇鍔℃�佸害鏄惁婊℃剰',
-          scriptType: 1, // 1: 鍗曢�夐, 2: 澶氶�夐
-          totalCount: 156,
-          answerCount: 145,
-          averageScore: 4.5,
-          maxScore: 5,
-          minScore: 3,
-          options: [
-            { optionText: '闈炲父婊℃剰', chosenQuantity: 89, chosenPercentage: 0.61 },
-            { optionText: '婊℃剰', chosenQuantity: 45, chosenPercentage: 0.31 },
-            { optionText: '涓�鑸�', chosenQuantity: 8, chosenPercentage: 0.06 },
-            { optionText: '涓嶆弧鎰�', chosenQuantity: 2, chosenPercentage: 0.01 },
-            { optionText: '闈炲父涓嶆弧鎰�', chosenQuantity: 1, chosenPercentage: 0.01 }
-          ]
-        },
-        {
-          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 }
-          ]
-        },
-        {
-          scriptContent: '鎮ㄨ涓哄尰鎶や汉鍛樹笌鎮ㄧ殑娌熼�氭槸鍚﹀厖鍒�',
-          scriptType: 1,
-          totalCount: 156,
-          answerCount: 140,
-          averageScore: 4.6,
-          maxScore: 5,
-          minScore: 3,
-          options: [
-            { optionText: '娌熼�氶潪甯稿厖鍒�', chosenQuantity: 85, chosenPercentage: 0.61 },
-            { optionText: '娌熼�氭瘮杈冨厖鍒�', chosenQuantity: 45, chosenPercentage: 0.32 },
-            { optionText: '娌熼�氫竴鑸�', chosenQuantity: 8, chosenPercentage: 0.06 },
-            { optionText: '娌熼�氫笉澶熷厖鍒�', chosenQuantity: 2, chosenPercentage: 0.01 },
-            { optionText: '娌熼�氶潪甯镐笉鍏呭垎', chosenQuantity: 0, chosenPercentage: 0 }
-          ]
-        },
-        {
-          scriptContent: '鎮ㄥ绛夊緟灏辫瘖鍜屾不鐤楃殑鏃堕棿鏄惁婊℃剰',
-          scriptType: 1,
-          totalCount: 156,
-          answerCount: 135,
-          averageScore: 4.0,
-          maxScore: 5,
-          minScore: 1,
-          options: [
-            { optionText: '绛夊緟鏃堕棿寰堢煭', chosenQuantity: 60, chosenPercentage: 0.44 },
-            { optionText: '绛夊緟鏃堕棿鍚堢悊', chosenQuantity: 55, chosenPercentage: 0.41 },
-            { optionText: '绛夊緟鏃堕棿杈冮暱', chosenQuantity: 15, chosenPercentage: 0.11 },
-            { optionText: '绛夊緟鏃堕棿寰堥暱', chosenQuantity: 5, chosenPercentage: 0.04 },
-            { optionText: '鏃犳硶蹇嶅彈鐨勭瓑寰�', chosenQuantity: 0, chosenPercentage: 0 }
-          ]
-        },
-        {
-          scriptContent: '鎮ㄥ鍖婚櫌鏀惰垂鐨勯�忔槑搴﹀拰鍚堢悊鎬ц瘎浠峰浣�',
-          scriptType: 1,
-          totalCount: 156,
-          answerCount: 130,
-          averageScore: 4.2,
-          maxScore: 5,
-          minScore: 2,
-          options: [
-            { optionText: '闈炲父閫忔槑鍚堢悊', chosenQuantity: 70, chosenPercentage: 0.54 },
-            { optionText: '姣旇緝閫忔槑鍚堢悊', chosenQuantity: 45, chosenPercentage: 0.35 },
-            { optionText: '涓�鑸�', chosenQuantity: 10, chosenPercentage: 0.08 },
-            { optionText: '涓嶅お閫忔槑', chosenQuantity: 5, chosenPercentage: 0.04 },
-            { optionText: '闈炲父涓嶉�忔槑', chosenQuantity: 0, chosenPercentage: 0 }
-          ]
-        },
-        {
-          scriptContent: '鎮ㄤ細鍚戜翰鍙嬫帹鑽愭垜浠尰闄㈠悧',
-          scriptType: 1,
-          totalCount: 156,
-          answerCount: 148,
-          averageScore: 4.8,
-          maxScore: 5,
-          minScore: 3,
-          options: [
-            { optionText: '闈炲父鎰挎剰鎺ㄨ崘', chosenQuantity: 100, chosenPercentage: 0.68 },
-            { optionText: '姣旇緝鎰挎剰鎺ㄨ崘', chosenQuantity: 40, chosenPercentage: 0.27 },
-            { optionText: '涓�鑸�', chosenQuantity: 6, chosenPercentage: 0.04 },
-            { optionText: '涓嶅お鎰挎剰鎺ㄨ崘', chosenQuantity: 2, chosenPercentage: 0.01 },
-            { optionText: '缁濆涓嶄細鎺ㄨ崘', chosenQuantity: 0, chosenPercentage: 0 }
-          ]
-        },
-        {
-          scriptContent: '鎮ㄥ浠ヤ笅鍝簺鏂归潰姣旇緝婊℃剰锛堝閫夛級',
-          scriptType: 2, // 澶氶�夐
-          totalCount: 156,
-          answerCount: 150,
-          averageScore: 4.4,
-          maxScore: 5,
-          minScore: 3,
-          options: [
-            { optionText: '鍖荤枟鎶�鏈按骞�', chosenQuantity: 120, chosenPercentage: 0.8 },
-            { optionText: '鏈嶅姟鎬佸害', chosenQuantity: 110, chosenPercentage: 0.73 },
-            { optionText: '鐜鍗敓', chosenQuantity: 90, chosenPercentage: 0.6 },
-            { optionText: '鍖荤枟璁惧', chosenQuantity: 85, chosenPercentage: 0.57 },
-            { optionText: '鏀惰垂閫忔槑搴�', chosenQuantity: 70, chosenPercentage: 0.47 },
-            { optionText: '绛夊緟鏃堕棿', chosenQuantity: 60, chosenPercentage: 0.4 }
-          ]
-        },
-        {
-          scriptContent: '鎮ㄨ涓哄尰闄㈠摢浜涙柟闈㈤渶瑕佹敼杩涳紙澶氶�夛級',
-          scriptType: 2,
-          totalCount: 156,
-          answerCount: 125,
-          averageScore: 3.8,
-          maxScore: 5,
-          minScore: 2,
-          options: [
-            { optionText: '绛夊緟鏃堕棿杩囬暱', chosenQuantity: 80, chosenPercentage: 0.64 },
-            { optionText: '灏辫瘖娴佺▼澶嶆潅', chosenQuantity: 70, chosenPercentage: 0.56 },
-            { optionText: '璐圭敤杈冮珮', chosenQuantity: 60, chosenPercentage: 0.48 },
-            { optionText: '鍋滆溅鍥伴毦', chosenQuantity: 50, chosenPercentage: 0.4 },
-            { optionText: '鎸囧紩鏍囪瘑涓嶆竻', chosenQuantity: 40, chosenPercentage: 0.32 },
-            { optionText: '缃戠粶棰勭害涓嶄究', chosenQuantity: 30, chosenPercentage: 0.24 }
-          ]
-        },
-        {
-          scriptContent: '鎮ㄥ鏈浣忛櫌鐨勬暣浣撲綋楠岃瘎鍒�',
-          scriptType: 1,
-          totalCount: 156,
-          answerCount: 152,
-          averageScore: 4.6,
-          maxScore: 5,
-          minScore: 3,
-          options: [
-            { optionText: '5鍒嗭紙闈炲父婊℃剰锛�', chosenQuantity: 90, chosenPercentage: 0.59 },
-            { optionText: '4鍒嗭紙婊℃剰锛�', chosenQuantity: 50, chosenPercentage: 0.33 },
-            { optionText: '3鍒嗭紙涓�鑸級', chosenQuantity: 10, chosenPercentage: 0.07 },
-            { optionText: '2鍒嗭紙涓嶆弧鎰忥級', chosenQuantity: 2, chosenPercentage: 0.01 },
-            { optionText: '1鍒嗭紙闈炲父涓嶆弧鎰忥級', chosenQuantity: 0, chosenPercentage: 0 }
-          ]
-        }
-      ];
+      return new Promise((resolve) => {
+        setTimeout(() => {
+          const questions = [
+            {
+              scriptContent: "鎮ㄥ鍖绘姢浜哄憳鐨勬湇鍔℃�佸害鏄惁婊℃剰",
+              scriptType: 1,
+              totalCount: 156,
+              answerCount: 145,
+              averageScore: 4.5,
+              maxScore: 5,
+              minScore: 3,
+              options: [
+                {
+                  optionText: "闈炲父婊℃剰",
+                  chosenQuantity: 89,
+                  chosenPercentage: 0.61,
+                },
+                {
+                  optionText: "婊℃剰",
+                  chosenQuantity: 45,
+                  chosenPercentage: 0.31,
+                },
+                {
+                  optionText: "涓�鑸�",
+                  chosenQuantity: 8,
+                  chosenPercentage: 0.06,
+                },
+                {
+                  optionText: "涓嶆弧鎰�",
+                  chosenQuantity: 2,
+                  chosenPercentage: 0.01,
+                },
+                {
+                  optionText: "闈炲父涓嶆弧鎰�",
+                  chosenQuantity: 1,
+                  chosenPercentage: 0.01,
+                },
+              ],
+            },
+            {
+              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 = (this.detailQueryParams.pageNum - 1) * this.detailQueryParams.pageSize;
-      const endIndex = startIndex + this.detailQueryParams.pageSize;
-      const paginatedData = questions.slice(startIndex, endIndex);
+          const startIndex =
+            (this.detailQueryParams.pageNum - 1) *
+            this.detailQueryParams.pageSize;
+          const endIndex = startIndex + this.detailQueryParams.pageSize;
+          const paginatedData = questions.slice(startIndex, endIndex);
 
-      return {
-        list: paginatedData,
-        total: questions.length
-      };
+          resolve({
+            list: paginatedData,
+            total: questions.length,
+          });
+        }, 300);
+      });
+    },
+
+    // 鐢熸垚Mock绫诲瀷鏄庣粏鏁版嵁
+    generateMockTypeDetail() {
+      return new Promise((resolve) => {
+        setTimeout(() => {
+          // 鍦� generateMockTypeDetail 鏂规硶涓浛鎹负锛�
+          const types = [
+            {
+              id: 401,
+              typeName: "鍑洪櫌婊℃剰搴�",
+              isSpecial: false,
+              sendCount: 2850,
+              receiveCount: 2680,
+              recoveryRate: 0.94,
+              averageScore: 4.8,
+              maxScore: 5,
+              minScore: 3.8,
+              satisfactionLevel: "浼樼",
+              trend: "up",
+            },
+            {
+              id: 402,
+              typeName: "浣忛櫌婊℃剰搴�",
+              isSpecial: false,
+              sendCount: 2620,
+              receiveCount: 2405,
+              recoveryRate: 0.918,
+              averageScore: 4.6,
+              maxScore: 5,
+              minScore: 3.5,
+              satisfactionLevel: "浼樼",
+              trend: "stable",
+            },
+            {
+              id: 403,
+              typeName: "闂ㄨ瘖婊℃剰搴�",
+              isSpecial: false,
+              sendCount: 3780,
+              receiveCount: 3220,
+              recoveryRate: 0.852,
+              averageScore: 4.3,
+              maxScore: 5,
+              minScore: 2.5,
+              satisfactionLevel: "鑹ソ",
+              trend: "up",
+            },
+            {
+              id: 404,
+              typeName: "甯哥敤婊℃剰搴�",
+              isSpecial: true,
+              sendCount: 1950,
+              receiveCount: 1780,
+              recoveryRate: 0.913,
+              averageScore: 4.5,
+              maxScore: 5,
+              minScore: 3.2,
+              satisfactionLevel: "鑹ソ",
+              trend: "stable",
+            },
+          ];
+
+          resolve(types);
+        }, 300);
+      });
     },
 
     // 澶勭悊鍥捐〃鍝嶅簲寮�
@@ -808,6 +1177,13 @@
       this.loadData();
     },
 
+    // 澶勭悊Tab鍒囨崲
+    handleTabClick(tab) {
+      if (tab.name === "typeDetail" && this.typeDetailData.length === 0) {
+        this.loadTypeDetailData();
+      }
+    },
+
     // 澶勭悊鏄庣粏鍒嗛〉澶у皬鍙樺寲
     handleDetailSizeChange(size) {
       this.detailQueryParams.pageSize = size;
@@ -821,80 +1197,131 @@
       this.loadQuestionDetailData();
     },
 
+    // 澶勭悊绫诲瀷璇︽儏
+    handleTypeDetail(row) {
+      this.$message.info(`鏌ョ湅绫诲瀷璇︽儏锛�${row.typeName}`);
+      // 杩欓噷鍙互璺宠浆鍒拌鎯呴〉闈㈡垨鎵撳紑璇︽儏瀵硅瘽妗�
+    },
+
+    // 澶勭悊瀵煎嚭鏁版嵁
+    handleExportData(row) {
+      this.$message.success(`姝e湪瀵煎嚭 ${row.typeName} 鏁版嵁...`);
+      // 杩欓噷鍙互瀹炵幇瀵煎嚭閫昏緫
+    },
+
     // 鏍煎紡鍖栫櫨鍒嗘瘮
     formatPercent(value) {
-      if (value === null || value === undefined) return '-';
+      if (value === null || value === undefined) return "-";
       const num = parseFloat(value);
-      if (isNaN(num)) return '-';
+      if (isNaN(num)) return "-";
       return `${(num * 100).toFixed(2)}%`;
-    }
-  }
+    },
+
+    // 鑾峰彇鍥炴敹鐜囨牱寮忕被
+    getRateClass(rate) {
+      if (rate >= 0.9) return "rate-high";
+      if (rate >= 0.8) return "rate-medium";
+      return "rate-low";
+    },
+
+    // 鑾峰彇婊℃剰搴︾瓑绾ф爣绛剧被鍨�
+    getLevelTagType(level) {
+      const levelMap = {
+        浼樼: "success",
+        鑹ソ: "primary",
+        涓�鑸�: "warning",
+        杈冨樊: "danger",
+        宸�: "info",
+      };
+      return levelMap[level] || "info";
+    },
+  },
 };
 </script>
 
 <style lang="scss" scoped>
 .satisfaction-statistics {
+  padding: 20px;
+  background-color: #f5f7fa;
+  min-height: 100vh;
+
   .query-section {
-    background: #fff;
-    padding: 20px;
-    border-radius: 4px;
     margin-bottom: 20px;
 
     .query-form {
       display: flex;
       flex-wrap: wrap;
+      align-items: center;
 
       ::v-deep .el-form-item {
-        margin-bottom: 20px;
+        margin-bottom: 0;
+        margin-right: 20px;
 
-        &:not(:last-child) {
-          margin-right: 20px;
+        &:last-child {
+          margin-right: 0;
         }
       }
     }
   }
 
   .chart-section {
-    background: #fff;
-    padding: 20px;
-    border-radius: 4px;
     margin-bottom: 20px;
 
     .chart-container {
-      width: 100%;
-
-      .chart-title {
-        font-size: 16px;
-        font-weight: 600;
-        color: #333;
+      .chart-header {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
         margin-bottom: 20px;
-        padding-bottom: 10px;
+        padding-bottom: 15px;
         border-bottom: 1px solid #f0f0f0;
-      }
 
-      #satisfactionBarChart {
-        width: 100%;
-        height: 400px;
+        .chart-title {
+          margin: 0;
+          font-size: 16px;
+          font-weight: 600;
+          color: #303133;
+        }
+
+        .statistic-info {
+          display: flex;
+          gap: 30px;
+          align-items: center;
+
+          .statistic-item {
+            display: flex;
+            align-items: center;
+            gap: 8px;
+
+            .statistic-label {
+              font-size: 14px;
+              color: #606266;
+            }
+
+            .statistic-value {
+              font-size: 18px;
+              font-weight: 600;
+              color: #409eff;
+            }
+          }
+        }
       }
     }
   }
 
-  .detail-table-section {
-    background: #fff;
-    padding: 20px;
-    border-radius: 4px;
-
-    .section-title {
-      font-size: 16px;
-      font-weight: 600;
-      color: #333;
-      margin-bottom: 20px;
-      padding-bottom: 10px;
-      border-bottom: 1px solid #f0f0f0;
+  .tab-section {
+    ::v-deep .el-tabs__header {
+      margin-bottom: 0;
     }
 
+    ::v-deep .el-tabs__content {
+      padding: 20px 0 0 0;
+    }
+  }
+
+  .detail-table-section {
     .option-detail {
-      padding: 20px;
+      padding: 15px;
       background: #f8f9fa;
       border-radius: 4px;
       margin: 10px 0;
@@ -905,6 +1332,11 @@
         background-color: #f8f9fa;
         font-weight: 600;
         color: #333;
+        padding: 12px 0;
+      }
+
+      td {
+        padding: 12px 0;
       }
 
       .question-row {
@@ -930,7 +1362,7 @@
       margin-top: 20px;
       padding: 20px;
       background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
-      border-radius: 4px;
+      border-radius: 8px;
       border: 1px solid #dee2e6;
 
       .summary-content {
@@ -943,27 +1375,129 @@
 
           .label {
             font-size: 16px;
-            color: #666;
+            color: #606266;
             margin-right: 8px;
           }
 
           .value {
             font-size: 24px;
             font-weight: 600;
-            color: #1890ff;
+            color: #409eff;
           }
         }
       }
     }
+
+    .pagination-section {
+      display: flex;
+      justify-content: center;
+      padding: 20px 0 0 0;
+    }
   }
 
-  .pagination-section {
-    display: flex;
-    justify-content: flex-end;
-    background: #fff;
-    padding: 20px;
-    border-radius: 4px;
-    margin-top: 20px;
+  .type-detail-section {
+    .type-detail-table {
+      ::v-deep .el-table__header-wrapper {
+        th {
+          background-color: #f0f7ff;
+          font-weight: 600;
+          color: #333;
+        }
+      }
+
+      .type-name-cell {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+
+        .type-name {
+          font-weight: 500;
+        }
+      }
+
+      .number-text {
+        font-weight: 600;
+        color: #333;
+      }
+
+      .rate-text {
+        font-weight: 600;
+        font-size: 14px;
+
+        &.rate-high {
+          color: #67c23a;
+        }
+
+        &.rate-medium {
+          color: #e6a23c;
+        }
+
+        &.rate-low {
+          color: #f56c6c;
+        }
+      }
+
+      .score-text {
+        font-weight: 600;
+        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 {
+      margin-top: 20px;
+      padding: 20px;
+      background: linear-gradient(135deg, #f0f9ff 0%, #e6f7ff 100%);
+      border-radius: 8px;
+      border: 1px solid #d0ebff;
+
+      .type-summary-content {
+        display: flex;
+        justify-content: space-around;
+        align-items: center;
+        flex-wrap: wrap;
+        gap: 20px;
+
+        .type-summary-item {
+          text-align: center;
+          min-width: 150px;
+
+          .label {
+            font-size: 14px;
+            color: #606266;
+            margin-right: 8px;
+          }
+
+          .value {
+            font-size: 20px;
+            font-weight: 600;
+            color: #409eff;
+          }
+
+          .high-count {
+            color: #67c23a;
+          }
+        }
+      }
+    }
   }
 
   // 鍐呭眰琛ㄦ牸鏍峰紡
@@ -987,4 +1521,51 @@
     }
   }
 }
+
+@media (max-width: 768px) {
+  .satisfaction-statistics {
+    padding: 10px;
+
+    .query-section {
+      .query-form {
+        ::v-deep .el-form-item {
+          width: 100%;
+          margin-right: 0;
+          margin-bottom: 10px;
+        }
+      }
+    }
+
+    .chart-section {
+      .chart-container {
+        .chart-header {
+          flex-direction: column;
+          align-items: flex-start;
+          gap: 15px;
+
+          .statistic-info {
+            width: 100%;
+            justify-content: space-between;
+            flex-wrap: wrap;
+            gap: 10px;
+          }
+        }
+      }
+    }
+
+    .detail-table-section {
+      .summary-content {
+        flex-direction: column;
+        gap: 15px;
+      }
+    }
+
+    .type-detail-section {
+      .type-summary-content {
+        flex-direction: column;
+        gap: 15px;
+      }
+    }
+  }
+}
 </style>

--
Gitblit v1.9.3