From d725dc65cf7f74df3aa3f5a0297fd6f8b767cdbc Mon Sep 17 00:00:00 2001
From: liusheng <337615773@qq.com>
Date: 星期五, 30 十月 2026 10:23:03 +0800
Subject: [PATCH] Merge branch 'subtask' of http://116.62.18.175:6699/r/~yxh/smartor-web into subtask
---
src/components/UploadExcel/index.vue | 2
src/views/Satisfaction/sfstatistics/components/ChartsPanel.vue | 175 ++++++++---
src/views/Satisfaction/sfstatistics/components/SatisfactionStatistics.vue | 346 ++++++++++++++++++++++
src/views/Satisfaction/sfstatistics/components/DataOverview.vue | 221 ++++++++++----
src/views/Satisfaction/sfstatistics/components/FollowupStatistics.vue | 81 ++--
src/views/Satisfaction/sfstatistics/components/visitStatistics.vue | 63 ++--
6 files changed, 705 insertions(+), 183 deletions(-)
diff --git a/src/components/UploadExcel/index.vue b/src/components/UploadExcel/index.vue
index bf6d7a9..acf34f5 100644
--- a/src/components/UploadExcel/index.vue
+++ b/src/components/UploadExcel/index.vue
@@ -32,7 +32,7 @@
</template>
<script>
-import XLSX from "xlsx";
+import * as XLSX from "xlsx";
export default {
name: "UploadExcel",
props: {
diff --git a/src/views/Satisfaction/sfstatistics/components/ChartsPanel.vue b/src/views/Satisfaction/sfstatistics/components/ChartsPanel.vue
index 86c5b41..e5b5e64 100644
--- a/src/views/Satisfaction/sfstatistics/components/ChartsPanel.vue
+++ b/src/views/Satisfaction/sfstatistics/components/ChartsPanel.vue
@@ -41,7 +41,7 @@
<el-button type="primary" size="small" icon="el-icon-search" @click="refreshAll">鏌ヨ</el-button>
<el-button size="small" icon="el-icon-refresh" @click="handleReset">閲嶇疆</el-button>
</div>
- <el-button type="danger" size="small" icon="el-icon-download" @click="exportPDF">瀵煎嚭PDF</el-button>
+ <el-button type="danger" size="small" icon="el-icon-download" @click="exportExcel">瀵煎嚭Excel</el-button>
</div>
<el-row :gutter="20">
@@ -171,6 +171,8 @@
<script>
import * as echarts from 'echarts';
+import ExcelJS from 'exceljs';
+import { saveAs } from 'file-saver';
import { mydTrend, sltdMydTotalByDimension, sltdMydTotalByScore ,mzMydScoreRank} from "@/api/AiCentre/satisfaction";
import { getissuelist } from "@/api/AiCentre/questionnaire";
@@ -198,10 +200,10 @@
singleQuestionContent: '',
singleDeptWards: [],
- // 鎺掑悕缁村害绛涢��
- rankDimension: 'dept',
+ // 鎺掑悕缁村害绛涢�夛紙榛樿鎸夌梾鍖猴級
+ rankDimension: 'ward',
rankDeptWards: [],
- crossDimension: 'dept',
+ crossDimension: 'ward',
crossDeptWards: [],
// 鍥捐〃鏁版嵁
@@ -845,52 +847,129 @@
});
},
- async exportPDF() {
- const chartRefs = [
- { ref: this.$refs.chart1, id: 'chart1' },
- { ref: this.$refs.chart2, id: 'chart2' },
- { ref: this.$refs.chart4, id: 'chart4' },
- ];
- const chartImages = {};
- for (const { ref, id } of chartRefs) {
- if (ref) {
- const instance = echarts.getInstanceByDom(ref);
- if (instance) {
- chartImages[id] = instance.getDataURL({ type: 'png', pixelRatio: 2, backgroundColor: '#fff' });
+ // 瀵煎嚭锛氬浘琛ㄨ浆鍥剧墖 + 琛ㄦ牸锛屽唴瀹逛笌椤甸潰涓�鑷达紙鐩存帴涓嬭浇 xlsx锛屼笉渚濊禆鎵撳嵃锛�
+ async exportExcel() {
+ try {
+ const wb = new ExcelJS.Workbook();
+
+ // 鍥捐〃 sheet
+ const addImageSheet = (sheetName, title, refEl, tip) => {
+ const ws = wb.addWorksheet(sheetName, {
+ views: [{ showGridLines: false }],
+ });
+ ws.getCell('A1').value = title;
+ ws.getCell('A1').font = { size: 14, bold: true };
+ ws.mergeCells('A1:F1');
+ let anchorRow = 2.2;
+ if (tip) {
+ ws.getCell('A2').value = tip;
+ ws.mergeCells('A2:F2');
+ anchorRow = 2.8;
}
- }
+ for (let c = 1; c <= 6; c++) {
+ ws.getColumn(c).width = 18;
+ }
+ const inst = refEl ? echarts.getInstanceByDom(refEl) : null;
+ if (inst) {
+ const url = inst.getDataURL({
+ type: 'png',
+ pixelRatio: 2,
+ backgroundColor: '#fff',
+ });
+ const imgId = wb.addImage({
+ base64: url.split(',')[1],
+ extension: 'png',
+ });
+ ws.addImage(imgId, {
+ tl: { col: 0.1, row: anchorRow },
+ ext: { width: 900, height: 400 },
+ });
+ } else {
+ ws.getCell(`A${Math.ceil(anchorRow)}`).value = '鏆傛棤鏁版嵁';
+ }
+ return ws;
+ };
+
+ addImageSheet(
+ '缁煎悎寰楀垎瓒嬪娍',
+ '鎮h�呮弧鎰忓害缁煎悎寰楀垎瓒嬪娍',
+ this.$refs.chart1,
+ `鐜瘮 ${this.trendMoM}`
+ );
+ addImageSheet(
+ '鍒嗙被缁村害瀵规瘮',
+ `鍒嗙被缁村害 路 鍚勬寚鏍�${this.intervalLabel}瀵规瘮`,
+ this.$refs.chart2,
+ ''
+ );
+ addImageSheet(
+ '闄㈠尯缁村害瀵规瘮',
+ `闄㈠尯缁村害 路 鍚勯櫌鍖�${this.intervalLabel}瀵规瘮`,
+ this.$refs.chart4,
+ ''
+ );
+
+ // 鍗曢 路 閫夐」缁熻
+ const wsQ = wb.addWorksheet('鍗曢閫夐」缁熻');
+ wsQ.addRow(['鍗曢 路 閫夐」缁熻']).font = { size: 14, bold: true };
+ wsQ.mergeCells(1, 1, 1, 3);
+ const qHead = wsQ.addRow(['閫夐」', '鍚堣鏁伴噺', '鍗犳瘮姣斾緥']);
+ qHead.font = { bold: true };
+ (this.singleQuestionData || []).forEach((r) => {
+ wsQ.addRow([r.option, r.count, r.rate]);
+ });
+ wsQ.addRow([]);
+ wsQ.addRow([
+ `鏈鏈夋晥濉啓浜烘锛�${this.singleQuestionMeta.total}銆�缁煎悎寰楀垎锛�${this.singleQuestionMeta.score}`,
+ '',
+ '',
+ ]);
+ wsQ.mergeCells(wsQ.rowCount, 1, wsQ.rowCount, 3);
+ wsQ.columns.forEach((c, i) => {
+ c.width = i === 0 ? 36 : 16;
+ });
+
+ // 鎺掑悕琛ㄦ牸
+ const addRankSheet = (sheetName, title, rows, dimLabel) => {
+ const ws = wb.addWorksheet(sheetName);
+ ws.addRow([title]).font = { size: 14, bold: true };
+ ws.mergeCells(1, 1, 1, 4);
+ const head = ws.addRow(['鎺掑悕', dimLabel, '缁煎悎寰楀垎', '椤规暟']);
+ head.font = { bold: true };
+ (rows || []).forEach((r) => {
+ ws.addRow([r.rank, r.name, r.score, r.itemCount]);
+ });
+ if (!rows || !rows.length) {
+ ws.addRow(['鏆傛棤鏁版嵁', '', '', '']);
+ }
+ ws.columns.forEach((c, i) => {
+ c.width = i === 1 ? 30 : 12;
+ });
+ };
+ addRankSheet(
+ `${this.rankDimLabel}鎺掑悕`,
+ `${this.rankDimLabel}缁村害 路 闂ㄨ瘖鎮h�呮弧鎰忓害寰楀垎鎺掑悕`,
+ this.rankRows,
+ this.rankDimLabel
+ );
+ addRankSheet(
+ `鍗曢脳${this.crossDimLabel}鎺掑悕`,
+ `鍗曢脳${this.crossDimLabel} 路 寰楀垎鎺掑悕`,
+ this.crossRows,
+ this.crossDimLabel
+ );
+
+ const buffer = await wb.xlsx.writeBuffer();
+ const blob = new Blob([buffer], {
+ type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+ });
+ const range = (this.queryParams.dateRange || []).join('_');
+ saveAs(blob, `鍚勯」缁熻琛�${range ? '_' + range : ''}.xlsx`);
+ this.$message.success('瀵煎嚭鎴愬姛');
+ } catch (e) {
+ console.error('瀵煎嚭澶辫触:', e);
+ this.$message.error('瀵煎嚭澶辫触锛�' + (e.message || e));
}
-
- const printContent = this.$refs.pdfTarget.cloneNode(true);
- const chartBoxes = printContent.querySelectorAll('.chart-box');
- const imgKeys = Object.keys(chartImages);
- chartBoxes.forEach((box, i) => {
- if (imgKeys[i] && chartImages[imgKeys[i]]) {
- box.innerHTML = `<img src="${chartImages[imgKeys[i]]}" style="width:100%;height:auto;" />`;
- }
- });
-
- const win = window.open('', '_blank', 'width=900,height=800');
- if (!win) { this.$message.warning('璇峰厑璁稿脊鍑虹獥鍙d互瀵煎嚭PDF'); return; }
- win.document.write(`
- <html><head><meta charset="utf-8"><title>鍚勯」缁熻琛�</title>
- <style>
- body { font-family: 'Microsoft YaHei',sans-serif; padding: 20px; }
- .chart-card { break-inside: avoid; margin-bottom: 20px; border: 1px solid #ebeef5; border-radius: 6px; }
- .card-header { padding: 12px 16px; border-bottom: 1px solid #ebeef5; font-size: 15px; font-weight: 600; color: #303133; background: #f5f7fa; }
- .chart-box img { max-width: 100%; display: block; }
- table { width: 100%; border-collapse: collapse; margin: 12px 0; }
- th, td { border: 1px solid #d9d9d9; padding: 8px 12px; text-align: center; font-size: 12px; }
- th { background: #f0f2f5; font-weight: 600; }
- .table-footer { text-align: right; padding: 8px 0; font-size: 13px; color: #606266; }
- .export-bar, .filter-bar, .el-tag, .el-select, .el-radio-group { display: none; }
- @media print { @page { size: A4; margin: 10mm; } }
- </style></head><body>
- ${printContent.innerHTML}
- <script>window.onload=function(){window.print();}<\/script>
- </body></html>
- `);
- win.document.close();
},
},
};
diff --git a/src/views/Satisfaction/sfstatistics/components/DataOverview.vue b/src/views/Satisfaction/sfstatistics/components/DataOverview.vue
index 4539a87..3e8f084 100644
--- a/src/views/Satisfaction/sfstatistics/components/DataOverview.vue
+++ b/src/views/Satisfaction/sfstatistics/components/DataOverview.vue
@@ -106,6 +106,13 @@
<el-button size="small" icon="el-icon-refresh" @click="handleReset"
>閲嶇疆</el-button
>
+ <el-button
+ type="warning"
+ size="small"
+ icon="el-icon-download"
+ @click="exportTable()"
+ >瀵煎嚭Excel</el-button
+ >
</el-form-item>
</el-form>
</el-card>
@@ -115,13 +122,6 @@
<div slot="header" class="card-header">
<span class="card-title">鍚勬湇鍔¢」鐩弧鎰忓害缁熻</span>
<span class="card-subtitle">锛堝叚妗h瘎鍒嗛锛氬緢婊℃剰/婊℃剰/涓�鑸�/涓嶆弧鎰�/寰堜笉婊℃剰/鏈粡鍘嗭級</span>
- <el-button
- type="warning"
- size="small"
- icon="el-icon-download"
- @click="exportTable('table1')"
- >瀵煎嚭Excel</el-button
- >
</div>
<el-table
id="table1"
@@ -186,13 +186,6 @@
placeholder="鎸夐鐩ā绯婃煡璇�"
class="search-input"
/>
- <el-button
- type="warning"
- size="small"
- icon="el-icon-download"
- @click="exportTable('table2')"
- >瀵煎嚭Excel</el-button
- >
</div>
</div>
<div id="table2" v-loading="loading" element-loading-text="缁熻涓�...">
@@ -271,13 +264,6 @@
/>
</template>
</el-select>
- <el-button
- type="warning"
- size="small"
- icon="el-icon-download"
- @click="exportTable('table3')"
- >瀵煎嚭Excel</el-button
- >
</div>
</div>
<el-table
@@ -336,7 +322,7 @@
<script>
import { sltdMydTotalByScore,statQuestionOptionByKsOrBq } from "@/api/AiCentre/satisfaction";
import { deptTreeSelect } from "@/api/system/user";
-import XLSX from "xlsx";
+import * as XLSX from "xlsx";
// 婊℃剰搴﹂鐨勫浐瀹氶�夐」锛堥『搴忓嵆琛ㄦ牸鍒楅『搴忥級鈥斺�旇繖浜涢�夐」鐨勯鐩繘琛ㄤ竴锛屽叾浣欒繘琛ㄤ簩
const FIXED_OPTIONS = ["寰堟弧鎰�", "婊℃剰", "涓�鑸�", "涓嶆弧鎰�", "寰堜笉婊℃剰", "鏈粡鍘�"];
@@ -1128,52 +1114,165 @@
const hit = opts.find((o) => String(o.label) === String(name));
return hit ? hit.value : name;
},
+ // 瀵煎嚭 Excel锛氫竴娆″鍑烘暣椤典笁涓〃锛堝悇涓�涓� sheet锛夛紝鍜岄〉闈㈡樉绀轰繚鎸佷竴鑷�
exportTable(tableId) {
- const tableNames = {
- table1: "鍚勬湇鍔¢」鐩弧鎰忓害缁熻",
- table2: "鍏朵粬棰樼洰缁熻",
- table3: "鍚勭瀹ゆ弧鎰忓害璇勫垎瀵规瘮",
- };
- const name = tableNames[tableId] || "缁熻鏁版嵁";
- const table = document.getElementById(tableId);
- if (!table) return;
-
try {
- // 浠庤〃鏍兼彁鍙栨暟鎹瀯寤哄甫鏍峰紡鐨� Excel
+ const order = ["table1", "table2", "table3"];
+ if (tableId && order.indexOf(tableId) > 0) {
+ order.splice(order.indexOf(tableId), 1);
+ order.unshift(tableId);
+ }
+ const builders = {
+ table1: () => this.buildExportTable1(),
+ table2: () => this.buildExportTable2(),
+ table3: () => this.buildExportTable3(),
+ };
const wb = XLSX.utils.book_new();
- const data = [];
- table.querySelectorAll("tr").forEach((tr) => {
- const row = [];
- tr.querySelectorAll("th,td").forEach((td) => {
- row.push((td.innerText || "").trim());
- });
- if (row.length) data.push(row);
+ let count = 0;
+ order.forEach((id) => {
+ const sheet = builders[id]();
+ if (!sheet) return;
+ const ws = XLSX.utils.aoa_to_sheet(sheet.data);
+ ws["!merges"] = sheet.merges || [];
+ const widthRow = sheet.data.find((r) => r && r.length) || [];
+ ws["!cols"] = widthRow.map((_, i) => ({ wch: i === 0 ? 32 : 12 }));
+ XLSX.utils.book_append_sheet(wb, ws, sheet.name);
+ count++;
});
-
- const ws = XLSX.utils.aoa_to_sheet(data);
- // 璁剧疆鍒楀
- const colWidths = data[0] ? data[0].map(() => ({ wch: 16 })) : [];
- ws["!cols"] = colWidths;
-
- XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
- XLSX.writeFile(wb, name + ".xlsx");
+ if (!count) {
+ this.$message.warning("娌℃湁鍙鍑虹殑鏁版嵁");
+ return;
+ }
+ XLSX.writeFile(wb, "婊℃剰搴︽暟鎹�昏.xlsx");
+ this.$message.success("瀵煎嚭鎴愬姛");
} catch (e) {
- // fallback: CSV
- let csv = "锘�";
- table.querySelectorAll("tr").forEach((tr) => {
- const row = [];
- tr.querySelectorAll("th,td").forEach((td) =>
- row.push('"' + (td.innerText || "").replace(/"/g, '""') + '"')
- );
- csv += row.join(",") + "\n";
- });
- const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
- const link = document.createElement("a");
- link.href = URL.createObjectURL(blob);
- link.download = name + ".csv";
- link.click();
+ console.error("瀵煎嚭澶辫触:", e);
+ this.$message.error("瀵煎嚭澶辫触锛�" + (e.message || e));
}
},
+
+ // 琛ㄤ竴锛氬悇鏈嶅姟椤圭洰婊℃剰搴︾粺璁�
+ buildExportTable1() {
+ const rows = this.serviceSatisfaction || [];
+ if (!rows.length) return null;
+ const data = [
+ ["鍚勬湇鍔¢」鐩弧鎰忓害缁熻锛堝叚妗h瘎鍒嗛锛氬緢婊℃剰/婊℃剰/涓�鑸�/涓嶆弧鎰�/寰堜笉婊℃剰/鏈粡鍘嗭級"],
+ [
+ "鍒嗙被/棰樼洰",
+ "寰堟弧鎰�", "", "婊℃剰", "", "涓�鑸�", "",
+ "涓嶆弧鎰�", "", "寰堜笉婊℃剰", "", "鏈粡鍘�", "",
+ "缁煎悎寰楀垎",
+ ],
+ [
+ "",
+ "鏁伴噺", "姣斾緥", "鏁伴噺", "姣斾緥", "鏁伴噺", "姣斾緥",
+ "鏁伴噺", "姣斾緥", "鏁伴噺", "姣斾緥", "鏁伴噺", "姣斾緥",
+ "",
+ ],
+ ];
+ rows.forEach((r) => {
+ data.push([
+ r.category,
+ r.veryGoodCount, r.veryGoodRate,
+ r.goodCount, r.goodRate,
+ r.normalCount, r.normalRate,
+ r.badCount, r.badRate,
+ r.veryBadCount, r.veryBadRate,
+ r.naCount, r.naRate,
+ r.score,
+ ]);
+ });
+ const merges = [
+ { s: { r: 0, c: 0 }, e: { r: 0, c: 13 } },
+ { s: { r: 1, c: 0 }, e: { r: 2, c: 0 } },
+ ];
+ for (let i = 0; i < 6; i++) {
+ merges.push({ s: { r: 1, c: 1 + i * 2 }, e: { r: 1, c: 2 + i * 2 } });
+ }
+ merges.push({ s: { r: 1, c: 13 }, e: { r: 2, c: 13 } });
+ return { name: "鍚勬湇鍔¢」鐩弧鎰忓害", data, merges };
+ },
+
+ // 琛ㄤ簩锛氬叾浠栭鐩粺璁★紙姣忛涓�鍧楋細棰樼洰鏍囬 鈫� 閫夐」/鏁伴噺/姣斾緥 鈫� 鏈濉姤鎬婚噺锛�
+ buildExportTable2() {
+ const list = this.filteredQuestionStats || [];
+ if (!list.length) return null;
+ const data = [
+ ["鍏朵粬棰樼洰缁熻锛堝叚妗f弧鎰忓害棰樺凡鍦ㄤ笂琛紝杩欓噷鍙垪鍏朵綑棰樺瀷锛氭帹鑽愩�佹姳鎬ㄥ洖搴斻�佹剰瑙佺瓑锛�"],
+ [],
+ ];
+ const merges = [{ s: { r: 0, c: 0 }, e: { r: 0, c: 2 } }];
+ list.forEach((q) => {
+ data.push([q.title, "", ""]);
+ merges.push({
+ s: { r: data.length - 1, c: 0 },
+ e: { r: data.length - 1, c: 2 },
+ });
+ data.push(["閫夐」", "鏁伴噺", "姣斾緥"]);
+ const opts =
+ q.options && q.options.length
+ ? q.options
+ : [{ option: "锛堟棤閫夐」锛�", count: 0, rate: "-" }];
+ opts.forEach((o) => {
+ data.push([o.option, o.count, o.rate]);
+ });
+ data.push([`鏈濉姤鎬婚噺锛�${q.total}`, "", ""]);
+ merges.push({
+ s: { r: data.length - 1, c: 0 },
+ e: { r: data.length - 1, c: 2 },
+ });
+ data.push([]);
+ });
+ return { name: "鍏朵粬棰樼洰缁熻", data, merges };
+ },
+
+ // 琛ㄤ笁锛氬悇绉戝/鐥呭尯婊℃剰搴﹁瘎鍒嗗姣旓紙涓よ鍔ㄦ�佽〃澶达級
+ buildExportTable3() {
+ const rows = this.table3Rows || [];
+ const questions = this.table3Questions || [];
+ if (!rows.length) return null;
+ const head1 = [this.statDimension === "dept" ? "绉戝" : "鐥呭尯"];
+ const head2 = [""];
+ const groups = [];
+ questions.forEach((q) => {
+ const opts = q.options || [];
+ const startCol = head1.length;
+ head1.push(q.title);
+ for (let i = 1; i < opts.length + 1; i++) head1.push("");
+ groups.push({ start: startCol, end: startCol + opts.length });
+ opts.forEach((opt) => head2.push(opt));
+ head2.push("寰楀垎");
+ });
+ head1.push("缁煎悎寰楀垎");
+ head2.push("");
+ const data = [["鍚勭瀹�/鐥呭尯婊℃剰搴﹁瘎鍒嗗姣�"], head1, head2];
+ const merges = [
+ { s: { r: 0, c: 0 }, e: { r: 0, c: head1.length - 1 } },
+ { s: { r: 1, c: 0 }, e: { r: 2, c: 0 } },
+ {
+ s: { r: 1, c: head1.length - 1 },
+ e: { r: 2, c: head1.length - 1 },
+ },
+ ];
+ groups.forEach((g) => {
+ if (g.end > g.start) {
+ merges.push({ s: { r: 1, c: g.start }, e: { r: 1, c: g.end } });
+ }
+ });
+ rows.forEach((row) => {
+ const line = [row.name];
+ questions.forEach((q) => {
+ const cell = (row.cells && row.cells[q.title]) || {};
+ (q.options || []).forEach((opt) => {
+ line.push((cell[opt] && cell[opt].count) || 0);
+ });
+ line.push(cell._score || "0.00");
+ });
+ line.push(row.totalScore);
+ data.push(line);
+ });
+ return { name: "鍚勭瀹ょ梾鍖鸿瘎鍒嗗姣�", data, merges };
+ },
},
};
</script>
diff --git a/src/views/Satisfaction/sfstatistics/components/FollowupStatistics.vue b/src/views/Satisfaction/sfstatistics/components/FollowupStatistics.vue
index 754e244..c299b30 100644
--- a/src/views/Satisfaction/sfstatistics/components/FollowupStatistics.vue
+++ b/src/views/Satisfaction/sfstatistics/components/FollowupStatistics.vue
@@ -401,8 +401,8 @@
data() {
return {
// 婊℃剰搴︾被鍨嬶細leave=绂婚櫌婊℃剰搴︼紙鎸夊嚭闄㈢梾鍖虹粺璁★級锛宧ospital=鍦ㄩ櫌婊℃剰搴︼紙鎸夊湪闄㈢梾鍖虹粺璁★級
- // 榛樿鍦ㄩ櫌婊℃剰搴�
- satisfactionScope: "hospital",
+ // 榛樿绂婚櫌婊℃剰搴�
+ satisfactionScope: "leave",
// 鏌ヨ鍙傛暟
queryParams: {
@@ -432,7 +432,7 @@
options: [
{
value: 6,
- label: "浣忛櫌婊℃剰搴�",
+ label: "鍑哄叆闄㈡弧鎰忓害",
raw: {
cssClass: "",
listClass: "",
@@ -539,8 +539,11 @@
// 鑾峰彇绉戝鏍�
getDeptTree() {
- // 鑾峰彇鏈嶅姟绫诲瀷
- this.options = this.$store.getters.tasktypes || [];
+ // 鑾峰彇鏈嶅姟绫诲瀷锛堝瓧鍏搁噷鐨勩�屼綇闄㈡弧鎰忓害銆嶅湪鏈〉鏄剧ず涓恒�屽嚭鍏ラ櫌婊℃剰搴︺�嶏級
+ const labelFix = { 浣忛櫌婊℃剰搴�: "鍑哄叆闄㈡弧鎰忓害" };
+ this.options = (this.$store.getters.tasktypes || []).map((o) =>
+ labelFix[o.label] ? { ...o, label: labelFix[o.label] } : o
+ );
// 鑾峰彇绉戝鍒楄〃
this.flatArraydept = (this.$store.getters.belongDepts || []).map(
@@ -854,9 +857,9 @@
this.getList();
},
- // 閲嶇疆鏌ヨ锛堟仮澶嶉粯璁わ細鍦ㄩ櫌婊℃剰搴� + 鏈嶅姟绫诲瀷 6锛�
+ // 閲嶇疆鏌ヨ锛堟仮澶嶉粯璁わ細绂婚櫌婊℃剰搴� + 鏈嶅姟绫诲瀷 6锛�
resetQuery() {
- this.satisfactionScope = "hospital";
+ this.satisfactionScope = "leave";
this.queryParams = {
statisticaltype: 1,
leavehospitaldistrictcodes: [],
@@ -1087,15 +1090,9 @@
},
};
- // 娣诲姞鎬绘爣棰橈紙涓ゅ垪缁村害 + 鍏釜鎸囨爣鍒楋紝鍏� 10 鍒楋級
- worksheet.mergeCells(1, 1, 1, 10);
- const titleCell = worksheet.getCell(1, 1);
- titleCell.value = `婊℃剰搴﹂殢璁跨粺璁¤〃锛�${sheetNameSuffix}锛塦;
- titleCell.style = titleStyle;
- worksheet.getRow(1).height = 35;
-
- // 娣诲姞琛ㄥご锛堢瀹ょ粺璁″鍑哄湪闄㈢瀹�+绂婚櫌绉戝锛岀梾鍖虹粺璁″鍑哄湪闄㈢梾鍖�+绂婚櫌鐥呭尯锛�
+ // 琛ㄥご鎸夐〉闈㈠垪鍔ㄦ�佺敓鎴愶細绉戝/鐥呭尯缁熻鍒椾笉鍚岋紝銆屽強鏃剁巼銆嶅彧鏈夋櫙瀹侀櫌鍖洪〉闈㈡墠鏄剧ず
const isWardStatistics = this.queryParams.statisticaltype == 1;
+ const showTimelyRate = this.orgname === "鏅畞鐣叉棌鑷不鍘夸汉姘戝尰闄�";
const headers = [
isWardStatistics ? "鍦ㄩ櫌鐥呭尯" : "鍦ㄩ櫌绉戝",
isWardStatistics ? "绂婚櫌鐥呭尯" : "绂婚櫌绉戝",
@@ -1103,11 +1100,19 @@
"鏃犻渶闅忚浜烘",
"搴旈殢璁夸汉娆�",
"闅忚鐜�",
- "鍙婃椂鐜�",
- "婊℃剰搴﹂鐩�婚噺",
- "婊℃剰搴﹀~鎶ラ噺",
- "瀹屾垚姣旂巼",
];
+ if (showTimelyRate) {
+ headers.push("鍙婃椂鐜�");
+ }
+ headers.push("婊℃剰搴﹂鐩�婚噺", "婊℃剰搴﹀~鎶ラ噺", "瀹屾垚姣旂巼");
+ const colCount = headers.length;
+
+ // 娣诲姞鎬绘爣棰�
+ worksheet.mergeCells(1, 1, 1, colCount);
+ const titleCell = worksheet.getCell(1, 1);
+ titleCell.value = `婊℃剰搴﹂殢璁跨粺璁¤〃锛�${sheetNameSuffix}锛塦;
+ titleCell.style = titleStyle;
+ worksheet.getRow(1).height = 35;
const headerRow = worksheet.addRow(headers);
headerRow.eachCell((cell) => {
@@ -1115,9 +1120,13 @@
});
headerRow.height = 25;
- // 娣诲姞鏁版嵁琛�
+ // 娣诲姞鏁版嵁琛岋紙绌哄�肩粺涓�鏄剧ず鈥�-鈥濓紝涓庨〉闈繚鎸佷竴鑷达級
+ const dash = (v, formatter) => {
+ if (v === null || v === undefined || v === "") return "-";
+ return formatter ? formatter(v) : v;
+ };
this.userList.forEach((item) => {
- const dataRow = worksheet.addRow([
+ const rowData = [
isWardStatistics
? item.hospitaldistrictname || "-"
: item.hospitaldeptname || "-",
@@ -1127,12 +1136,17 @@
item.dischargeCount || 0,
item.nonFollowUp || 0,
item.followUpNeeded || 0,
- item.followUpRate || "0%",
- item.rate ? this.formatPercent(item.rate) : "0%",
+ dash(item.followUpRate),
+ ];
+ if (showTimelyRate) {
+ rowData.push(dash(item.rate, (v) => this.formatPercent(v)));
+ }
+ rowData.push(
item.joyAllCount || 0,
item.joyCount || 0,
- item.joyTotal ? this.formatPercent(item.joyTotal) : "0%",
- ]);
+ dash(item.joyTotal, (v) => this.formatPercent(v))
+ );
+ const dataRow = worksheet.addRow(rowData);
dataRow.eachCell((cell) => {
cell.style = cellStyle;
@@ -1140,19 +1154,10 @@
dataRow.height = 22;
});
- // 璁剧疆鍒楀
- worksheet.columns = [
- { width: 20 },
- { width: 20 },
- { width: 12 },
- { width: 12 },
- { width: 12 },
- { width: 12 },
- { width: 12 },
- { width: 15 },
- { width: 15 },
- { width: 12 },
- ];
+ // 璁剧疆鍒楀锛堣窡鍒楁暟涓�鑷达級
+ worksheet.columns = headers.map((h, i) => ({
+ width: i < 2 ? 20 : h.length > 6 ? 15 : 12,
+ }));
// 鐢熸垚骞朵笅杞芥枃浠�
const buffer = await workbook.xlsx.writeBuffer();
diff --git a/src/views/Satisfaction/sfstatistics/components/SatisfactionStatistics.vue b/src/views/Satisfaction/sfstatistics/components/SatisfactionStatistics.vue
index eda31ce..ec34803 100644
--- a/src/views/Satisfaction/sfstatistics/components/SatisfactionStatistics.vue
+++ b/src/views/Satisfaction/sfstatistics/components/SatisfactionStatistics.vue
@@ -14,7 +14,7 @@
<el-form-item label="婊℃剰搴︾被鍨�" prop="satisfactionScope">
<el-select
v-model="satisfactionScope"
- placeholder="榛樿鍦ㄩ櫌"
+ placeholder="榛樿绂婚櫌"
clearable
style="width: 140px"
@change="handleSearch"
@@ -104,6 +104,14 @@
</el-button>
<el-button icon="el-icon-refresh" @click="handleReset">
閲嶇疆
+ </el-button>
+ <el-button
+ type="warning"
+ icon="el-icon-download"
+ :loading="exporting"
+ @click="handleExportExcel"
+ >
+ 瀵煎嚭Excel
</el-button>
</el-form-item>
</el-form>
@@ -683,6 +691,9 @@
<script>
import * as echarts from "echarts";
+import * as XLSX from "xlsx";
+import ExcelJS from "exceljs";
+import { saveAs } from "file-saver";
import {
statistics,
satisfactionGraph,
@@ -698,8 +709,8 @@
return {
// 婊℃剰搴︾被鍨嬶細leave=绂婚櫌婊℃剰搴︼紙leaveldeptcodes/leavehospitaldistrictcodes锛夛紝
// hospital=鍦ㄩ櫌婊℃剰搴︼紙deptcodes/hospitaldistrictcodes锛�
- // 榛樿鍦ㄩ櫌锛氫繚鎸佽椤靛師鏈夎姹傚弬鏁颁笉鍙�
- satisfactionScope: "hospital",
+ // 榛樿绂婚櫌婊℃剰搴�
+ satisfactionScope: "leave",
// 鏌ヨ鍙傛暟
queryParams: {
type: 2,
@@ -737,6 +748,8 @@
// 棰樼洰鏄庣粏鏁版嵁
questionDetailData: [],
+ // 棰樼洰鏄庣粏鍏ㄩ噺鏁版嵁锛堝鍑虹敤锛屼笉鍙楀垎椤靛奖鍝嶏級
+ questionDetailAll: [],
// 缁村害棰樼洰鏄庣粏鏁版嵁
dimensionDetailData: [],
@@ -771,6 +784,9 @@
// 鍚勭被鍨嬬粺璁℃槑缁嗘暟鎹�
typeDetailData: [],
+
+ // 瀵煎嚭涓紙鎸夐挳 loading锛�
+ exporting: false,
// 鏌辩姸鍥炬暟鎹�
chartData: [],
@@ -1229,6 +1245,8 @@
const endIndex = startIndex + this.detailQueryParams.pageSize;
const paginatedData = detailData.slice(startIndex, endIndex);
+ // 瀵煎嚭鐢細淇濈暀涓嶅垎椤电殑鍏ㄩ噺鏁版嵁
+ this.questionDetailAll = detailData;
this.questionDetailData = paginatedData;
this.detailTotal = detailData.length;
this.totalAnswerCount = apiData.totalPerson || 0;
@@ -2059,6 +2077,8 @@
// 澶勭悊閲嶇疆
handleReset() {
this.$refs.queryForm.resetFields();
+ // 閲嶇疆鍚庡洖鍒伴粯璁ょ殑绂婚櫌婊℃剰搴�
+ this.satisfactionScope = "leave";
this.queryParams.dateRange = [];
this.queryParams.deptCodes = []; // 閲嶇疆涓烘暟缁�
this.queryParams.wardCodes = []; // 閲嶇疆涓烘暟缁�
@@ -2120,11 +2140,327 @@
this.$message.info(`鏌ョ湅绫诲瀷璇︽儏锛�${row.typeName}`);
},
- // 澶勭悊瀵煎嚭鏁版嵁
+ // 澶勭悊瀵煎嚭鏁版嵁锛氭寜椤甸潰杩欏紶绫诲瀷琛ㄧ殑鍒楀鍑鸿琛�
handleExportData(row) {
- this.$message.success(`姝e湪瀵煎嚭 ${row.typeName} 鏁版嵁...`);
+ if (!row) {
+ this.$message.warning("娌℃湁鍙鍑虹殑鏁版嵁");
+ return;
+ }
+ try {
+ const data = [
+ [`婊℃剰搴︾被鍨嬬粺璁★紙${row.typeName || ""}锛塦],
+ ["搴忓彿", "婊℃剰搴︾被鍨�", "鍙戦�侀棶鍗锋暟", "鍥炴敹闂嵎鏁�", "鍥炴敹鐜�", "骞冲潎鍒�", "婊℃剰搴︾瓑绾�"],
+ [
+ row.id,
+ row.typeName || "",
+ Number(row.sendCount) || 0,
+ Number(row.receiveCount) || 0,
+ this.formatPercent(row.recoveryRate),
+ Number(row.averageScore || 0).toFixed(1),
+ row.satisfactionLevel || "",
+ ],
+ ];
+ const ws = XLSX.utils.aoa_to_sheet(data);
+ ws["!merges"] = [{ s: { r: 0, c: 0 }, e: { r: 0, c: 6 } }];
+ ws["!cols"] = [
+ { wch: 8 },
+ { wch: 22 },
+ { wch: 14 },
+ { wch: 14 },
+ { wch: 12 },
+ { wch: 10 },
+ { wch: 12 },
+ ];
+ const wb = XLSX.utils.book_new();
+ XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
+ XLSX.writeFile(wb, `婊℃剰搴︾被鍨嬬粺璁${row.typeName || "瀵煎嚭"}.xlsx`);
+ this.$message.success("瀵煎嚭鎴愬姛");
+ } catch (e) {
+ console.error("瀵煎嚭澶辫触:", e);
+ this.$message.error("瀵煎嚭澶辫触锛�" + (e.message || e));
+ }
},
+ // 瀵煎嚭锛氫袱寮犲浘琛紙婊℃剰搴︾被鍨嬨�佺淮搴︾粺璁★紝鍥惧拰椤甸潰涓�鑷达級+ 涓夊紶鏄庣粏琛紙鍏ㄩ噺锛屼笉鍒嗛〉锛夛紝澶� sheet
+ async handleExportExcel() {
+ if (this.exporting) return;
+ this.exporting = true;
+ try {
+ // 涓夊紶鏄庣粏琛ㄦ槸鍒囧埌瀵瑰簲椤电鎵嶅姞杞界殑锛屽鍑哄墠鍏堣ˉ榻愭暟鎹紝閬垮厤瀵煎嚭绌鸿〃
+ await this.ensureDetailDataLoaded();
+ const wb = new ExcelJS.Workbook();
+
+ // 1銆�2锛氬浘琛� sheet锛堟弧鎰忓害绫诲瀷 / 缁村害缁熻锛�
+ const typeInfo = await this.captureChartImage("satisfactionType");
+ this.addChartSheet(wb, "婊℃剰搴︾被鍨�", "婊℃剰搴︾被鍨嬪~鎶ユ瘮渚嬬粺璁�", typeInfo);
+ const dimInfo = await this.captureChartImage("dimension");
+ this.addChartSheet(wb, "缁村害缁熻", "缁村害濉姤姣斾緥缁熻", dimInfo);
+
+ // 3锛氶鐩槑缁嗙粺璁★紙鍏ㄩ噺锛�
+ const qList =
+ this.questionDetailAll && this.questionDetailAll.length
+ ? this.questionDetailAll
+ : this.questionDetailData || [];
+ this.addTableSheet(
+ wb,
+ "棰樼洰鏄庣粏缁熻",
+ ["搴忓彿", "棰樼洰", "骞冲潎寰楀垎", "鏈�楂樺緱鍒�", "鏈�浣庡緱鍒�", "绛旈浜烘暟", "鏈瓟棰樹汉鏁�", "绛旈鐜�"],
+ qList.map((r, i) => [
+ i + 1,
+ r.scriptContent || "",
+ this.fix1(r.averageScore),
+ this.fix1(r.maxScore),
+ this.fix1(r.minScore),
+ r.answerCount || 0,
+ r.noAnswerPerson || 0,
+ this.formatPercent(r.answerRate),
+ ])
+ );
+
+ // 4锛氱淮搴﹂鐩槑缁嗭紙搴忓彿銆侀鐩�佺淮搴︺�佸钩鍧�/鏈�楂�/鏈�浣庡緱鍒嗐�佺瓟棰樹汉鏁般�佹湭绛旈浜烘暟銆佺瓟棰樼巼锛�
+ this.addTableSheet(
+ wb,
+ "缁村害棰樼洰鏄庣粏",
+ [
+ "搴忓彿",
+ "棰樼洰",
+ "缁村害",
+ "骞冲潎寰楀垎",
+ "鏈�楂樺緱鍒�",
+ "鏈�浣庡緱鍒�",
+ "绛旈浜烘暟",
+ "鏈瓟棰樹汉鏁�",
+ "绛旈鐜�",
+ ],
+ (this.dimensionDetailData || []).map((r, i) => [
+ i + 1,
+ r.scriptContent || "",
+ r.dimension ? this.getDimensionLabel(r.dimension) : r.dimensionName || "",
+ this.fix1(r.averageScore),
+ this.fix1(r.maxScore),
+ this.fix1(r.minScore),
+ r.answerPerson || 0,
+ r.noAnswerPerson || 0,
+ this.formatPercent(r.answerRate),
+ ])
+ );
+
+ // 5锛氬悇绫诲瀷缁熻鏄庣粏
+ this.addTableSheet(
+ wb,
+ "鍚勭被鍨嬬粺璁℃槑缁�",
+ ["搴忓彿", "婊℃剰搴︾被鍨�", "鍙戦�侀棶鍗锋暟", "鍥炴敹闂嵎鏁�", "鍥炴敹鐜�", "骞冲潎鍒�", "婊℃剰搴︾瓑绾�"],
+ (this.typeDetailData || []).map((r, i) => [
+ i + 1,
+ r.typeName || "",
+ r.sendCount || 0,
+ r.receiveCount || 0,
+ this.formatPercent(r.recoveryRate),
+ this.fix1(r.averageScore),
+ r.satisfactionLevel || "",
+ ])
+ );
+
+ const buffer = await wb.xlsx.writeBuffer();
+ const blob = new Blob([buffer], {
+ type:
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+ });
+ const suffix =
+ this.startTime && this.endTime
+ ? `_${String(this.startTime).slice(0, 10)}_${String(this.endTime).slice(0, 10)}`
+ : "";
+ saveAs(blob, `婊℃剰搴︽槑缁嗙粺璁�${suffix}.xlsx`);
+ this.$message.success("瀵煎嚭鎴愬姛");
+ } catch (e) {
+ console.error("瀵煎嚭澶辫触:", e);
+ this.$message.error("瀵煎嚭澶辫触锛�" + (e.message || e));
+ } finally {
+ this.exporting = false;
+ }
+ },
+
+ // 瀵煎嚭鍓嶈ˉ榻愪笁寮犳槑缁嗚〃鐨勬暟鎹紙椤甸潰鏄垏椤电鎵嶅姞杞斤紝娌″垏杩囩殑琛ㄦ槸绌虹殑锛�
+ async ensureDetailDataLoaded() {
+ const tasks = [];
+ if (!this.questionDetailAll || !this.questionDetailAll.length) {
+ tasks.push(this.loadQuestionDetailData());
+ }
+ if (!this.dimensionDetailData || !this.dimensionDetailData.length) {
+ tasks.push(this.loadDimensionDetailData());
+ }
+ if (!this.typeDetailData || !this.typeDetailData.length) {
+ tasks.push(this.loadTypeDetailData());
+ }
+ if (tasks.length) {
+ await Promise.all(tasks);
+ }
+ },
+
+ // 淇濈暀涓�浣嶅皬鏁帮紝绌哄�兼樉绀� -
+ fix1(v) {
+ if (v === null || v === undefined || v === "") return "-";
+ const n = Number(v);
+ return isNaN(n) ? "-" : n.toFixed(1);
+ },
+
+ // 鍥捐〃 sheet锛氭爣棰� + 姹囨�� + 鍥捐〃鍥剧墖
+ addChartSheet(wb, sheetName, title, info) {
+ const ws = wb.addWorksheet(sheetName, {
+ views: [{ showGridLines: false }],
+ });
+ ws.getCell("A1").value = title;
+ ws.getCell("A1").font = { size: 14, bold: true };
+ ws.mergeCells("A1:F1");
+ const rate =
+ info && info.totalSend
+ ? this.formatPercent(info.totalReceive / info.totalSend)
+ : "-";
+ ws.getCell("A2").value = `鍙戦�侀鐩�婚噺锛�${(info && info.totalSend) || 0} 鍥炴敹棰樼洰鎬婚噺锛�${(info && info.totalReceive) || 0} 鎬讳綋鍥炴敹鐜囷細${rate}`;
+ ws.mergeCells("A2:F2");
+ for (let c = 1; c <= 6; c++) {
+ ws.getColumn(c).width = 18;
+ }
+ if (info && info.url) {
+ const imgId = wb.addImage({
+ base64: info.url.split(",")[1],
+ extension: "png",
+ });
+ ws.addImage(imgId, {
+ tl: { col: 0.1, row: 3.1 },
+ ext: { width: 940, height: 420 },
+ });
+ } else {
+ ws.getCell("A4").value = "鏆傛棤鏁版嵁";
+ }
+ return ws;
+ },
+
+ // 鏅�氳〃鏍� sheet锛氭爣棰� + 琛ㄥご + 鏁版嵁
+ addTableSheet(wb, sheetName, headers, rows) {
+ const ws = wb.addWorksheet(sheetName);
+ ws.addRow([sheetName]).font = { size: 14, bold: true };
+ ws.mergeCells(1, 1, 1, Math.max(headers.length, 1));
+ const headerRow = ws.addRow(headers);
+ headerRow.eachCell((cell) => {
+ cell.font = { bold: true };
+ cell.alignment = { horizontal: "center", vertical: "middle" };
+ cell.fill = {
+ type: "pattern",
+ pattern: "solid",
+ fgColor: { argb: "FFF5F7FA" },
+ };
+ });
+ if (!rows || !rows.length) {
+ ws.addRow(["鏆傛棤鏁版嵁"]);
+ } else {
+ rows.forEach((r) => {
+ const row = ws.addRow(r);
+ row.eachCell((cell) => {
+ cell.alignment = { horizontal: "center", vertical: "middle" };
+ });
+ });
+ }
+ ws.columns.forEach((col, i) => {
+ col.width = i === 1 ? 40 : 14;
+ });
+ return ws;
+ },
+
+ // 鍙栨煇涓浘琛ㄩ〉绛剧殑鏁版嵁锛堜笉鏀瑰彉椤甸潰鐘舵�侊級
+ async fetchChartRows(chartType) {
+ const rows = [];
+ let totalSend = 0;
+ let totalReceive = 0;
+ let index = 0;
+
+ if (chartType === "dimension") {
+ const params = {
+ type: this.queryParams.type,
+ startTime: this.startTime,
+ endTime: this.endTime,
+ ...this.buildScopeParams(),
+ templateid: this.templateId,
+ questionType: this.queryParams.type || null,
+ serviceTypes: this.defaultServiceTypes,
+ dimensionList: this.dimensionList,
+ };
+ const res = await satisfactionGraphDimension(params);
+ Object.entries((res && res.rows) || {}).forEach(([code, stat]) => {
+ const sendCount = stat.subidAll || 0;
+ const receiveCount = stat.fillCountAll || 0;
+ const rate = stat.receiveRate || 0;
+ rows.push({
+ name: this.getDimensionLabel(code),
+ value: (rate * 100).toFixed(2),
+ sendCount: sendCount,
+ receiveCount: receiveCount,
+ averageScore: stat.averageScore || 0,
+ dimension: code,
+ itemStyle: { color: this.getChartColor(index++) },
+ });
+ totalSend += sendCount;
+ totalReceive += receiveCount;
+ });
+ } else {
+ const params = {
+ type: this.queryParams.type,
+ startTime: this.startTime,
+ endTime: this.endTime,
+ ...this.buildScopeParams(),
+ templateid: this.templateId,
+ };
+ const res = await satisfactionGraph(params);
+ Object.entries((res && res.rows) || {}).forEach(([name, stat]) => {
+ const sendCount = stat.subidAll || 0;
+ const receiveCount = stat.fillCountAll || 0;
+ const rate = stat.receiveRate || 0;
+ rows.push({
+ name: name,
+ value: (rate * 100).toFixed(2),
+ sendCount: sendCount,
+ receiveCount: receiveCount,
+ averageScore: stat.averageScore || 0,
+ itemStyle: { color: this.getChartColor(index++) },
+ });
+ totalSend += sendCount;
+ totalReceive += receiveCount;
+ });
+ }
+ return { rows, totalSend, totalReceive };
+ },
+
+ // 绂诲睆娓叉煋鍥捐〃骞跺鍑� base64 鍥剧墖锛堝鐢ㄩ〉闈� renderChart 鐨勬牱寮忥紝淇濊瘉鍥惧拰椤甸潰涓�鑷达級
+ async captureChartImage(chartType) {
+ const info = await this.fetchChartRows(chartType);
+ if (!info.rows.length) {
+ return { ...info, url: null };
+ }
+ const div = document.createElement("div");
+ div.style.cssText =
+ "position:absolute;left:-99999px;top:0;width:1000px;height:400px;";
+ document.body.appendChild(div);
+ const inst = echarts.init(div);
+ const prevChart = this.barChart;
+ try {
+ this.barChart = inst;
+ // 鍏抽棴鍔ㄧ敾锛氬惁鍒� getDataURL 鎴埌鐨勬槸鏌卞瓙杩樻病闀垮嚭鏉ョ殑绗竴甯э紙鍥鹃噷鏈夊潗鏍囪酱浣嗘病鏈夋煴瀛愶級
+ inst.setOption({ animation: false });
+ this.renderChart(info.rows, chartType);
+ // 绛変竴甯э紝纭繚 canvas 宸茬粡鐢诲畬
+ await new Promise((resolve) => setTimeout(resolve, 120));
+ const url = inst.getDataURL({
+ type: "png",
+ pixelRatio: 2,
+ backgroundColor: "#fff",
+ });
+ return { ...info, url };
+ } finally {
+ this.barChart = prevChart;
+ inst.dispose();
+ document.body.removeChild(div);
+ }
+ },
// 鏍煎紡鍖栫櫨鍒嗘瘮
formatPercent(value) {
if (value === null || value === undefined) return "-";
diff --git a/src/views/Satisfaction/sfstatistics/components/visitStatistics.vue b/src/views/Satisfaction/sfstatistics/components/visitStatistics.vue
index 2c7ed98..f2439a7 100644
--- a/src/views/Satisfaction/sfstatistics/components/visitStatistics.vue
+++ b/src/views/Satisfaction/sfstatistics/components/visitStatistics.vue
@@ -936,25 +936,27 @@
},
};
- // 娣诲姞鎬绘爣棰�
- worksheet.mergeCells(1, 1, 1, 10);
- const titleCell = worksheet.getCell(1, 1);
- titleCell.value = `澶嶈瘖閫氱煡缁熻琛紙${sheetNameSuffix}锛塦;
- titleCell.style = titleStyle;
- worksheet.getRow(1).height = 35;
-
- // 娣诲姞琛ㄥご
+ // 琛ㄥご鎸夐〉闈㈠垪鍔ㄦ�佺敓鎴愶細銆屽強鏃剁巼銆嶅彧鏈夋櫙瀹侀櫌鍖洪〉闈㈡墠鏄剧ず
+ const showTimelyRate = this.orgname === "鏅畞鐣叉棌鑷不鍘夸汉姘戝尰闄�";
const headers = [
this.queryParams.statisticaltype == 1 ? "鍑洪櫌鐥呭尯" : "绉戝",
"鍑洪櫌浜烘",
"鏃犻渶闅忚浜烘",
"搴旈殢璁夸汉娆�",
"闅忚鐜�",
- "鍙婃椂鐜�",
- "澶嶈瘖閫氱煡棰樼洰鎬婚噺",
- "澶嶈瘖閫氱煡濉姤閲�",
- "瀹屾垚姣旂巼",
];
+ if (showTimelyRate) {
+ headers.push("鍙婃椂鐜�");
+ }
+ headers.push("澶嶈瘖閫氱煡棰樼洰鎬婚噺", "澶嶈瘖閫氱煡濉姤閲�", "瀹屾垚姣旂巼");
+ const colCount = headers.length;
+
+ // 娣诲姞鎬绘爣棰�
+ worksheet.mergeCells(1, 1, 1, colCount);
+ const titleCell = worksheet.getCell(1, 1);
+ titleCell.value = `澶嶈瘖閫氱煡缁熻琛紙${sheetNameSuffix}锛塦;
+ titleCell.style = titleStyle;
+ worksheet.getRow(1).height = 35;
const headerRow = worksheet.addRow(headers);
headerRow.eachCell((cell) => {
@@ -962,21 +964,30 @@
});
headerRow.height = 25;
- // 娣诲姞鏁版嵁琛�
+ // 娣诲姞鏁版嵁琛岋紙绌哄�肩粺涓�鏄剧ず鈥�-鈥濓紝涓庨〉闈繚鎸佷竴鑷达級
+ const dash = (v, formatter) => {
+ if (v === null || v === undefined || v === "") return "-";
+ return formatter ? formatter(v) : v;
+ };
this.userList.forEach((item) => {
- const dataRow = worksheet.addRow([
+ const rowData = [
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%",
+ dash(item.followUpRate),
+ ];
+ if (showTimelyRate) {
+ rowData.push(dash(item.rate, (v) => this.formatPercent(v)));
+ }
+ rowData.push(
item.joyAllCount || 0,
item.joyCount || 0,
- item.joyTotal ? this.formatPercent(item.joyTotal) : "0%",
- ]);
+ dash(item.joyTotal, (v) => this.formatPercent(v))
+ );
+ const dataRow = worksheet.addRow(rowData);
dataRow.eachCell((cell) => {
cell.style = cellStyle;
@@ -984,18 +995,10 @@
dataRow.height = 22;
});
- // 璁剧疆鍒楀
- worksheet.columns = [
- { width: 20 },
- { width: 12 },
- { width: 12 },
- { width: 12 },
- { width: 12 },
- { width: 12 },
- { width: 15 },
- { width: 15 },
- { width: 12 },
- ];
+ // 璁剧疆鍒楀锛堣窡鍒楁暟涓�鑷达級
+ worksheet.columns = headers.map((h, i) => ({
+ width: i === 0 ? 20 : h.length > 6 ? 15 : 12,
+ }));
// 鐢熸垚骞朵笅杞芥枃浠�
const buffer = await workbook.xlsx.writeBuffer();
--
Gitblit v1.9.3