<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 -->
|
<div
|
v-for="(item, index) in processedTopicList"
|
:key="item.scriptid"
|
class="ttaabbcc"
|
>
|
<div class="describe">
|
第{{ index + 1 }}题: {{ item.scriptContent }}
|
<span>[{{ item.scriptType == 1 ? "单选题" : "多选题" }}]</span>
|
</div>
|
<div>
|
<el-table :data="item.details" style="width: 100%">
|
<el-table-column
|
prop="optionText"
|
label="问题选项"
|
align="center"
|
min-width="200"
|
/>
|
<el-table-column
|
prop="chosenQuantity"
|
label="选择人数"
|
align="center"
|
min-width="120"
|
>
|
<template slot-scope="{ row }">
|
{{ row.chosenQuantity || 0 }}
|
</template>
|
</el-table-column>
|
<el-table-column
|
prop="chosenPercentage"
|
label="比例"
|
align="center"
|
min-width="120"
|
>
|
<template slot-scope="{ row }">
|
<span
|
v-if="
|
row.chosenPercentage !== null &&
|
row.chosenPercentage !== undefined
|
"
|
>
|
{{ (Number(row.chosenPercentage) * 100).toFixed(2) }}%
|
</span>
|
<span v-else>-</span>
|
</template>
|
</el-table-column>
|
</el-table>
|
</div>
|
</div>
|
</div>
|
</div>
|
|
<!-- 如果没有数据 -->
|
<div
|
v-if="!processedTopicList.length"
|
class="no-data"
|
style="text-align: center; padding: 50px 0"
|
>
|
<el-empty description="暂无数据"></el-empty>
|
</div>
|
|
<div
|
slot="footer"
|
class="dialog-footer"
|
style="text-align: center; padding-top: 20px"
|
>
|
<el-button @click="handleClose">关 闭</el-button>
|
</div>
|
</div>
|
</template>
|
|
<script>
|
import ExcelJS from "exceljs";
|
import { saveAs } from "file-saver";
|
export default {
|
name: "TopicDialog",
|
props: {
|
rowData: {
|
type: Object,
|
default: () => ({}),
|
},
|
queryParams: {
|
type: Object,
|
default: () => ({}),
|
},
|
topicList: {
|
type: [Array, Object],
|
default: () => ({}),
|
},
|
},
|
data() {
|
return {
|
processedTopicList: [], // 处理后的数据
|
};
|
},
|
computed: {
|
configTitle() {
|
// 从父级 queryParams 中读取
|
const key = this.queryParams?.configKey;
|
return key === "returnVisitCount" ? "复诊通知" : "满意度";
|
},
|
},
|
watch: {
|
// 监听父组件传递的数据变化
|
topicList: {
|
immediate: true,
|
handler(newVal) {
|
console.log("TopicDialog接收到父组件数据:", newVal);
|
this.processTopicList(newVal);
|
},
|
},
|
},
|
mounted() {
|
console.log("TopicDialog mounted, props:", this.$props);
|
},
|
methods: {
|
// 处理topicList数据
|
processTopicList(data) {
|
console.log("开始处理数据:", data);
|
|
if (!data || typeof data !== "object") {
|
this.processedTopicList = [];
|
return;
|
}
|
|
// 将对象转换为数组
|
const result = [];
|
|
Object.keys(data).forEach((key) => {
|
const item = data[key];
|
if (item && item.scriptContent) {
|
// 深拷贝item,避免修改原数据
|
const processedItem = JSON.parse(JSON.stringify(item));
|
|
// 过滤details,只保留有选项文本的
|
if (processedItem.details && Array.isArray(processedItem.details)) {
|
processedItem.details = processedItem.details.filter(
|
(detail) => detail && detail.optionText
|
);
|
}
|
|
result.push(processedItem);
|
}
|
});
|
|
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 "-";
|
const num = parseFloat(value);
|
if (isNaN(num)) return "-";
|
return `${num.toFixed(2)}%`; // 注意:你的数据中百分比已经是0-100的形式
|
},
|
|
// 关闭对话框
|
handleClose() {
|
this.$emit("close");
|
},
|
},
|
};
|
</script>
|
|
<style lang="scss" scoped>
|
.topic-dialog {
|
.topicdia {
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
"Helvetica Neue", Arial, sans-serif;
|
color: #333;
|
}
|
|
.ttaabbcc {
|
background: #fafafa;
|
border-radius: 6px;
|
padding: 16px;
|
margin-bottom: 20px;
|
border-left: 4px solid #4794c5;
|
}
|
|
.describe {
|
font-size: 15px;
|
line-height: 1.6;
|
margin-bottom: 12px;
|
color: #1f2d3d;
|
}
|
|
.describe span {
|
font-size: 13px;
|
color: #999;
|
font-style: italic;
|
margin-left: 8px;
|
}
|
|
::v-deep .el-table {
|
border-radius: 4px;
|
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;
|
font-weight: 600;
|
}
|
|
::v-deep .el-table td {
|
border-bottom: 1px solid #f0f0f0;
|
padding: 12px 0;
|
}
|
}
|
</style>
|