From e06cd3953ba8a6e0eee11c235bce9ced419a2800 Mon Sep 17 00:00:00 2001
From: WXL (wul) <wl_5969728@163.com>
Date: 星期三, 03 六月 2026 14:05:08 +0800
Subject: [PATCH] 测试完成
---
src/views/sfstatistics/percentage/components/SecondFollowUp.vue | 1640 ++++++++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 1,315 insertions(+), 325 deletions(-)
diff --git a/src/views/sfstatistics/percentage/components/SecondFollowUp.vue b/src/views/sfstatistics/percentage/components/SecondFollowUp.vue
index 4b03076..c3a6bae 100644
--- a/src/views/sfstatistics/percentage/components/SecondFollowUp.vue
+++ b/src/views/sfstatistics/percentage/components/SecondFollowUp.vue
@@ -25,21 +25,329 @@
show-summary
:summary-method="getInnerSummaries"
>
+ <el-table-column label="" align="center" width="96" fixed="right">
+ <template slot="header">
+ <div
+ style="
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ "
+ >
+ <el-button
+ type="primary"
+ size="mini"
+ icon="el-icon-download"
+ @click="exportDoctorTable(props.row)"
+ >
+ 瀵煎嚭
+ </el-button>
+ </div>
+ </template>
+ </el-table-column>
<el-table-column label="鍖荤敓濮撳悕" prop="drname" align="center" />
- <el-table-column label="绉戝" width="120" prop="deptname" align="center" />
- <el-table-column label="鍑洪櫌浜烘" prop="dischargeCount" align="center" />
- <el-table-column label="鏃犻渶闅忚浜烘" align="center" width="100" key="nonFollowUp" prop="nonFollowUp" />
- <el-table-column label="搴旈殢璁夸汉娆�" align="center" width="100" key="followUpNeeded" prop="followUpNeeded" />
+ <el-table-column
+ label="绉戝"
+ width="120"
+ prop="deptname"
+ align="center"
+ />
+ <el-table-column
+ label="鍑洪櫌浜烘"
+ prop="dischargeCount"
+ align="center"
+ >
+ <template slot-scope="scope">
+ <el-button
+ size="medium"
+ type="text"
+ @click="
+ handleViewDetails(
+ scope.row,
+ 'dischargeCountInfo',
+ '鍑洪櫌鎮h�呭垪琛�',
+ '1'
+ )
+ "
+ >
+ <span class="button-zx">{{
+ scope.row.dischargeCount
+ }}</span>
+ </el-button>
+ </template>
+ </el-table-column>
+ <el-table-column
+ label="鏃犻渶闅忚浜烘"
+ align="center"
+ width="100"
+ key="nonFollowUp"
+ prop="nonFollowUp"
+ >
+ <template slot-scope="scope">
+ <el-button
+ size="medium"
+ type="text"
+ @click="
+ handleViewDetails(
+ scope.row,
+ 'nonFollowUpInfo',
+ '鏃犻渶闅忚鍒楄〃',
+ '1'
+ )
+ "
+ >
+ <span class="button-zx">{{ scope.row.nonFollowUp }}</span>
+ </el-button>
+ </template>
+ </el-table-column>
+ <el-table-column
+ label="搴旈殢璁夸汉娆�"
+ align="center"
+ width="100"
+ key="followUpNeeded"
+ prop="followUpNeeded"
+ >
+ <template slot-scope="scope">
+ <el-button
+ size="medium"
+ type="text"
+ @click="
+ handleViewDetails(
+ scope.row,
+ 'followUpNeededInfo',
+ '搴旈殢璁垮垪琛�',
+ '1'
+ )
+ "
+ >
+ <span class="button-zx">{{
+ scope.row.followUpNeeded
+ }}</span>
+ </el-button>
+ </template>
+ </el-table-column>
<el-table-column align="center" label="鍐嶆鍑洪櫌闅忚">
- <el-table-column label="闇�闅忚" align="center" key="needFollowUpAgain" prop="needFollowUpAgain" />
- <el-table-column label="寰呴殢璁�" align="center" key="pendingFollowUpAgain" prop="pendingFollowUpAgain" />
- <el-table-column label="闅忚鎴愬姛" align="center" key="followUpSuccessAgain" prop="followUpSuccessAgain" />
- <el-table-column label="闅忚澶辫触" align="center" key="followUpFailAgain" prop="followUpFailAgain" />
- <el-table-column label="闅忚鐜�" align="center" width="120" key="followUpRateAgain" prop="followUpRateAgain" />
- <el-table-column v-if="orgname != '涓芥按甯備腑鍖婚櫌'" label="浜哄伐" align="center" key="manualAgain" prop="manualAgain" />
- <el-table-column v-if="orgname != '涓芥按甯備腑鍖婚櫌'" label="鐭俊" align="center" key="smsAgain" prop="smsAgain" />
- <el-table-column v-if="orgname != '涓芥按甯備腑鍖婚櫌'" label="寰俊" align="center" key="weChatAgain" prop="weChatAgain" />
+ <el-table-column
+ label="闇�闅忚"
+ align="center"
+ key="needFollowUpAgain"
+ prop="needFollowUpAgain"
+ >
+ <template slot-scope="scope">
+ <el-button
+ size="medium"
+ type="text"
+ @click="
+ handleViewDetails(
+ scope.row,
+ 'needFollowUpAgainInfo',
+ '闇�闅忚鍒楄〃',
+ '1'
+ )
+ "
+ >
+ <span class="button-zx">{{
+ scope.row.needFollowUpAgain
+ }}</span>
+ </el-button>
+ </template>
+ </el-table-column>
+ <el-table-column
+ label="寰呴殢璁�"
+ align="center"
+ key="pendingFollowUpAgain"
+ prop="pendingFollowUpAgain"
+ >
+ <template slot-scope="scope">
+ <el-button
+ size="medium"
+ type="text"
+ @click="
+ handleViewDetails(
+ scope.row,
+ 'pendingFollowUpAgainInfo',
+ '寰呴殢璁垮垪琛�',
+ '1'
+ )
+ "
+ >
+ <span class="button-zx">{{
+ scope.row.pendingFollowUpAgain
+ }}</span>
+ </el-button>
+ </template>
+ </el-table-column>
+ <el-table-column
+ label="闅忚鎴愬姛"
+ align="center"
+ key="followUpSuccessAgain"
+ prop="followUpSuccessAgain"
+ >
+ <template slot-scope="scope">
+ <el-button
+ size="medium"
+ type="text"
+ @click="
+ handleViewDetails(
+ scope.row,
+ 'followUpSuccessAgainInfo',
+ '闅忚鎴愬姛鍒楄〃',
+ '1'
+ )
+ "
+ >
+ <span class="button-zx">{{
+ scope.row.followUpSuccessAgain
+ }}</span>
+ </el-button>
+ </template>
+ </el-table-column>
+ <el-table-column
+ label="闅忚澶辫触"
+ align="center"
+ key="followUpFailAgain"
+ prop="followUpFailAgain"
+ >
+ <template slot-scope="scope">
+ <el-button
+ size="medium"
+ type="text"
+ @click="
+ handleViewDetails(
+ scope.row,
+ 'followUpFailAgainInfo',
+ '闅忚澶辫触鍒楄〃',
+ '1'
+ )
+ "
+ >
+ <span class="button-zx">{{
+ scope.row.followUpFailAgain
+ }}</span>
+ </el-button>
+ </template>
+ </el-table-column>
+ <el-table-column
+ label="鎴愬姛鐜�"
+ align="center"
+ width="120"
+ key="successRateAgain"
+ prop="successRateAgain"
+ >
+ <template slot-scope="scope">
+ <span class="success-rate">{{
+ calculateSuccessRate(
+ scope.row.followUpSuccessAgain,
+ scope.row.needFollowUpAgain,
+ scope.row.pendingFollowUpAgain
+ )
+ }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column
+ label="闅忚鐜�"
+ align="center"
+ width="120"
+ key="followUpRateAgain"
+ prop="followUpRateAgain"
+ />
+ <el-table-column
+ v-if="orgname != '涓芥按甯備腑鍖婚櫌'"
+ label="浜哄伐"
+ align="center"
+ key="manualAgain"
+ prop="manualAgain"
+ >
+ <template slot-scope="scope">
+ <el-button
+ size="medium"
+ type="text"
+ @click="
+ handleViewDetails(
+ scope.row,
+ 'manualAgainInfo',
+ '浜哄伐闅忚鍒楄〃',
+ '1'
+ )
+ "
+ >
+ <span class="button-zx">{{ scope.row.manualAgain }}</span>
+ </el-button>
+ </template>
+ </el-table-column>
+ <el-table-column
+ v-if="orgname != '涓芥按甯備腑鍖婚櫌'"
+ label="璇煶"
+ align="center"
+ key="voiceAgain"
+ prop="voiceAgain"
+ >
+ <template slot-scope="scope">
+ <el-button
+ size="medium"
+ type="text"
+ @click="
+ handleViewDetails(
+ scope.row,
+ 'voiceAgainInfo',
+ '璇煶闅忚鍒楄〃',
+ '1'
+ )
+ "
+ >
+ <span class="button-zx">{{ scope.row.voiceAgain }}</span>
+ </el-button>
+ </template>
+ </el-table-column>
+ <el-table-column
+ v-if="orgname != '涓芥按甯備腑鍖婚櫌'"
+ label="鐭俊"
+ align="center"
+ key="smsAgain"
+ prop="smsAgain"
+ >
+ <template slot-scope="scope">
+ <el-button
+ size="medium"
+ type="text"
+ @click="
+ handleViewDetails(
+ scope.row,
+ 'smsAgainInfo',
+ '鐭俊闅忚鍒楄〃',
+ '1'
+ )
+ "
+ >
+ <span class="button-zx">{{ scope.row.smsAgain }}</span>
+ </el-button>
+ </template>
+ </el-table-column>
+ <el-table-column
+ v-if="orgname != '涓芥按甯備腑鍖婚櫌'"
+ label="寰俊"
+ align="center"
+ key="weChatAgain"
+ prop="weChatAgain"
+ >
+ <template slot-scope="scope">
+ <el-button
+ size="medium"
+ type="text"
+ @click="
+ handleViewDetails(
+ scope.row,
+ 'weChatAgainInfo',
+ '寰俊闅忚鍒楄〃',
+ '1'
+ )
+ "
+ >
+ <span class="button-zx">{{ scope.row.weChatAgain }}</span>
+ </el-button>
+ </template>
+ </el-table-column>
</el-table-column>
</el-table>
</template>
@@ -47,6 +355,7 @@
<!-- 琛ㄦ牸鍒楀畾涔� -->
<el-table-column
+ v-if="queryParams.statisticaltype == 1"
label="鍑洪櫌鐥呭尯"
align="center"
sortable
@@ -56,58 +365,276 @@
:show-overflow-tooltip="true"
:sort-method="sortChineseNumber"
/>
- <el-table-column label="绉戝" align="center" key="deptname" prop="deptname" :show-overflow-tooltip="true" />
- <el-table-column label="鍑洪櫌浜烘" align="center" key="dischargeCount" prop="dischargeCount" />
- <el-table-column label="鏃犻渶闅忚浜烘" align="center" width="100" key="nonFollowUp" prop="nonFollowUp" />
- <el-table-column label="搴旈殢璁夸汉娆�" align="center" width="100" key="followUpNeeded" prop="followUpNeeded" />
+ <el-table-column
+ v-if="queryParams.statisticaltype == 2"
+ label="绉戝"
+ align="center"
+ key="deptname"
+ prop="deptname"
+ :show-overflow-tooltip="true"
+ />
+ <el-table-column
+ label="鍑洪櫌浜烘"
+ align="center"
+ key="dischargeCount"
+ prop="dischargeCount"
+ >
+ <template slot-scope="scope">
+ <el-button
+ size="medium"
+ type="text"
+ @click="
+ handleViewDetails(
+ scope.row,
+ 'dischargeCountInfo',
+ '鍑洪櫌鎮h�呭垪琛�'
+ )
+ "
+ >
+ <span class="button-zx">{{ scope.row.dischargeCount }}</span>
+ </el-button>
+ </template>
+ </el-table-column>
+ <el-table-column
+ label="鏃犻渶闅忚浜烘"
+ align="center"
+ width="100"
+ key="nonFollowUp"
+ prop="nonFollowUp"
+ >
+ <template slot-scope="scope">
+ <el-button
+ size="medium"
+ type="text"
+ @click="
+ handleViewDetails(scope.row, 'nonFollowUpInfo', '鏃犻渶闅忚鍒楄〃')
+ "
+ >
+ <span class="button-zx">{{ scope.row.nonFollowUp }}</span>
+ </el-button>
+ </template>
+ </el-table-column>
+ <el-table-column
+ label="搴旈殢璁夸汉娆�"
+ align="center"
+ width="100"
+ key="followUpNeeded"
+ prop="followUpNeeded"
+ >
+ <template slot-scope="scope">
+ <el-button
+ size="medium"
+ type="text"
+ @click="
+ handleViewDetails(scope.row, 'followUpNeededInfo', '搴旈殢璁垮垪琛�')
+ "
+ >
+ <span class="button-zx">{{ scope.row.followUpNeeded }}</span>
+ </el-button>
+ </template>
+ </el-table-column>
<el-table-column align="center" label="鍐嶆鍑洪櫌闅忚">
- <el-table-column label="闇�闅忚" align="center" key="needFollowUpAgain" prop="needFollowUpAgain">
+ <el-table-column
+ label="闇�闅忚"
+ align="center"
+ key="needFollowUpAgain"
+ prop="needFollowUpAgain"
+ >
<template slot-scope="scope">
- <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'needFollowUpAgainInfo', '鍐嶆闅忚闇�闅忚鍒楄〃')">
+ <el-button
+ size="medium"
+ type="text"
+ @click="
+ handleViewDetails(
+ scope.row,
+ 'needFollowUpAgainInfo',
+ '鍐嶆闅忚闇�闅忚鍒楄〃'
+ )
+ "
+ >
<span class="button-zx">{{ scope.row.needFollowUpAgain }}</span>
</el-button>
</template>
</el-table-column>
- <el-table-column label="寰呴殢璁�" align="center" key="pendingFollowUpAgain" prop="pendingFollowUpAgain">
+ <el-table-column
+ label="寰呴殢璁�"
+ align="center"
+ key="pendingFollowUpAgain"
+ prop="pendingFollowUpAgain"
+ >
<template slot-scope="scope">
- <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'pendingFollowUpAgainInfo', '鍐嶆闅忚寰呴殢璁垮垪琛�')">
- <span class="button-zx">{{ scope.row.pendingFollowUpAgain }}</span>
+ <el-button
+ size="medium"
+ type="text"
+ @click="
+ handleViewDetails(
+ scope.row,
+ 'pendingFollowUpAgainInfo',
+ '鍐嶆闅忚寰呴殢璁垮垪琛�'
+ )
+ "
+ >
+ <span class="button-zx">{{
+ scope.row.pendingFollowUpAgain
+ }}</span>
</el-button>
</template>
</el-table-column>
- <el-table-column label="闅忚鎴愬姛" align="center" key="followUpSuccessAgain" prop="followUpSuccessAgain">
+ <el-table-column
+ label="闅忚鎴愬姛"
+ align="center"
+ key="followUpSuccessAgain"
+ prop="followUpSuccessAgain"
+ >
<template slot-scope="scope">
- <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'followUpSuccessAgainInfo', '鍐嶆闅忚闅忚鎴愬姛鍒楄〃')">
- <span class="button-zx">{{ scope.row.followUpSuccessAgain }}</span>
+ <el-button
+ size="medium"
+ type="text"
+ @click="
+ handleViewDetails(
+ scope.row,
+ 'followUpSuccessAgainInfo',
+ '鍐嶆闅忚闅忚鎴愬姛鍒楄〃'
+ )
+ "
+ >
+ <span class="button-zx">{{
+ scope.row.followUpSuccessAgain
+ }}</span>
</el-button>
</template>
</el-table-column>
- <el-table-column label="闅忚澶辫触" align="center" key="followUpFailAgain" prop="followUpFailAgain">
+ <el-table-column
+ label="闅忚澶辫触"
+ align="center"
+ key="followUpFailAgain"
+ prop="followUpFailAgain"
+ >
<template slot-scope="scope">
- <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'followUpFailAgainInfo', '鍐嶆闅忚闅忚澶辫触鍒楄〃')">
+ <el-button
+ size="medium"
+ type="text"
+ @click="
+ handleViewDetails(
+ scope.row,
+ 'followUpFailAgainInfo',
+ '鍐嶆闅忚闅忚澶辫触鍒楄〃'
+ )
+ "
+ >
<span class="button-zx">{{ scope.row.followUpFailAgain }}</span>
</el-button>
</template>
</el-table-column>
- <el-table-column label="闅忚鐜�" align="center" width="120" key="followUpRateAgain" prop="followUpRateAgain" />
- <el-table-column v-if="orgname != '涓芥按甯備腑鍖婚櫌'" label="浜哄伐" align="center" key="manualAgain" prop="manualAgain">
+ <el-table-column
+ label="鎴愬姛鐜�"
+ align="center"
+ width="120"
+ key="successRateAgain"
+ prop="successRateAgain"
+ >
<template slot-scope="scope">
- <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'manualAgainInfo', '鍐嶆闅忚浜哄伐闅忚鍒楄〃')">
+ <span class="success-rate">{{
+ calculateSuccessRate(
+ scope.row.followUpSuccessAgain,
+ scope.row.needFollowUpAgain,
+ scope.row.pendingFollowUpAgain
+ )
+ }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column
+ label="闅忚鐜�"
+ align="center"
+ width="120"
+ key="followUpRateAgain"
+ prop="followUpRateAgain"
+ />
+ <el-table-column
+ v-if="orgname != '涓芥按甯備腑鍖婚櫌'"
+ label="浜哄伐"
+ align="center"
+ key="manualAgain"
+ prop="manualAgain"
+ >
+ <template slot-scope="scope">
+ <el-button
+ size="medium"
+ type="text"
+ @click="
+ handleViewDetails(
+ scope.row,
+ 'manualAgainInfo',
+ '鍐嶆闅忚浜哄伐闅忚鍒楄〃'
+ )
+ "
+ >
<span class="button-zx">{{ scope.row.manualAgain }}</span>
</el-button>
</template>
</el-table-column>
- <el-table-column v-if="orgname != '涓芥按甯備腑鍖婚櫌'" label="鐭俊" align="center" key="smsAgain" prop="smsAgain">
+ <el-table-column
+ v-if="orgname != '涓芥按甯備腑鍖婚櫌'"
+ label="璇煶"
+ align="center"
+ key="voiceAgain"
+ prop="voiceAgain"
+ >
<template slot-scope="scope">
- <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'smsAgainInfo', '鍐嶆闅忚鐭俊闅忚鍒楄〃')">
+ <el-button
+ size="medium"
+ type="text"
+ @click="
+ handleViewDetails(scope.row, 'voiceAgainInfo', '璇煶闅忚鍒楄〃')
+ "
+ >
+ <span class="button-zx">{{ scope.row.voiceAgain }}</span>
+ </el-button>
+ </template>
+ </el-table-column>
+ <el-table-column
+ v-if="orgname != '涓芥按甯備腑鍖婚櫌'"
+ label="鐭俊"
+ align="center"
+ key="smsAgain"
+ prop="smsAgain"
+ >
+ <template slot-scope="scope">
+ <el-button
+ size="medium"
+ type="text"
+ @click="
+ handleViewDetails(
+ scope.row,
+ 'smsAgainInfo',
+ '鍐嶆闅忚鐭俊闅忚鍒楄〃'
+ )
+ "
+ >
<span class="button-zx">{{ scope.row.smsAgain }}</span>
</el-button>
</template>
</el-table-column>
- <el-table-column v-if="orgname != '涓芥按甯備腑鍖婚櫌'" label="寰俊" align="center" key="weChatAgain" prop="weChatAgain">
+ <el-table-column
+ v-if="orgname != '涓芥按甯備腑鍖婚櫌'"
+ label="寰俊"
+ align="center"
+ key="weChatAgain"
+ prop="weChatAgain"
+ >
<template slot-scope="scope">
- <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'weChatAgainInfo', '鍐嶆闅忚寰俊闅忚鍒楄〃')">
+ <el-button
+ size="medium"
+ type="text"
+ @click="
+ handleViewDetails(
+ scope.row,
+ 'weChatAgainInfo',
+ '鍐嶆闅忚寰俊闅忚鍒楄〃'
+ )
+ "
+ >
<span class="button-zx">{{ scope.row.weChatAgain }}</span>
</el-button>
</template>
@@ -124,163 +651,251 @@
import { saveAs } from "file-saver";
export default {
- name: 'SecondFollowUp',
+ name: "SecondFollowUp",
props: {
queryParams: {
type: Object,
- required: true
+ required: true,
},
flatArrayhospit: {
type: Array,
- default: () => []
+ default: () => [],
},
flatArraydept: {
type: Array,
- default: () => []
+ default: () => [],
},
options: {
type: Array,
- default: () => []
+ default: () => [],
},
orgname: {
type: String,
- default: ''
- }
+ default: "",
+ },
},
data() {
return {
tableData: [],
loading: false,
expands: [],
- ids: []
- }
+ ids: [],
+ };
},
methods: {
loadData() {
- this.loading = true
+ this.loading = true;
const params = {
...this.queryParams,
visitCount: 2,
- leavehospitaldistrictcodes: this.queryParams.leavehospitaldistrictcodes.includes("all")
- ? this.getAllWardCodes()
- : this.queryParams.leavehospitaldistrictcodes,
+ leavehospitaldistrictcodes:
+ this.queryParams.leavehospitaldistrictcodes.includes("all")
+ ? this.getAllWardCodes()
+ : this.queryParams.leavehospitaldistrictcodes,
deptcodes: this.queryParams.deptcodes.includes("all")
? this.getAllDeptCodes()
- : this.queryParams.deptcodes
- }
+ : this.queryParams.deptcodes,
+ };
- delete params.leavehospitaldistrictcodes.all
- delete params.deptcodes.all
+ delete params.leavehospitaldistrictcodes.all;
+ delete params.deptcodes.all;
+ params.rateDay = 7;
getSfStatistics(params)
- .then(response => {
- this.tableData = this.customSort(response.data)
+ .then((response) => {
+ this.tableData = this.customSort(response.data);
})
- .catch(error => {
- console.error("鑾峰彇鍐嶆闅忚鏁版嵁澶辫触:", error)
- this.$message.error("鑾峰彇鍐嶆闅忚鏁版嵁澶辫触")
+ .catch((error) => {
+ console.error("鑾峰彇鍐嶆闅忚鏁版嵁澶辫触:", error);
+ this.$message.error("鑾峰彇鍐嶆闅忚鏁版嵁澶辫触");
})
.finally(() => {
- this.loading = false
- })
+ this.loading = false;
+ });
},
getAllWardCodes() {
return this.flatArrayhospit
- .filter(item => item.value !== 'all')
- .map(item => item.value)
+ .filter((item) => item.value !== "all")
+ .map((item) => item.value);
},
getAllDeptCodes() {
return this.flatArraydept
- .filter(item => item.value !== 'all')
- .map(item => item.value)
+ .filter((item) => item.value !== "all")
+ .map((item) => item.value);
},
customSort(data) {
const order = [
- "涓�","浜�","涓�","鍥�","浜�","鍏�","涓�","鍏�","涔�","鍗�",
- "鍗佷竴","鍗佷簩","鍗佷笁","鍗佸洓","鍗佷簲","鍗佸叚","鍗佷竷","鍗佸叓","鍗佷節","浜屽崄",
- "浜屽崄涓�","浜屽崄浜�","浜屽崄涓�","浜屽崄鍥�","浜屽崄浜�","浜屽崄鍏�","浜屽崄涓�","浜屽崄鍏�","浜屽崄涔�","涓夊崄",
- "涓夊崄涓�","涓夊崄浜�","涓夊崄涓�","涓夊崄鍥�","涓夊崄浜�","涓夊崄鍏�","涓夊崄涓�","涓夊崄鍏�","涓夊崄涔�","鍥涘崄",
- "鍥涘崄涓�","鍥涘崄浜�","鍥涘崄涓�","鍥涘崄鍥�","鍥涘崄浜�"
- ]
+ "涓�",
+ "浜�",
+ "涓�",
+ "鍥�",
+ "浜�",
+ "鍏�",
+ "涓�",
+ "鍏�",
+ "涔�",
+ "鍗�",
+ "鍗佷竴",
+ "鍗佷簩",
+ "鍗佷笁",
+ "鍗佸洓",
+ "鍗佷簲",
+ "鍗佸叚",
+ "鍗佷竷",
+ "鍗佸叓",
+ "鍗佷節",
+ "浜屽崄",
+ "浜屽崄涓�",
+ "浜屽崄浜�",
+ "浜屽崄涓�",
+ "浜屽崄鍥�",
+ "浜屽崄浜�",
+ "浜屽崄鍏�",
+ "浜屽崄涓�",
+ "浜屽崄鍏�",
+ "浜屽崄涔�",
+ "涓夊崄",
+ "涓夊崄涓�",
+ "涓夊崄浜�",
+ "涓夊崄涓�",
+ "涓夊崄鍥�",
+ "涓夊崄浜�",
+ "涓夊崄鍏�",
+ "涓夊崄涓�",
+ "涓夊崄鍏�",
+ "涓夊崄涔�",
+ "鍥涘崄",
+ "鍥涘崄涓�",
+ "鍥涘崄浜�",
+ "鍥涘崄涓�",
+ "鍥涘崄鍥�",
+ "鍥涘崄浜�",
+ ];
return data.sort((a, b) => {
const getIndex = (name) => {
- if (!name || typeof name !== "string") return -1
- const chineseMatch = name.match(/^([涓�浜屼笁鍥涗簲鍏竷鍏節鍗乚+)/)
+ if (!name || typeof name !== "string") return -1;
+ const chineseMatch = name.match(/^([涓�浜屼笁鍥涗簲鍏竷鍏節鍗乚+)/);
if (chineseMatch && chineseMatch[1]) {
- return order.indexOf(chineseMatch[1])
+ return order.indexOf(chineseMatch[1]);
}
- const arabicMatch = name.match(/^(\d+)/)
+ const arabicMatch = name.match(/^(\d+)/);
if (arabicMatch && arabicMatch[1]) {
- const num = parseInt(arabicMatch[1], 10)
+ const num = parseInt(arabicMatch[1], 10);
if (num >= 1 && num <= 45) {
- return num - 1
+ return num - 1;
}
}
- return -1
- }
+ return -1;
+ };
- const indexA = getIndex(a.leavehospitaldistrictname)
- const indexB = getIndex(b.leavehospitaldistrictname)
+ const indexA = getIndex(a.leavehospitaldistrictname);
+ const indexB = getIndex(b.leavehospitaldistrictname);
if (indexA === -1 && indexB === -1) {
- return (a.leavehospitaldistrictname || "").localeCompare(b.leavehospitaldistrictname || "")
+ return (a.leavehospitaldistrictname || "").localeCompare(
+ b.leavehospitaldistrictname || ""
+ );
}
- if (indexA === -1) return 1
- if (indexB === -1) return -1
- return indexA - indexB
- })
+ if (indexA === -1) return 1;
+ if (indexB === -1) return -1;
+ return indexA - indexB;
+ });
},
sortChineseNumber(aRow, bRow) {
- const a = aRow.leavehospitaldistrictname
- const b = bRow.leavehospitaldistrictname
+ const a = aRow.leavehospitaldistrictname;
+ const b = bRow.leavehospitaldistrictname;
const chineseNumMap = {
- 涓�:1,浜�:2,涓�:3,鍥�:4,浜�:5,鍏�:6,涓�:7,鍏�:8,涔�:9,鍗�:10,
- 鍗佷竴:11,鍗佷簩:12,鍗佷笁:13,鍗佸洓:14,鍗佷簲:15,鍗佸叚:16,鍗佷竷:17,鍗佸叓:18,鍗佷節:19,浜屽崄:20,
- 浜屽崄涓�:21,浜屽崄浜�:22,浜屽崄涓�:23,浜屽崄鍥�:24,浜屽崄浜�:25,浜屽崄鍏�:26,浜屽崄涓�:27,浜屽崄鍏�:28,浜屽崄涔�:29,涓夊崄:30,
- 涓夊崄涓�:31,涓夊崄浜�:32,涓夊崄涓�:33,涓夊崄鍥�:34,涓夊崄浜�:35,涓夊崄鍏�:36,涓夊崄涓�:37,涓夊崄鍏�:38,涓夊崄涔�:39,鍥涘崄:40,
- 鍥涘崄涓�:41,鍥涘崄浜�:42,鍥涘崄涓�:43,鍥涘崄鍥�:44,鍥涘崄浜�:45
- }
+ 涓�: 1,
+ 浜�: 2,
+ 涓�: 3,
+ 鍥�: 4,
+ 浜�: 5,
+ 鍏�: 6,
+ 涓�: 7,
+ 鍏�: 8,
+ 涔�: 9,
+ 鍗�: 10,
+ 鍗佷竴: 11,
+ 鍗佷簩: 12,
+ 鍗佷笁: 13,
+ 鍗佸洓: 14,
+ 鍗佷簲: 15,
+ 鍗佸叚: 16,
+ 鍗佷竷: 17,
+ 鍗佸叓: 18,
+ 鍗佷節: 19,
+ 浜屽崄: 20,
+ 浜屽崄涓�: 21,
+ 浜屽崄浜�: 22,
+ 浜屽崄涓�: 23,
+ 浜屽崄鍥�: 24,
+ 浜屽崄浜�: 25,
+ 浜屽崄鍏�: 26,
+ 浜屽崄涓�: 27,
+ 浜屽崄鍏�: 28,
+ 浜屽崄涔�: 29,
+ 涓夊崄: 30,
+ 涓夊崄涓�: 31,
+ 涓夊崄浜�: 32,
+ 涓夊崄涓�: 33,
+ 涓夊崄鍥�: 34,
+ 涓夊崄浜�: 35,
+ 涓夊崄鍏�: 36,
+ 涓夊崄涓�: 37,
+ 涓夊崄鍏�: 38,
+ 涓夊崄涔�: 39,
+ 鍥涘崄: 40,
+ 鍥涘崄涓�: 41,
+ 鍥涘崄浜�: 42,
+ 鍥涘崄涓�: 43,
+ 鍥涘崄鍥�: 44,
+ 鍥涘崄浜�: 45,
+ };
const getNumberFromText = (text) => {
- if (!text || typeof text !== "string") return -1
- const match = text.match(/^([涓�浜屼笁鍥涗簲鍏竷鍏節鍗乚+)/)
+ if (!text || typeof text !== "string") return -1;
+ const match = text.match(/^([涓�浜屼笁鍥涗簲鍏竷鍏節鍗乚+)/);
if (match && match[1]) {
- const chineseNum = match[1]
- return chineseNumMap[chineseNum] !== undefined ? chineseNumMap[chineseNum] : -1
+ const chineseNum = match[1];
+ return chineseNumMap[chineseNum] !== undefined
+ ? chineseNumMap[chineseNum]
+ : -1;
}
- const arabicMatch = text.match(/^(\d+)/)
+ const arabicMatch = text.match(/^(\d+)/);
if (arabicMatch && arabicMatch[1]) {
- const num = parseInt(arabicMatch[1], 10)
- return num >= 1 && num <= 45 ? num : -1
+ const num = parseInt(arabicMatch[1], 10);
+ return num >= 1 && num <= 45 ? num : -1;
}
- return -1
- }
+ return -1;
+ };
- const numA = getNumberFromText(a)
- const numB = getNumberFromText(b)
+ const numA = getNumberFromText(a);
+ const numB = getNumberFromText(b);
if (numA === -1 && numB === -1) {
- return (a || "").localeCompare(b || "")
+ return (a || "").localeCompare(b || "");
}
- if (numA === -1) return 1
- if (numB === -1) return -1
- return numA - numB
+ if (numA === -1) return 1;
+ if (numB === -1) return -1;
+ return numA - numB;
},
getRowKey(row) {
- return row.statisticaltype === 1 ? row.leavehospitaldistrictcode : row.deptcode
+ return row.statisticaltype === 1
+ ? row.leavehospitaldistrictcode
+ : row.deptcode;
},
handleRowClick(row) {
if (this.expands.includes(this.getRowKey(row))) {
- this.expands = []
- return
+ this.expands = [];
+ return;
}
const params = {
@@ -290,222 +905,521 @@
: this.queryParams.deptcodes,
leavehospitaldistrictcodes: [row.leavehospitaldistrictcode],
drcode: "1",
- visitCount: 2
- }
+ visitCount: 2,
+ };
- delete params.leavehospitaldistrictcodes.all
- delete params.deptcodes.all
+ delete params.leavehospitaldistrictcodes.all;
+ delete params.deptcodes.all;
if (!row.doctorStats) {
- this.loading = true
+ this.loading = true;
+ params.rateDay = 7;
+
getSfStatistics(params).then((res) => {
- this.$set(row, "doctorStats", res.data)
- this.expands = [this.getRowKey(row)]
- this.loading = false
- })
+ this.$set(row, "doctorStats", res.data);
+ this.expands = [this.getRowKey(row)];
+ this.loading = false;
+ });
} else {
- this.expands = [this.getRowKey(row)]
+ this.expands = [this.getRowKey(row)];
}
},
+ // 鍦ㄧ粺璁℃眹鎬绘柟娉曚腑澶勭悊鎴愬姛鐜�
getSummaries(param) {
- const { columns, data } = param
- const sums = []
+ const { columns, data } = param;
+ const sums = [];
columns.forEach((column, index) => {
if (index === 0) {
- sums[index] = "鍚堣"
- return
+ sums[index] = "鍚堣";
+ return;
}
- if (index === 1 || index === 2) {
- sums[index] = "/"
- return
+ if (index === 1) {
+ sums[index] = "/";
+ return;
}
- if (column.property === "followUpRateAgain") {
+ if (column.property === "successRateAgain") {
+ // 鎴愬姛鐜囬渶瑕侀噸鏂拌绠楁�荤殑鎴愬姛鐜囷紝鑰屼笉鏄钩鍧囧��
+ const totalSuccess = data.reduce((sum, item) => {
+ return sum + (Number(item.followUpSuccessAgain) || 0);
+ }, 0);
+
+ const totalNeed = data.reduce((sum, item) => {
+ return sum + (Number(item.needFollowUpAgain) || 0);
+ }, 0);
+
+ const totalPending = data.reduce((sum, item) => {
+ return sum + (Number(item.pendingFollowUpAgain) || 0);
+ }, 0);
+
+ const denominator = totalNeed - totalPending;
+
+ if (denominator > 0) {
+ sums[index] = ((totalSuccess / denominator) * 100).toFixed(2) + "%";
+ } else {
+ sums[index] = "0.00%";
+ }
+ } else if (column.property === "followUpRateAgain") {
const percentageValues = data
.map((item) => {
- const value = item[column.property]
- if (!value || value === "-" || value === "0%") return null
+ const value = item[column.property];
+ if (!value || value === "-" || value === "0%") return null;
if (typeof value === "string" && value.includes("%")) {
- const numValue = parseFloat(value.replace("%", "")) / 100
- return isNaN(numValue) ? null : numValue
+ const numValue = parseFloat(value.replace("%", "")) / 100;
+ return isNaN(numValue) ? null : numValue;
} else {
- const numValue = parseFloat(value)
- return isNaN(numValue) ? null : numValue
+ const numValue = parseFloat(value);
+ return isNaN(numValue) ? null : numValue;
}
})
- .filter((value) => value !== null && value !== 0)
+ .filter((value) => value !== null && value !== 0);
if (percentageValues.length > 0) {
- const average = percentageValues.reduce((sum, value) => sum + value, 0) / percentageValues.length
- sums[index] = (average * 100).toFixed(2) + "%"
+ const average =
+ percentageValues.reduce((sum, value) => sum + value, 0) /
+ percentageValues.length;
+ sums[index] = (average * 100).toFixed(2) + "%";
} else {
- sums[index] = "0.00%"
+ sums[index] = "0.00%";
}
} else {
const values = data.map((item) => {
- const value = item[column.property]
- if (value === "-" || value === "" || value === null) return 0
- return Number(value) || 0
- })
+ const value = item[column.property];
+ if (value === "-" || value === "" || value === null) return 0;
+ return Number(value) || 0;
+ });
if (!values.every((value) => isNaN(value))) {
- sums[index] = values.reduce((prev, curr) => prev + curr, 0)
- sums[index] = this.formatNumber(sums[index])
+ sums[index] = values.reduce((prev, curr) => prev + curr, 0);
+ sums[index] = this.formatNumber(sums[index]);
} else {
- sums[index] = "-"
+ sums[index] = "-";
}
}
- })
+ });
- return sums
+ return sums;
},
getInnerSummaries(param) {
- const { columns, data } = param
- const sums = []
+ const { columns, data } = param;
+ const sums = [];
columns.forEach((column, index) => {
if (index === 0) {
- sums[index] = "灏忚"
- return
+ sums[index] = "灏忚";
+ return;
}
if (column.property === "drname" || column.property === "deptname") {
- sums[index] = "-"
- return
+ sums[index] = "-";
+ return;
}
- if (column.property === "followUpRateAgain") {
+ if (column.property === "successRateAgain") {
+ // 鎴愬姛鐜囬渶瑕侀噸鏂拌绠楁�荤殑鎴愬姛鐜囷紝鑰屼笉鏄钩鍧囧��
+ const totalSuccess = data.reduce((sum, item) => {
+ return sum + (Number(item.followUpSuccessAgain) || 0);
+ }, 0);
+
+ const totalNeed = data.reduce((sum, item) => {
+ return sum + (Number(item.needFollowUpAgain) || 0);
+ }, 0);
+
+ const totalPending = data.reduce((sum, item) => {
+ return sum + (Number(item.pendingFollowUpAgain) || 0);
+ }, 0);
+
+ const denominator = totalNeed - totalPending;
+
+ if (denominator > 0) {
+ sums[index] = ((totalSuccess / denominator) * 100).toFixed(2) + "%";
+ } else {
+ sums[index] = "0.00%";
+ }
+ } else if (column.property === "followUpRateAgain") {
const percentageValues = data
.map((item) => {
- const value = item[column.property]
- if (!value || value === "-" || value === "0%") return null
+ const value = item[column.property];
+ if (!value || value === "-" || value === "0%") return null;
if (typeof value === "string" && value.includes("%")) {
- const numValue = parseFloat(value.replace("%", "")) / 100
- return isNaN(numValue) ? null : numValue
+ const numValue = parseFloat(value.replace("%", "")) / 100;
+ return isNaN(numValue) ? null : numValue;
} else {
- const numValue = parseFloat(value)
- return isNaN(numValue) ? null : numValue
+ const numValue = parseFloat(value);
+ return isNaN(numValue) ? null : numValue;
}
})
- .filter((value) => value !== null && value !== 0)
+ .filter((value) => value !== null && value !== 0);
if (percentageValues.length > 0) {
- const average = percentageValues.reduce((sum, value) => sum + value, 0) / percentageValues.length
- sums[index] = (average * 100).toFixed(2) + "%"
+ const average =
+ percentageValues.reduce((sum, value) => sum + value, 0) /
+ percentageValues.length;
+ sums[index] = (average * 100).toFixed(2) + "%";
} else {
- sums[index] = "0.00%"
+ sums[index] = "0.00%";
}
} else {
const values = data.map((item) => {
- const value = item[column.property]
- if (value === "-" || value === "" || value === null) return 0
- return Number(value) || 0
- })
+ const value = item[column.property];
+ if (value === "-" || value === "" || value === null) return 0;
+ return Number(value) || 0;
+ });
if (!values.every((value) => isNaN(value))) {
- sums[index] = values.reduce((prev, curr) => prev + curr, 0)
- sums[index] = this.formatNumber(sums[index])
+ sums[index] = values.reduce((prev, curr) => prev + curr, 0);
+ sums[index] = this.formatNumber(sums[index]);
} else {
- sums[index] = "-"
+ sums[index] = "-";
}
}
- })
+ });
- return sums
+ return sums;
},
formatNumber(num) {
- if (isNaN(num)) return "-"
- return Number.isInteger(num) ? num.toString() : num.toFixed(0)
+ if (isNaN(num)) return "-";
+ return Number.isInteger(num) ? num.toString() : num.toFixed(0);
},
handleSelectionChange(selection) {
- this.ids = selection.map((item) => item.tagid)
+ this.ids = selection.map((item) => item.tagid);
},
- handleViewDetails(row, infoKey, titleSuffix) {
- const title = `${row.leavehospitaldistrictname || row.deptname}${titleSuffix}`
- this.$emit('view-details', row[infoKey], title)
+ handleViewDetails(row, infoKey, titleSuffix, type) {
+ const title = `${
+ row.leavehospitaldistrictname || row.deptname
+ }${titleSuffix}`;
+ this.$emit("view-details", row, infoKey, title, type);
},
+ // 璁$畻鎴愬姛鐜囩殑鏂规硶
+ calculateSuccessRate(followUpSuccess, needFollowUp, pendingFollowUp) {
+ const success = Number(followUpSuccess) || 0;
+ const need = Number(needFollowUp) || 0;
+ const pending = Number(pendingFollowUp) || 0;
+ // 鍒嗘瘝 = 闇�闅忚 - 寰呴殢璁�
+ const denominator = need - pending;
+
+ if (denominator <= 0) {
+ return "0.00%";
+ }
+
+ const rate = (success / denominator) * 100;
+ return rate.toFixed(2) + "%";
+ },
async exportTable() {
try {
- let dateRangeString = ""
- let sheetNameSuffix = ""
+ let dateRangeString = "";
+ let sheetNameSuffix = "";
- if (this.queryParams.dateRange && this.queryParams.dateRange.length === 2) {
- const startDateStr = this.queryParams.dateRange[0]
- const endDateStr = this.queryParams.dateRange[1]
+ if (
+ this.queryParams.dateRange &&
+ this.queryParams.dateRange.length === 2
+ ) {
+ const startDateStr = this.queryParams.dateRange[0];
+ const endDateStr = this.queryParams.dateRange[1];
const formatDateForDisplay = (dateTimeStr) => {
- return dateTimeStr.split(" ")[0]
- }
- const startDateFormatted = formatDateForDisplay(startDateStr)
- const endDateFormatted = formatDateForDisplay(endDateStr)
- dateRangeString = `${startDateFormatted}鑷�${endDateFormatted}`
- sheetNameSuffix = `${startDateFormatted}鑷�${endDateFormatted}`
+ return dateTimeStr.split(" ")[0];
+ };
+ const startDateFormatted = formatDateForDisplay(startDateStr);
+ const endDateFormatted = formatDateForDisplay(endDateStr);
+ dateRangeString = `${startDateFormatted}鑷�${endDateFormatted}`;
+ sheetNameSuffix = `${startDateFormatted}鑷�${endDateFormatted}`;
} else {
- const now = new Date()
- const currentMonth = now.getMonth() + 1
- dateRangeString = `${currentMonth}鏈坄
- sheetNameSuffix = `${currentMonth}鏈坄
+ const now = new Date();
+ const currentMonth = now.getMonth() + 1;
+ dateRangeString = `${currentMonth}鏈坄;
+ sheetNameSuffix = `${currentMonth}鏈坄;
}
- const excelName = `鍐嶆鍑洪櫌闅忚缁熻琛╛${dateRangeString}.xlsx`
- const worksheetName = `鍐嶆闅忚缁熻_${sheetNameSuffix}`
+ const excelName = `鍐嶆鍑洪櫌闅忚缁熻琛╛${dateRangeString}.xlsx`;
+ const worksheetName = `鍐嶆闅忚缁熻_${sheetNameSuffix}`;
if (!this.tableData || this.tableData.length === 0) {
- this.$message.warning("鏆傛棤鍐嶆闅忚鏁版嵁鍙鍑�")
- return false
+ this.$message.warning("鏆傛棤鍐嶆闅忚鏁版嵁鍙鍑�");
+ return false;
}
- const workbook = new ExcelJS.Workbook()
- const worksheet = workbook.addWorksheet(worksheetName)
+ const workbook = new ExcelJS.Workbook();
+ const worksheet = workbook.addWorksheet(worksheetName);
// 鏋勫缓琛ㄦ牸
- this.buildExportSheet(worksheet, sheetNameSuffix)
+ this.buildExportSheet(worksheet, sheetNameSuffix);
- const buffer = await workbook.xlsx.writeBuffer()
+ const buffer = await workbook.xlsx.writeBuffer();
const blob = new Blob([buffer], {
- type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
- })
- saveAs(blob, excelName)
+ type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+ });
+ saveAs(blob, excelName);
- this.$message.success("瀵煎嚭鎴愬姛")
- return true
+ this.$message.success("瀵煎嚭鎴愬姛");
+ return true;
} catch (error) {
- console.error("瀵煎嚭澶辫触:", error)
- this.$message.error(`瀵煎嚭澶辫触: ${error.message}`)
- return false
+ console.error("瀵煎嚭澶辫触:", error);
+ this.$message.error(`瀵煎嚭澶辫触: ${error.message}`);
+ return false;
}
},
+ /** 瀵煎嚭鍖荤敓瀛愯〃锛堝啀娆¢殢璁匡級 */
+ async exportDoctorTable(row) {
+ try {
+ const areaName =
+ row.leavehospitaldistrictname || row.deptname || "鏈煡鐥呭尯";
- buildExportSheet(worksheet, sheetNameSuffix) {
- const titleStyle = {
- font: { name: "寰蒋闆呴粦", size: 16, bold: true, color: { argb: "FF000000" } },
- fill: { type: "pattern", pattern: "solid", fgColor: { argb: "FFE6F3FF" } },
- alignment: { vertical: "middle", horizontal: "center", wrapText: true },
- border: {
- top: { style: "thin", color: { argb: "FFD0D0D0" } },
- left: { style: "thin", color: { argb: "FFD0D0D0" } },
- bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
- right: { style: "thin", color: { argb: "FFD0D0D0" } }
+ let dateRangeString = "";
+ if (
+ this.queryParams.dateRange &&
+ this.queryParams.dateRange.length === 2
+ ) {
+ const start = this.queryParams.dateRange[0].split(" ")[0];
+ const end = this.queryParams.dateRange[1].split(" ")[0];
+ dateRangeString = `${start}鑷�${end}`;
+ } else {
+ dateRangeString = `${new Date().getMonth() + 1}鏈坄;
}
+
+ const fileName = `${areaName}鍖荤敓鍐嶆闅忚鍒楄〃_${dateRangeString}.xlsx`;
+ const sheetName = `${areaName}鍖荤敓鍐嶆闅忚`;
+
+ if (!row.doctorStats || row.doctorStats.length === 0) {
+ this.$message.warning("褰撳墠鐥呭尯鏆傛棤鍖荤敓鍐嶆闅忚鏁版嵁");
+ return;
+ }
+
+ const workbook = new ExcelJS.Workbook();
+ const worksheet = workbook.addWorksheet(sheetName);
+
+ this.buildDoctorExportSheet(worksheet, row.doctorStats, areaName);
+
+ const buffer = await workbook.xlsx.writeBuffer();
+ saveAs(
+ new Blob([buffer], {
+ type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+ }),
+ fileName
+ );
+
+ this.$message.success("鍖荤敓鍐嶆闅忚鍒楄〃瀵煎嚭鎴愬姛");
+ } catch (err) {
+ console.error(err);
+ this.$message.error("瀵煎嚭澶辫触");
}
+ },
+ buildDoctorExportSheet(worksheet, data, areaName) {
+ const titleStyle = {
+ font: { name: "寰蒋闆呴粦", size: 16, bold: true },
+ alignment: { horizontal: "center", vertical: "middle" },
+ };
const headerStyle = {
- font: { name: "寰蒋闆呴粦", size: 11, bold: true, color: { argb: "FF000000" } },
- fill: { type: "pattern", pattern: "solid", fgColor: { argb: "FFF5F7FA" } },
+ font: { name: "寰蒋闆呴粦", size: 11, bold: true },
+ fill: {
+ type: "pattern",
+ pattern: "solid",
+ fgColor: { argb: "FFF5F7FA" },
+ },
+ alignment: { horizontal: "center", vertical: "middle", wrapText: true },
+ 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, 10);
+ worksheet.getCell(1, 1).value = `${areaName}鍖荤敓鍐嶆闅忚鍒楄〃`;
+ worksheet.getCell(1, 1).style = titleStyle;
+ worksheet.getRow(1).height = 30;
+
+ // 琛ㄥご
+ const headers = [
+ "鍖荤敓濮撳悕",
+ "绉戝",
+ "鍑洪櫌浜烘",
+ "鏃犻渶闅忚",
+ "搴旈殢璁�",
+ "闇�闅忚",
+ "寰呴殢璁�",
+ "闅忚鎴愬姛",
+ "闅忚澶辫触",
+ "鎴愬姛鐜�", // 鏂板
+ "闅忚鐜�", // 鍘熸潵鍦ㄦ垚鍔熺巼浣嶇疆
+ ];
+
+ const headerRow = worksheet.addRow(headers);
+ headerRow.eachCell((cell) => {
+ cell.style = headerStyle;
+ });
+ worksheet.getRow(2).height = 25;
+
+ // 鏁版嵁
+ data.forEach((item) => {
+ const row = worksheet.addRow([
+ item.drname,
+ item.deptname,
+ item.dischargeCount,
+ item.nonFollowUp,
+ item.followUpNeeded,
+ item.needFollowUpAgain,
+ item.pendingFollowUpAgain,
+ item.followUpSuccessAgain,
+ item.followUpFailAgain,
+ this.calculateSuccessRate(
+ item.followUpSuccessAgain,
+ item.needFollowUpAgain,
+ item.pendingFollowUpAgain
+ ),
+ item.followUpRateAgain,
+ ]);
+ row.eachCell((cell) => {
+ cell.style = cellStyle;
+ });
+ });
+
+ // 灏忚琛�
+ const summaryRow = worksheet.addRow(
+ this.getDoctorAgainExportSummary(data)
+ );
+ summaryRow.eachCell((cell) => {
+ cell.font = { bold: true };
+ cell.fill = {
+ type: "pattern",
+ pattern: "solid",
+ fgColor: { argb: "FFF5F7FA" },
+ };
+ });
+
+ // 鍒楀
+ worksheet.columns = [
+ { width: 15 },
+ { width: 15 },
+ { width: 12 },
+ { width: 12 },
+ { width: 12 },
+ { width: 12 },
+ { width: 12 },
+ { width: 12 },
+ { width: 12 },
+ { width: 12 }, // 鎴愬姛鐜�
+ { width: 12 }, // 闅忚鐜�
+ ];
+ },
+ /** 鍐嶆闅忚 - 鍖荤敓瀛愯〃瀵煎嚭灏忚 */
+ getDoctorAgainExportSummary(data) {
+ const sums = ["灏忚"];
+
+ const keys = [
+ "dischargeCount",
+ "nonFollowUp",
+ "followUpNeeded",
+ "needFollowUpAgain",
+ "pendingFollowUpAgain",
+ "followUpSuccessAgain",
+ "followUpFailAgain",
+ ];
+
+ keys.forEach((key) => {
+ sums.push(data.reduce((t, r) => t + (Number(r[key]) || 0), 0));
+ });
+
+ // 鎴愬姛鐜囷紙骞冲潎鍊硷級
+ const successRates = data
+ .map((item) => {
+ const success = Number(item.followUpSuccessAgain) || 0;
+ const need = Number(item.needFollowUpAgain) || 0;
+ const pending = Number(item.pendingFollowUpAgain) || 0;
+ const denominator = need - pending;
+ if (denominator <= 0) return 0;
+ return success / denominator;
+ })
+ .filter((rate) => !isNaN(rate));
+
+ sums.push(
+ successRates.length
+ ? (
+ (successRates.reduce((a, b) => a + b, 0) / successRates.length) *
+ 100
+ ).toFixed(2) + "%"
+ : "0.00%"
+ );
+
+ // 闅忚鐜囷紙骞冲潎鍊硷級
+ const followUpRates = data
+ .map((i) => this.extractPercentageValue(i.followUpRateAgain))
+ .filter(Boolean);
+
+ sums.push(
+ followUpRates.length
+ ? (
+ (followUpRates.reduce((a, b) => a + b, 0) /
+ followUpRates.length) *
+ 100
+ ).toFixed(2) + "%"
+ : "0.00%"
+ );
+
+ return sums;
+ },
+ buildExportSheet(worksheet, sheetNameSuffix) {
+ const titleStyle = {
+ font: {
+ name: "寰蒋闆呴粦",
+ size: 16,
+ bold: true,
+ color: { argb: "FF000000" },
+ },
+ fill: {
+ type: "pattern",
+ pattern: "solid",
+ fgColor: { argb: "FFE6F3FF" },
+ },
alignment: { vertical: "middle", horizontal: "center", wrapText: true },
border: {
top: { style: "thin", color: { argb: "FFD0D0D0" } },
left: { style: "thin", color: { argb: "FFD0D0D0" } },
bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
- right: { style: "thin", color: { argb: "FFD0D0D0" } }
- }
- }
+ right: { style: "thin", color: { argb: "FFD0D0D0" } },
+ },
+ };
+
+ const headerStyle = {
+ font: {
+ name: "寰蒋闆呴粦",
+ size: 11,
+ bold: true,
+ color: { argb: "FF000000" },
+ },
+ fill: {
+ type: "pattern",
+ pattern: "solid",
+ fgColor: { argb: "FFF5F7FA" },
+ },
+ alignment: { vertical: "middle", horizontal: "center", wrapText: true },
+ border: {
+ top: { style: "thin", color: { argb: "FFD0D0D0" } },
+ left: { style: "thin", color: { argb: "FFD0D0D0" } },
+ bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
+ right: { style: "thin", color: { argb: "FFD0D0D0" } },
+ },
+ };
const cellStyle = {
font: { name: "瀹嬩綋", size: 10, color: { argb: "FF000000" } },
@@ -514,156 +1428,232 @@
top: { style: "thin", color: { argb: "FFD0D0D0" } },
left: { style: "thin", color: { argb: "FFD0D0D0" } },
bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
- right: { style: "thin", color: { argb: "FFD0D0D0" } }
- }
- }
+ right: { style: "thin", color: { argb: "FFD0D0D0" } },
+ },
+ };
const summaryStyle = {
- font: { name: "瀹嬩綋", size: 10, bold: true, color: { argb: "FF409EFF" } },
- fill: { type: "pattern", pattern: "solid", fgColor: { argb: "FFF5F7FA" } },
+ font: {
+ name: "瀹嬩綋",
+ size: 10,
+ bold: true,
+ color: { argb: "FF409EFF" },
+ },
+ fill: {
+ type: "pattern",
+ pattern: "solid",
+ fgColor: { argb: "FFF5F7FA" },
+ },
alignment: { vertical: "middle", horizontal: "center" },
border: {
top: { style: "thin", color: { argb: "FFD0D0D0" } },
left: { style: "thin", color: { argb: "FFD0D0D0" } },
bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
- right: { style: "thin", color: { argb: "FFD0D0D0" } }
- }
- }
+ right: { style: "thin", color: { argb: "FFD0D0D0" } },
+ },
+ };
// 娣诲姞鏍囬琛�
- worksheet.mergeCells(1, 1, 1, 15)
- const titleCell = worksheet.getCell(1, 1)
- titleCell.value = `鍐嶆鍑洪櫌闅忚缁熻琛╛${sheetNameSuffix}`
- titleCell.style = titleStyle
- worksheet.getRow(1).height = 35
+ worksheet.mergeCells(1, 1, 1, 15);
+ const titleCell = worksheet.getCell(1, 1);
+ titleCell.value = `鍐嶆鍑洪櫌闅忚缁熻琛╛${sheetNameSuffix}`;
+ titleCell.style = titleStyle;
+ worksheet.getRow(1).height = 35;
// 琛ㄥご
+ // 琛ㄥご闇�瑕佸鍔犳垚鍔熺巼鍒�
const secondRowHeaders = [
- "", "鍑洪櫌鐥呭尯", "绉戝", "鍑洪櫌浜烘", "鏃犻渶闅忚浜烘", "搴旈殢璁夸汉娆�",
- "闇�闅忚", "寰呴殢璁�", "闅忚鎴愬姛", "闅忚澶辫触", "闅忚鐜�", "浜哄伐", "鐭俊", "寰俊"
- ]
+ "",
+ "鍑洪櫌鐥呭尯",
+ "绉戝",
+ "鍑洪櫌浜烘",
+ "鏃犻渶闅忚浜烘",
+ "搴旈殢璁夸汉娆�",
+ "闇�闅忚",
+ "寰呴殢璁�",
+ "闅忚鎴愬姛",
+ "闅忚澶辫触",
+ "鎴愬姛鐜�", // 鎴愬姛鐜囧簲璇ュ湪闅忚澶辫触鍚庨潰
+ "闅忚鐜�", // 闅忚鐜囧湪鎴愬姛鐜囧悗闈�
+ "浜哄伐",
+ "璇煶", // 淇锛氬簲璇ユ槸璇煶锛屼笉鏄煭淇�
+ "鐭俊", // 鐭俊
+ "寰俊", // 寰俊
+ ];
secondRowHeaders.forEach((header, index) => {
- const cell = worksheet.getCell(3, index + 1)
- cell.value = header
- cell.style = headerStyle
- })
+ const cell = worksheet.getCell(3, index + 1);
+ cell.value = header;
+ cell.style = headerStyle;
+ });
- // 鍚堝苟鍗曞厓鏍�
+ // 鏇存柊鍚堝苟鍗曞厓鏍肩殑鑼冨洿
for (let i = 1; i <= 6; i++) {
- worksheet.mergeCells(2, i, 3, i)
- const cell = worksheet.getCell(2, i)
- cell.style = headerStyle
+ worksheet.mergeCells(2, i, 3, i);
+ const cell = worksheet.getCell(2, i);
+ cell.style = headerStyle;
}
- worksheet.getCell(2, 1).value = ""
- worksheet.getCell(2, 2).value = "鍑洪櫌鐥呭尯"
- worksheet.getCell(2, 3).value = "绉戝"
- worksheet.getCell(2, 4).value = "鍑洪櫌浜烘"
- worksheet.getCell(2, 5).value = "鏃犻渶闅忚浜烘"
- worksheet.getCell(2, 6).value = "搴旈殢璁夸汉娆�"
+ worksheet.getCell(2, 1).value = "";
+ worksheet.getCell(2, 2).value = "鍑洪櫌鐥呭尯";
+ worksheet.getCell(2, 3).value = "绉戝";
+ worksheet.getCell(2, 4).value = "鍑洪櫌浜烘";
+ worksheet.getCell(2, 5).value = "鏃犻渶闅忚浜烘";
+ worksheet.getCell(2, 6).value = "搴旈殢璁夸汉娆�";
- worksheet.mergeCells(2, 7, 2, 14)
- worksheet.getCell(2, 7).value = "鍐嶆鍑洪櫌闅忚"
- worksheet.getCell(2, 7).style = headerStyle
+ // 娉ㄦ剰锛氱敱浜庡鍔犱簡鎴愬姛鐜囧垪锛屽悎骞跺垪鏁拌澧炲姞
+ worksheet.mergeCells(2, 7, 2, 16); // 浠�7鍚堝苟鍒�16锛堝師鏉ユ槸7-14锛�
+ worksheet.getCell(2, 7).value = "鍐嶆鍑洪櫌闅忚";
+ worksheet.getCell(2, 7).style = headerStyle;
- worksheet.getRow(2).height = 28
- worksheet.getRow(3).height = 25
+ worksheet.getRow(2).height = 28;
+ worksheet.getRow(3).height = 25;
// 鏁版嵁琛�
this.tableData.forEach((item, rowIndex) => {
- const dataRow = worksheet.addRow([
- "",
- item.leavehospitaldistrictname || "",
- item.deptname || "",
- item.dischargeCount || 0,
- item.nonFollowUp || 0,
- item.followUpNeeded || 0,
- item.needFollowUpAgain || 0,
- item.pendingFollowUpAgain || 0,
- item.followUpSuccessAgain || 0,
- item.followUpFailAgain || 0,
- item.followUpRateAgain || "0%",
- item.manualAgain || 0,
- item.smsAgain || 0,
- item.weChatAgain || 0
- ], rowIndex + 4)
+ const dataRow = worksheet.addRow(
+ [
+ "",
+ item.leavehospitaldistrictname || "",
+ item.deptname || "",
+ item.dischargeCount || 0,
+ item.nonFollowUp || 0,
+ item.followUpNeeded || 0,
+ item.needFollowUpAgain || 0,
+ item.pendingFollowUpAgain || 0,
+ item.followUpSuccessAgain || 0,
+ item.followUpFailAgain || 0,
+ // 鎴愬姛鐜� - 闇�瑕佸姩鎬佽绠�
+ this.calculateSuccessRate(
+ item.followUpSuccessAgain,
+ item.needFollowUpAgain,
+ item.pendingFollowUpAgain
+ ),
+ item.followUpRateAgain || "0%", // 闅忚鐜�
+ item.manualAgain || 0,
+ item.voiceAgain || 0,
+ item.smsAgain || 0,
+ item.weChatAgain || 0,
+ ],
+ rowIndex + 4
+ );
dataRow.eachCell((cell) => {
- cell.style = cellStyle
- })
- dataRow.height = 24
- })
+ cell.style = cellStyle;
+ });
+ dataRow.height = 24;
+ });
// 鍚堣琛�
- const summaries = this.getExportSummaries()
- const summaryRow = worksheet.addRow(summaries)
+ const summaries = this.getExportSummaries();
+ const summaryRow = worksheet.addRow(summaries);
summaryRow.eachCell((cell, colNumber) => {
- cell.style = summaryStyle
+ cell.style = summaryStyle;
if (colNumber === 1) {
- cell.value = "鍚堣"
+ cell.value = "鍚堣";
}
- })
- summaryRow.height = 28
+ });
+ summaryRow.height = 28;
// 鍒楀
+ // 淇鍒楀
worksheet.columns = [
- { width: 8 }, { width: 20 }, { width: 15 }, { width: 12 }, { width: 12 }, { width: 12 },
- { width: 10 }, { width: 10 }, { width: 10 }, { width: 10 }, { width: 12 },
- { width: 8 }, { width: 8 }, { width: 8 }
- ]
+ { width: 8 },
+ { width: 20 },
+ { width: 15 },
+ { width: 12 },
+ { width: 12 },
+ { width: 12 },
+ { width: 10 },
+ { width: 10 },
+ { width: 10 },
+ { width: 10 },
+ { width: 12 }, // 鎴愬姛鐜�
+ { width: 12 }, // 闅忚鐜�
+ { width: 8 }, // 浜哄伐
+ { width: 8 }, // 璇煶
+ { width: 8 }, // 鐭俊
+ { width: 8 }, // 寰俊
+ ];
},
getExportSummaries() {
- const summaries = ["鍚堣", "/", "/", 0, 0, 0, 0, 0, 0, 0, "0%", 0, 0, 0]
+ const summaries = [
+ "鍚堣",
+ "/",
+ "/",
+ 0, // 3: dischargeCount
+ 0, // 4: nonFollowUp
+ 0, // 5: followUpNeeded
+ 0, // 6: needFollowUpAgain
+ 0, // 7: pendingFollowUpAgain
+ 0, // 8: followUpSuccessAgain
+ 0, // 9: followUpFailAgain
+ "0%", // 10: 鎴愬姛鐜�
+ "0%", // 11: 闅忚鐜�
+ 0, // 12: manualAgain
+ 0, // 13: voiceAgain
+ 0, // 14: smsAgain
+ 0, // 15: weChatAgain
+ ];
this.tableData.forEach((item) => {
- summaries[3] += Number(item.dischargeCount) || 0
- summaries[4] += Number(item.nonFollowUp) || 0
- summaries[5] += Number(item.followUpNeeded) || 0
- summaries[6] += Number(item.needFollowUpAgain) || 0
- summaries[7] += Number(item.pendingFollowUpAgain) || 0
- summaries[8] += Number(item.followUpSuccessAgain) || 0
- summaries[9] += Number(item.followUpFailAgain) || 0
- summaries[11] += Number(item.manualAgain) || 0
- summaries[12] += Number(item.smsAgain) || 0
- summaries[13] += Number(item.weChatAgain) || 0
- })
+ summaries[3] += Number(item.dischargeCount) || 0;
+ summaries[4] += Number(item.nonFollowUp) || 0;
+ summaries[5] += Number(item.followUpNeeded) || 0;
+ summaries[6] += Number(item.needFollowUpAgain) || 0;
+ summaries[7] += Number(item.pendingFollowUpAgain) || 0;
+ summaries[8] += Number(item.followUpSuccessAgain) || 0;
+ summaries[9] += Number(item.followUpFailAgain) || 0;
+ summaries[12] += Number(item.manualAgain) || 0;
+ summaries[13] += Number(item.voiceAgain) || 0;
+ summaries[14] += Number(item.smsAgain) || 0;
+ summaries[15] += Number(item.weChatAgain) || 0;
+ });
- const followUpRateAgainValues = this.tableData
- .map((item) => this.extractPercentageValue(item.followUpRateAgain))
- .filter((value) => value !== null)
+ // 鎴愬姛鐜囪绠�
+ const totalSuccess = summaries[8]; // followUpSuccessAgain鐨勬�诲拰
+ const totalNeed = summaries[6]; // needFollowUpAgain鐨勬�诲拰
+ const totalPending = summaries[7]; // pendingFollowUpAgain鐨勬�诲拰
+ const denominator = totalNeed - totalPending;
- if (followUpRateAgainValues.length > 0) {
- const avgFollowUpRateAgain = followUpRateAgainValues.reduce((sum, val) => sum + val, 0) / followUpRateAgainValues.length
- summaries[10] = (avgFollowUpRateAgain * 100).toFixed(2) + "%"
+ if (denominator > 0) {
+ summaries[10] = ((totalSuccess / denominator) * 100).toFixed(2) + "%";
+ } else {
+ summaries[10] = "0.00%";
}
- summaries[3] = this.formatNumber(summaries[3])
- summaries[4] = this.formatNumber(summaries[4])
- summaries[5] = this.formatNumber(summaries[5])
- summaries[6] = this.formatNumber(summaries[6])
- summaries[7] = this.formatNumber(summaries[7])
- summaries[8] = this.formatNumber(summaries[8])
- summaries[9] = this.formatNumber(summaries[9])
- summaries[11] = this.formatNumber(summaries[11])
- summaries[12] = this.formatNumber(summaries[12])
- summaries[13] = this.formatNumber(summaries[13])
+ // 闅忚鐜囪绠�
+ const followUpRateAgainValues = this.tableData
+ .map((item) => this.extractPercentageValue(item.followUpRateAgain))
+ .filter((value) => value !== null);
- return summaries
+ if (followUpRateAgainValues.length > 0) {
+ const avgFollowUpRateAgain =
+ followUpRateAgainValues.reduce((sum, val) => sum + val, 0) /
+ followUpRateAgainValues.length;
+ summaries[11] = (avgFollowUpRateAgain * 100).toFixed(2) + "%";
+ }
+
+ // 鏍煎紡鍖栨暟瀛�
+ [3, 4, 5, 6, 7, 8, 9, 12, 13, 14, 15].forEach((index) => {
+ summaries[index] = this.formatNumber(summaries[index]);
+ });
+
+ return summaries;
},
extractPercentageValue(value) {
- if (!value) return null
+ if (!value) return null;
if (typeof value === "string" && value.includes("%")) {
- const num = parseFloat(value.replace("%", ""))
- return isNaN(num) ? null : num / 100
+ const num = parseFloat(value.replace("%", ""));
+ return isNaN(num) ? null : num / 100;
}
- const num = parseFloat(value)
- return isNaN(num) ? null : num
- }
- }
-}
+ const num = parseFloat(value);
+ return isNaN(num) ? null : num;
+ },
+ },
+};
</script>
<style lang="scss" scoped>
--
Gitblit v1.9.3