<template>
|
<div class="data-overview">
|
<!-- 表格一:各服务项目满意度统计 -->
|
<el-card shadow="never" class="overview-card">
|
<div slot="header" class="card-header">
|
<span class="card-title">各服务项目满意度统计</span>
|
<el-button type="warning" size="small" icon="el-icon-download" @click="exportTable('table1')">导出Excel</el-button>
|
</div>
|
<el-table id="table1" :data="serviceSatisfaction" border size="small" :header-cell-style="{ background: '#f5f7fa', color: '#303133' }">
|
<el-table-column prop="category" label="分类/题目" min-width="220" fixed="left" />
|
<el-table-column label="非常满意" align="center">
|
<el-table-column prop="veryGoodCount" label="数量" width="90" />
|
<el-table-column prop="veryGoodRate" label="比例" width="90" />
|
</el-table-column>
|
<el-table-column label="满意" align="center">
|
<el-table-column prop="goodCount" label="数量" width="90" />
|
<el-table-column prop="goodRate" label="比例" width="90" />
|
</el-table-column>
|
<el-table-column label="一般" align="center">
|
<el-table-column prop="normalCount" label="数量" width="90" />
|
<el-table-column prop="normalRate" label="比例" width="90" />
|
</el-table-column>
|
<el-table-column label="不满意" align="center">
|
<el-table-column prop="badCount" label="数量" width="90" />
|
<el-table-column prop="badRate" label="比例" width="90" />
|
</el-table-column>
|
<el-table-column label="不适用" align="center">
|
<el-table-column prop="naCount" label="数量" width="90" />
|
<el-table-column prop="naRate" label="比例" width="90" />
|
</el-table-column>
|
<el-table-column prop="score" label="综合得分" width="100" align="center" />
|
</el-table>
|
</el-card>
|
|
<!-- 表格二:单选题/多选题统计 -->
|
<el-card shadow="never" class="overview-card">
|
<div slot="header" class="card-header">
|
<span class="card-title">单选题/多选题统计</span>
|
<el-button type="warning" size="small" icon="el-icon-download" @click="exportTable('table2')">导出Excel</el-button>
|
</div>
|
<div class="question-block" v-for="(q, qi) in questionStats" :key="qi">
|
<h4 class="q-title">{{ q.title }}</h4>
|
<el-table :data="q.options" border size="small" :header-cell-style="{ background: '#f5f7fa', color: '#303133' }">
|
<el-table-column prop="option" label="选项" min-width="180" />
|
<el-table-column prop="count" label="数量" width="100" align="center" />
|
<el-table-column prop="rate" label="比例" width="100" align="center" />
|
</el-table>
|
<div v-if="q.total" class="q-footer">本题有效填写人次:<b>{{ q.total }}</b></div>
|
</div>
|
</el-card>
|
|
<!-- 表格三:各科室满意度评分对比 -->
|
<el-card shadow="never" class="overview-card">
|
<div slot="header" class="card-header">
|
<span class="card-title">各科室满意度评分对比</span>
|
<el-button type="warning" size="small" icon="el-icon-download" @click="exportTable('table3')">导出Excel</el-button>
|
</div>
|
<el-table id="table3" :data="deptComparison" border size="small" :header-cell-style="{ background: '#f5f7fa', color: '#303133' }">
|
<el-table-column prop="dept" label="科室"fixed="left" align="center" />
|
<el-table-column label="第1题" align="center">
|
<el-table-column prop="q1VeryGood" label="非常满意" width="100" />
|
<el-table-column prop="q1Good" label="满意" width="90" />
|
<el-table-column prop="q1Normal" label="一般" width="90" />
|
<el-table-column prop="q1Bad" label="不满意" width="90" />
|
<el-table-column prop="q1Score" label="得分" width="100" />
|
</el-table-column>
|
<el-table-column label="第2题" align="center">
|
<el-table-column prop="q2VeryGood" label="非常满意" width="100" />
|
<el-table-column prop="q2Good" label="满意" width="90" />
|
<el-table-column prop="q2Normal" label="一般" width="90" />
|
<el-table-column prop="q2Bad" label="不满意" width="90" />
|
<el-table-column prop="q2Score" label="得分" width="100" />
|
</el-table-column>
|
<el-table-column prop="totalScore" label="综合得分" align="center" />
|
</el-table>
|
</el-card>
|
</div>
|
</template>
|
|
<script>
|
import XLSX from 'xlsx';
|
|
export default {
|
name: "DataOverview",
|
data() {
|
return {
|
serviceSatisfaction: [
|
{ category: "诊疗过程中,医务人员是否注意保护您的隐私?", veryGoodCount: 3219, veryGoodRate: "67.84%", goodCount: 1351, goodRate: "28.47%", normalCount: 142, normalRate: "2.99%", badCount: 33, badRate: "0.70%", naCount: 0, naRate: "0.00%", score: "87.82" },
|
{ category: "您对医院服务设施的总体印象如何?", veryGoodCount: 3110, veryGoodRate: "65.54%", goodCount: 1369, goodRate: "28.85%", normalCount: 217, normalRate: "4.57%", badCount: 49, badRate: "1.03%", naCount: 0, naRate: "0.00%", score: "86.30" },
|
{ category: "医院的厕所是否清洁无异味?", veryGoodCount: 2973, veryGoodRate: "62.66%", goodCount: 1504, goodRate: "31.70%", normalCount: 235, normalRate: "4.95%", badCount: 33, badRate: "0.70%", naCount: 0, naRate: "0.00%", score: "85.44" },
|
{ category: "医院内的路标和指示是否明确?", veryGoodCount: 3234, veryGoodRate: "68.16%", goodCount: 1289, goodRate: "27.17%", normalCount: 196, normalRate: "4.13%", badCount: 26, badRate: "0.55%", naCount: 0, naRate: "0.00%", score: "87.64" },
|
{ category: "医院的空间布局是否便利?", veryGoodCount: 3037, veryGoodRate: "64.00%", goodCount: 1460, goodRate: "30.77%", normalCount: 209, normalRate: "4.40%", badCount: 39, badRate: "0.82%", naCount: 0, naRate: "0.00%", score: "85.99" },
|
{ category: "看病期间,您的抱怨和不满能否及时得到回应?", veryGoodCount: 3019, veryGoodRate: "63.62%", goodCount: 1317, goodRate: "27.76%", normalCount: 294, normalRate: "6.20%", badCount: 115, badRate: "2.42%", naCount: 0, naRate: "0.00%", score: "84.19" },
|
{ category: "医生是否用您听得懂的方式解释问题?", veryGoodCount: 3402, veryGoodRate: "71.70%", goodCount: 967, goodRate: "20.38%", normalCount: 254, normalRate: "5.35%", badCount: 122, badRate: "2.57%", naCount: 0, naRate: "0.00%", score: "87.07" },
|
{ category: "医生对您是否尊重?", veryGoodCount: 3495, veryGoodRate: "73.66%", goodCount: 897, goodRate: "18.90%", normalCount: 249, normalRate: "5.25%", badCount: 104, badRate: "2.19%", naCount: 0, naRate: "0.00%", score: "88.01" },
|
{ category: "医生是否仔细倾听您讲话?", veryGoodCount: 3422, veryGoodRate: "72.12%", goodCount: 937, goodRate: "19.75%", normalCount: 251, normalRate: "5.29%", badCount: 135, badRate: "2.85%", naCount: 0, naRate: "0.00%", score: "87.05" },
|
{ category: "对挂号服务人员服务态度是否满意", veryGoodCount: 3458, veryGoodRate: "72.88%", goodCount: 1205, goodRate: "25.40%", normalCount: 52, normalRate: "1.10%", badCount: 30, badRate: "0.63%", naCount: 0, naRate: "0.00%", score: "90.17" },
|
{ category: "您对预约挂号是否满意?", veryGoodCount: 3527, veryGoodRate: "74.33%", goodCount: 1088, goodRate: "22.93%", normalCount: 72, normalRate: "1.52%", badCount: 58, badRate: "1.22%", naCount: 0, naRate: "0.00%", score: "90.12" },
|
{ category: "护士对您是否尊重?", veryGoodCount: 3420, veryGoodRate: "72.08%", goodCount: 1184, goodRate: "24.95%", normalCount: 113, normalRate: "2.38%", badCount: 28, badRate: "0.59%", naCount: 0, naRate: "0.00%", score: "89.50" },
|
{ category: "护士是否用您听得懂的方式解释问题?", veryGoodCount: 3346, veryGoodRate: "70.52%", goodCount: 1250, goodRate: "26.34%", normalCount: 122, normalRate: "2.57%", badCount: 27, badRate: "0.57%", naCount: 0, naRate: "0.00%", score: "88.94" },
|
{ category: "护士是否仔细倾听您讲话?", veryGoodCount: 3378, veryGoodRate: "71.19%", goodCount: 1205, goodRate: "25.40%", normalCount: 134, normalRate: "2.82%", badCount: 28, badRate: "0.59%", naCount: 0, naRate: "0.00%", score: "89.06" },
|
{ category: "总计", veryGoodCount: 54863, veryGoodRate: "69.02%", goodCount: 20800, goodRate: "26.17%", normalCount: 2920, normalRate: "3.67%", badCount: 908, badRate: "1.14%", naCount: 0, naRate: "0.00%", score: "87.66" },
|
],
|
questionStats: [
|
{
|
title: "第1题:您对我院工作人员的服务质量满意不满意?【分值单选题】- 综合得分",
|
options: [
|
{ option: "非常满意", count: 1084, rate: "75.66%" },
|
{ option: "满意", count: 1959, rate: "20.92%" },
|
{ option: "一般", count: 167, rate: "1.78%" },
|
{ option: "不满意", count: 153, rate: "1.63%" },
|
],
|
total: 3363
|
},
|
{
|
title: "第2题:您对哪部分服务不满意?【多选题】",
|
options: [
|
{ option: "医生诊断和诊疗", count: 131, rate: "32.11%" },
|
{ option: "护理服务", count: 47, rate: "11.52%" },
|
{ option: "其他医务人员技术水平", count: 30, rate: "7.33%" },
|
{ option: "工人", count: 72, rate: "17.65%" },
|
],
|
total: 408
|
},
|
{
|
title: "第3题:医生诊断和治疗中哪些服务质量不满意?【多选题】",
|
options: [
|
{ option: "医生诊断错误", count: 23, rate: "15.44%" },
|
{ option: "对治疗效果不满意", count: 72, rate: "48.32%" },
|
{ option: "其他", count: 54, rate: "36.24%" },
|
],
|
total: 131
|
},
|
],
|
deptComparison: [
|
{ dept: "内分泌科", q1VeryGood: 103, q1Good: 34, q1Normal: 0, q1Bad: 0, q1Score: "377.00", q2VeryGood: 101, q2Good: 35, q2Normal: 1, q2Bad: 0, q2Score: "374.00", totalScore: "75.25" },
|
{ dept: "皮肤科", q1VeryGood: 112, q1Good: 25, q1Normal: 2, q1Bad: 3, q1Score: "388.00", q2VeryGood: 111, q2Good: 27, q2Normal: 3, q2Bad: 1, q2Score: "390.00", totalScore: "76.12" },
|
{ dept: "肿瘤内科", q1VeryGood: 24, q1Good: 12, q1Normal: 2, q1Bad: 0, q1Score: "98.00", q2VeryGood: 25, q2Good: 12, q2Normal: 1, q2Bad: 0, q2Score: "100.00", totalScore: "70.22" },
|
{ dept: "消化内科", q1VeryGood: 180, q1Good: 52, q1Normal: 1, q1Bad: 0, q1Score: "645.00", q2VeryGood: 168, q2Good: 62, q2Normal: 3, q2Bad: 0, q2Score: "631.00", totalScore: "73.56" },
|
{ dept: "肾内科", q1VeryGood: 21, q1Good: 4, q1Normal: 0, q1Bad: 0, q1Score: "71.00", q2VeryGood: 19, q2Good: 6, q2Normal: 0, q2Bad: 0, q2Score: "65.00", totalScore: "68.50" },
|
],
|
};
|
},
|
methods: {
|
exportTable(tableId) {
|
const tableNames = { table1: '各服务项目满意度统计', table2: '单选题多选题统计', table3: '各科室满意度评分对比' };
|
const name = tableNames[tableId] || '统计数据';
|
const table = document.getElementById(tableId);
|
if (!table) return;
|
|
try {
|
// 从表格提取数据构建带样式的 Excel
|
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);
|
});
|
|
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');
|
} 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();
|
}
|
},
|
},
|
};
|
</script>
|
|
<style lang="scss" scoped>
|
.data-overview { .overview-card { margin-bottom: 20px; } }
|
.card-header { display: flex; justify-content: space-between; align-items: center; }
|
.card-title { font-size: 16px; font-weight: 600; color: #303133; }
|
.question-block { margin-bottom: 24px;
|
.q-title { margin: 0 0 12px 0; font-size: 14px; color: #606266; }
|
.q-footer { margin-top: 8px; font-size: 13px; color: #909399; text-align: right; }
|
}
|
</style>
|