WXL (wul)
昨天 e06cd3953ba8a6e0eee11c235bce9ced419a2800
src/views/Satisfaction/sfstatistics/components/components/TopicDialog.vue
@@ -1,5 +1,18 @@
<template>
  <div class="topic-dialog">
    <div class="dialog-header">
      <span class="title"> {{ configTitle }}指标详情 </span>
      <el-button
        type="primary"
        size="mini"
        icon="el-icon-download"
        :disabled="!processedTopicList.length"
        @click="exportTopicDetail"
      >
        导出
      </el-button>
    </div>
    <div class="topicdia">
      <div style="overflow-x: hidden; overflow-y: auto; max-height: 65vh">
        <!-- 修改这里:使用 processedTopicList 而不是 topicList -->
@@ -74,6 +87,8 @@
</template>
<script>
import ExcelJS from "exceljs";
import { saveAs } from "file-saver";
export default {
  name: "TopicDialog",
  props: {
@@ -94,6 +109,13 @@
    return {
      processedTopicList: [], // 处理后的数据
    };
  },
  computed: {
    configTitle() {
      // 从父级 queryParams 中读取
      const key = this.queryParams?.configKey;
      return key === "returnVisitCount" ? "复诊通知" : "满意度";
    },
  },
  watch: {
    // 监听父组件传递的数据变化
@@ -141,7 +163,146 @@
      console.log("处理后的数据:", result);
      this.processedTopicList = result;
    },
    /** 导出题目明细 */
    async exportTopicDetail() {
      if (!this.processedTopicList.length) {
        this.$message.warning("暂无数据可导出");
        return;
      }
      const workbook = new ExcelJS.Workbook();
      const sheetName = `${
        this.rowData.leavehospitaldistrictname || this.rowData.deptname
      }${this.configTitle}明细`;
      const worksheet = workbook.addWorksheet(sheetName);
      /* ---------- 样式 ---------- */
      const titleStyle = {
        font: { name: "微软雅黑", size: 14, bold: true },
        alignment: { horizontal: "center", vertical: "middle" },
        fill: {
          type: "pattern",
          pattern: "solid",
          fgColor: { argb: "FFF5F7FA" },
        },
      };
      const subtitleStyle = {
        font: { name: "微软雅黑", size: 12, bold: true },
        alignment: { horizontal: "left", vertical: "middle" },
      };
      const headerStyle = {
        font: { name: "微软雅黑", size: 11, bold: true },
        fill: {
          type: "pattern",
          pattern: "solid",
          fgColor: { argb: "FFEBEEF5" },
        },
        alignment: { horizontal: "center", vertical: "middle" },
        border: {
          top: { style: "thin" },
          left: { style: "thin" },
          bottom: { style: "thin" },
          right: { style: "thin" },
        },
      };
      const cellStyle = {
        font: { name: "宋体", size: 10 },
        alignment: { horizontal: "center", vertical: "middle" },
        border: {
          top: { style: "thin" },
          left: { style: "thin" },
          bottom: { style: "thin" },
          right: { style: "thin" },
        },
      };
      /* ---------- 标题区 ---------- */
      worksheet.mergeCells(1, 1, 1, 4);
      worksheet.getCell(1, 1).value = `${this.configTitle}题目明细`;
      worksheet.getCell(1, 1).style = titleStyle;
      worksheet.mergeCells(2, 1, 2, 4);
      worksheet.getCell(2, 1).value = `统计对象:${
        this.rowData.leavehospitaldistrictname || this.rowData.deptname
      }`;
      worksheet.getCell(2, 1).style = subtitleStyle;
      worksheet.mergeCells(3, 1, 3, 4);
      worksheet.getCell(3, 1).value = `统计时间:${
        this.queryParams.dateRange?.[0] || "-"
      } 至 ${this.queryParams.dateRange?.[1] || "-"}`;
      worksheet.getCell(3, 1).style = subtitleStyle;
      let currentRow = 5;
      /* ---------- 逐题写入 ---------- */
      this.processedTopicList.forEach((item, index) => {
        worksheet.mergeCells(currentRow, 1, currentRow, 4);
        worksheet.getCell(currentRow, 1).value = `第${index + 1}题:${
          item.scriptContent
        } [${item.scriptType == 1 ? "单选题" : "多选题"}]`;
        worksheet.getCell(currentRow, 1).style = subtitleStyle;
        currentRow++;
        const headerRow = worksheet.addRow([
          "问题选项",
          "选择人数",
          "占比",
          "",
        ]);
        headerRow.eachCell((cell) => {
          cell.style = headerStyle;
        });
        currentRow++;
        item.details.forEach((detail) => {
          const percent =
            detail.chosenPercentage != null
              ? (Number(detail.chosenPercentage) * 100).toFixed(2) + "%"
              : "-";
          const row = worksheet.addRow([
            detail.optionText,
            detail.chosenQuantity || 0,
            percent,
            "",
          ]);
          row.eachCell((cell) => {
            cell.style = cellStyle;
          });
          currentRow++;
        });
        currentRow++;
      });
      /* ---------- 列宽 ---------- */
      worksheet.columns = [
        { width: 40 },
        { width: 12 },
        { width: 12 },
        { width: 10 },
      ];
      /* ---------- 导出 ---------- */
      const buffer = await workbook.xlsx.writeBuffer();
      const fileName =
        `${this.rowData.leavehospitaldistrictname || this.rowData.deptname}` +
        `${this.configTitle}明细_` +
        `${this.queryParams.dateRange?.[0]}至${this.queryParams.dateRange?.[1]}.xlsx`;
      saveAs(
        new Blob([buffer], {
          type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        }),
        fileName
      );
      this.$message.success("导出成功");
    },
    // 格式化百分比
    formatPercent(value) {
      if (value === null || value === undefined) return "-";
@@ -193,7 +354,20 @@
    overflow: hidden;
    font-size: 14px;
  }
  .dialog-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 12px 16px;
    border-bottom: 1px solid #ebeef5;
    background: #fafafa;
    .title {
      font-size: 16px;
      font-weight: 600;
      color: #303133;
    }
  }
  ::v-deep .el-table th {
    background-color: #f1f5f9;
    color: #333;