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

---
 src/views/Satisfaction/sfstatistics/components/visitStatistics.vue |  319 +++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 274 insertions(+), 45 deletions(-)

diff --git a/src/views/Satisfaction/sfstatistics/components/visitStatistics.vue b/src/views/Satisfaction/sfstatistics/components/visitStatistics.vue
index 2c7ed98..ea36ad9 100644
--- a/src/views/Satisfaction/sfstatistics/components/visitStatistics.vue
+++ b/src/views/Satisfaction/sfstatistics/components/visitStatistics.vue
@@ -383,6 +383,7 @@
 
       // 鍔犺浇鐘舵��
       loading: false,
+      orgname: "",
 
       // 閫変腑鐨勮
       ids: [],
@@ -441,6 +442,7 @@
   },
 
   created() {
+    this.orgname = localStorage.getItem("orgname");
     this.initData();
   },
 
@@ -824,6 +826,113 @@
       }
     },
 
+    // 鑾峰彇鎸囧畾鐥呭尯/绉戝鐨勯鐩鎯�
+    async fetchTopicDetail(row) {
+      const params = {
+        configKey: "returnVisitCount",
+        ...this.queryParams,
+      };
+      // 瀵煎嚭闇�瑕佽鐥呭尯/绉戝鐨勫叏閮ㄩ鐩紝瑕嗙洊涓昏〃鍒嗛〉鍙傛暟
+      params.pageNum = 1;
+      params.pageSize = 1000;
+      if (
+        this.queryParams.dateRange &&
+        this.queryParams.dateRange.length === 2
+      ) {
+        params.startTime = this.queryParams.dateRange[0];
+        params.endTime = this.queryParams.dateRange[1];
+      }
+      if (this.queryParams.statisticaltype == 1) {
+        params.leavehospitaldistrictcodes = [row.leavehospitaldistrictcode];
+      } else {
+        params.deptcodes = [row.deptcode];
+      }
+      const response = await getSfStatisticsJoyInfo(params);
+      return response.data || {};
+    },
+
+    // 涓昏〃瀵煎嚭琛屾暟鎹�
+    getMainExportRow(item) {
+      return [
+        this.queryParams.statisticaltype == 1
+          ? item.leavehospitaldistrictname
+          : item.deptname,
+        item.dischargeCount || 0,
+        item.nonFollowUp || 0,
+        item.followUpNeeded || 0,
+        item.followUpRate || "0%",
+        item.rate ? this.formatPercent(item.rate) : "0%",
+        item.joyAllCount || 0,
+        item.joyCount || 0,
+        item.joyTotal ? this.formatPercent(item.joyTotal) : "0%",
+      ];
+    },
+
+    // 璁$畻鏂囨湰鏄剧ず瀹藉害锛堜腑鏂囨寜 2銆佽嫳鏂�/鏁板瓧鎸� 1锛�
+    textWidth(str) {
+      if (!str) return 0;
+      let width = 0;
+      for (const ch of String(str)) {
+        width += ch.charCodeAt(0) > 255 ? 2 : 1;
+      }
+      return width;
+    },
+
+    // 涓芥按甯備腑鍖婚櫌锛氭媺鍙栨墍鏈夌瀹ら鐩槑缁嗭紝鎵佸钩鍖栦负銆岄鐩�夐」銆嶅垪缁撴瀯
+    async buildLishuiTopicColumns() {
+      const topicMap = new Map();
+      const rowQuantities = [];
+
+      for (const item of this.userList) {
+        const topiclist = await this.fetchTopicDetail(item);
+        const qMap = new Map();
+
+        if (topiclist && Object.keys(topiclist).length) {
+          Object.keys(topiclist).forEach((key) => {
+            const topic = topiclist[key];
+            if (!topic || !topic.scriptContent) return;
+
+            const tKey =
+              topic.scriptid != null && topic.scriptid !== ""
+                ? String(topic.scriptid)
+                : topic.scriptContent;
+
+            if (!topicMap.has(tKey)) {
+              topicMap.set(tKey, {
+                key: tKey,
+                scriptContent: topic.scriptContent,
+                options: [],
+                optionSet: new Set(),
+              });
+            }
+
+            const t = topicMap.get(tKey);
+            const topicQ = new Map();
+            (topic.details || []).forEach((detail) => {
+              if (!detail || !detail.optionText) return;
+              if (!t.optionSet.has(detail.optionText)) {
+                t.optionSet.add(detail.optionText);
+                t.options.push(detail.optionText);
+              }
+              topicQ.set(detail.optionText, Number(detail.chosenQuantity) || 0);
+            });
+            qMap.set(tKey, topicQ);
+          });
+        }
+
+        rowQuantities.push(qMap);
+      }
+
+      const topics = Array.from(topicMap.values());
+      // 娌℃湁閫夐」鐨勯鐩粯璁ゅ~鍏呬竴涓┖閫夐」鍒楋紝閬垮厤琛ㄥご/鏁版嵁閿欎綅
+      topics.forEach((t) => {
+        if (!t.options.length) {
+          t.options = [""];
+        }
+      });
+      return { topics, rowQuantities };
+    },
+
     // 瀵煎嚭鏁版嵁
     async handleExport() {
       if (!this.userList.length) {
@@ -916,7 +1025,11 @@
             pattern: "solid",
             fgColor: { argb: "FFF5F7FA" },
           },
-          alignment: { vertical: "middle", horizontal: "center" },
+          alignment: {
+            vertical: "middle",
+            horizontal: "center",
+            wrapText: true,
+          },
           border: {
             top: { style: "thin", color: { argb: "FFD0D0D0" } },
             left: { style: "thin", color: { argb: "FFD0D0D0" } },
@@ -936,15 +1049,17 @@
           },
         };
 
-        // 娣诲姞鎬绘爣棰�
-        worksheet.mergeCells(1, 1, 1, 10);
-        const titleCell = worksheet.getCell(1, 1);
-        titleCell.value = `澶嶈瘖閫氱煡缁熻琛紙${sheetNameSuffix}锛塦;
-        titleCell.style = titleStyle;
-        worksheet.getRow(1).height = 35;
+        // 涓芥按甯備腑鍖婚櫌锛氶鍏堟媺鍙栭鐩槑缁嗭紝鎵佸钩鍖栦负銆岄鐩�夐」銆嶅垪
+        let lishuiTopics = [];
+        let lishuiRowQuantities = [];
+        if (isLishuiHospital) {
+          const built = await this.buildLishuiTopicColumns();
+          lishuiTopics = built.topics;
+          lishuiRowQuantities = built.rowQuantities;
+        }
 
-        // 娣诲姞琛ㄥご
-        const headers = [
+        // 涓昏〃鍒�
+        const mainHeaders = [
           this.queryParams.statisticaltype == 1 ? "鍑洪櫌鐥呭尯" : "绉戝",
           "鍑洪櫌浜烘",
           "鏃犻渶闅忚浜烘",
@@ -955,47 +1070,161 @@
           "澶嶈瘖閫氱煡濉姤閲�",
           "瀹屾垚姣旂巼",
         ];
+        const mainColumnCount = mainHeaders.length;
 
-        const headerRow = worksheet.addRow(headers);
-        headerRow.eachCell((cell) => {
-          cell.style = headerStyle;
-        });
-        headerRow.height = 25;
+        // 鎬诲垪鏁帮紙涓芥按甯備腑鍖婚櫌鍦ㄦ湯灏捐拷鍔犻鐩�夐」鍒楋級
+        const topicColumnCount = lishuiTopics.reduce(
+          (sum, t) => sum + (t.options.length || 1),
+          0
+        );
+        const totalColumns = mainColumnCount + topicColumnCount;
 
-        // 娣诲姞鏁版嵁琛�
-        this.userList.forEach((item) => {
-          const dataRow = worksheet.addRow([
-            this.queryParams.statisticaltype == 1
-              ? item.leavehospitaldistrictname
-              : item.deptname,
-            item.dischargeCount || 0,
-            item.nonFollowUp || 0,
-            item.followUpNeeded || 0,
-            item.followUpRate || "0%",
-            item.rate ? this.formatPercent(item.rate) : "0%",
-            item.joyAllCount || 0,
-            item.joyCount || 0,
-            item.joyTotal ? this.formatPercent(item.joyTotal) : "0%",
-          ]);
+        // 娣诲姞鎬绘爣棰�
+        worksheet.mergeCells(1, 1, 1, totalColumns);
+        const titleCell = worksheet.getCell(1, 1);
+        titleCell.value = `澶嶈瘖閫氱煡缁熻琛紙${sheetNameSuffix}锛塦;
+        titleCell.style = titleStyle;
+        worksheet.getRow(1).height = 35;
 
-          dataRow.eachCell((cell) => {
-            cell.style = cellStyle;
+        if (isLishuiHospital && lishuiTopics.length) {
+          // 璁$畻姣忎釜棰樼洰鐨勯�夐」鍒楀锛堥�夐」鏂囧瓧鑷�傚簲锛岄骞茶繃闀挎椂鎽婂鍒椼�佸繀瑕佹椂鎹㈣锛�
+          const topicColumns = lishuiTopics.map((topic) => {
+            const n = topic.options.length || 1;
+            const baseWidths = topic.options.map((opt) =>
+              opt === "" ? 10 : Math.max(10, this.textWidth(opt) + 4)
+            );
+            const sumWidth = baseWidths.reduce((s, w) => s + w, 0);
+            const topicWidth = this.textWidth(topic.scriptContent) + 4;
+            const groupWidth = Math.max(sumWidth, topicWidth);
+            const extra = (groupWidth - sumWidth) / n;
+            const widths = baseWidths.map((w) => w + extra);
+            const lines = Math.max(1, Math.ceil(topicWidth / groupWidth));
+            return { widths, lines };
           });
-          dataRow.height = 22;
-        });
+          const maxHeaderLines = topicColumns.reduce(
+            (m, t) => Math.max(m, t.lines),
+            1
+          );
 
-        // 璁剧疆鍒楀
-        worksheet.columns = [
-          { width: 20 },
-          { width: 12 },
-          { width: 12 },
-          { width: 12 },
-          { width: 12 },
-          { width: 12 },
-          { width: 15 },
-          { width: 15 },
-          { width: 12 },
-        ];
+          // 涓よ琛ㄥご锛氱涓�琛� = 涓昏〃鍒� + 棰樼洰鍚嶏紱绗簩琛� = 閫夐」鍚�
+          const headerRow1 = worksheet.addRow([]);
+          const headerRow2 = worksheet.addRow([]);
+
+          mainHeaders.forEach((h, i) => {
+            const col = i + 1;
+            headerRow1.getCell(col).value = h;
+            headerRow1.getCell(col).style = headerStyle;
+            headerRow2.getCell(col).style = headerStyle;
+            worksheet.mergeCells(
+              headerRow1.number,
+              col,
+              headerRow2.number,
+              col
+            );
+          });
+
+          let colIndex = mainColumnCount + 1;
+          lishuiTopics.forEach((topic) => {
+            const optCount = topic.options.length || 1;
+            for (let k = 0; k < optCount; k++) {
+              headerRow1.getCell(colIndex + k).style = headerStyle;
+            }
+            headerRow1.getCell(colIndex).value = topic.scriptContent;
+            if (optCount > 1) {
+              worksheet.mergeCells(
+                headerRow1.number,
+                colIndex,
+                headerRow1.number,
+                colIndex + optCount - 1
+              );
+            }
+            topic.options.forEach((opt, k) => {
+              headerRow2.getCell(colIndex + k).value = opt;
+              headerRow2.getCell(colIndex + k).style = headerStyle;
+            });
+            colIndex += optCount;
+          });
+
+          // 琛ㄥご楂樺害锛氶骞叉崲琛屾椂鎸夋渶闀块鐩鐣�
+          headerRow1.height = Math.max(30, 15 * maxHeaderLines + 8);
+          headerRow2.height = 25;
+
+          // 鏁版嵁琛�
+          this.userList.forEach((item, idx) => {
+            const row = worksheet.addRow([]);
+            const main = this.getMainExportRow(item);
+            main.forEach((v, i) => {
+              const cell = row.getCell(i + 1);
+              cell.value = v;
+              cell.style = cellStyle;
+            });
+
+            const qMap = lishuiRowQuantities[idx] || new Map();
+            let cIndex = mainColumnCount + 1;
+            for (const topic of lishuiTopics) {
+              const topicQ = qMap.get(topic.key);
+              topic.options.forEach((opt) => {
+                const cell = row.getCell(cIndex);
+                if (opt === "") {
+                  // 绌洪�夐」鍗犱綅鍒椾笉濉暟瀛�
+                  cell.value = "";
+                } else {
+                  const val = topicQ ? topicQ.get(opt) : undefined;
+                  cell.value = val === undefined || val === null ? 0 : val;
+                }
+                cell.style = cellStyle;
+                cIndex++;
+              });
+            }
+            row.height = 22;
+          });
+
+          // 鍒楀锛氫富琛ㄥ垪 + 棰樼洰閫夐」鍒�
+          const columns = [
+            { width: 20 },
+            { width: 12 },
+            { width: 12 },
+            { width: 12 },
+            { width: 12 },
+            { width: 12 },
+            { width: 15 },
+            { width: 15 },
+            { width: 12 },
+          ];
+          lishuiTopics.forEach((topic, ti) => {
+            topicColumns[ti].widths.forEach((w) => {
+              columns.push({ width: w });
+            });
+          });
+          worksheet.columns = columns;
+        } else {
+          // 鍏朵粬鍖婚櫌锛氬崟琛岃〃澶�
+          const headerRow = worksheet.addRow(mainHeaders);
+          headerRow.eachCell((cell) => {
+            cell.style = headerStyle;
+          });
+          headerRow.height = 25;
+
+          this.userList.forEach((item) => {
+            const dataRow = worksheet.addRow(this.getMainExportRow(item));
+            dataRow.eachCell((cell) => {
+              cell.style = cellStyle;
+            });
+            dataRow.height = 22;
+          });
+
+          worksheet.columns = [
+            { width: 20 },
+            { width: 12 },
+            { width: 12 },
+            { width: 12 },
+            { width: 12 },
+            { width: 12 },
+            { width: 15 },
+            { width: 15 },
+            { width: 12 },
+          ];
+        }
 
         // 鐢熸垚骞朵笅杞芥枃浠�
         const buffer = await workbook.xlsx.writeBuffer();

--
Gitblit v1.9.3