| | |
| | | > |
| | | <el-table-column label="" align="center" width="96" fixed="left"> |
| | | <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)"> |
| | | <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> |
| | |
| | | </el-table-column> |
| | | |
| | | <el-table-column label="医生姓名" prop="drname" align="center" /> |
| | | <el-table-column label="科室" prop="deptname" align="center" width="120" /> |
| | | <el-table-column |
| | | label="科室" |
| | | prop="deptname" |
| | | align="center" |
| | | width="120" |
| | | /> |
| | | |
| | | <!-- 基础列 --> |
| | | <el-table-column label="出院人次" prop="dischargeCount" align="center"> |
| | | <el-table-column |
| | | label="出院人次" |
| | | prop="dischargeCount" |
| | | align="center" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleViewDetails(scope.row, 'dischargeCountInfo', '出院患者列表', '1')"> |
| | | <span class="button-zx">{{ scope.row.dischargeCount }}</span> |
| | | <el-button |
| | | type="text" |
| | | @click=" |
| | | handleViewDetails( |
| | | scope.row, |
| | | 'dischargeCountInfo', |
| | | '出院患者列表', |
| | | '1' |
| | | ) |
| | | " |
| | | > |
| | | <span class="button-zx">{{ |
| | | scope.row.dischargeCount |
| | | }}</span> |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <!-- 首次随访(医生) --> |
| | | <el-table-column label="首次无需随访" prop="nonFollowUp" align="center"> |
| | | <el-table-column |
| | | label="首次无需随访" |
| | | prop="nonFollowUp" |
| | | align="center" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleViewDetails(scope.row, 'nonFollowUpInfo', '首次无需随访列表', '1')"> |
| | | <el-button |
| | | 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="首次应随访" prop="followUpNeeded" align="center"> |
| | | <el-table-column |
| | | label="首次应随访" |
| | | prop="followUpNeeded" |
| | | align="center" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleViewDetails(scope.row, 'followUpNeededInfo', '首次应随访列表', '1')"> |
| | | <span class="button-zx">{{ scope.row.followUpNeeded }}</span> |
| | | <el-button |
| | | 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 label="首次需随访" prop="needFollowUp" align="center"> |
| | | <el-table-column |
| | | label="首次需随访" |
| | | prop="needFollowUp" |
| | | align="center" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleViewDetails(scope.row, 'needFollowUpInfo', '首次需随访列表', '1')"> |
| | | <el-button |
| | | type="text" |
| | | @click=" |
| | | handleViewDetails( |
| | | scope.row, |
| | | 'needFollowUpInfo', |
| | | '首次需随访列表', |
| | | '1' |
| | | ) |
| | | " |
| | | > |
| | | <span class="button-zx">{{ scope.row.needFollowUp }}</span> |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="首次待随访" prop="pendingFollowUp" align="center"> |
| | | <el-table-column |
| | | label="首次待随访" |
| | | prop="pendingFollowUp" |
| | | align="center" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleViewDetails(scope.row, 'pendingFollowUpInfo', '首次待随访列表', '1')"> |
| | | <span class="button-zx">{{ scope.row.pendingFollowUp }}</span> |
| | | <el-button |
| | | type="text" |
| | | @click=" |
| | | handleViewDetails( |
| | | scope.row, |
| | | 'pendingFollowUpInfo', |
| | | '首次待随访列表', |
| | | '1' |
| | | ) |
| | | " |
| | | > |
| | | <span class="button-zx">{{ |
| | | scope.row.pendingFollowUp |
| | | }}</span> |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="首次完成" prop="followUpSuccess" align="center"> |
| | | <el-table-column |
| | | label="首次完成" |
| | | prop="followUpSuccess" |
| | | align="center" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleViewDetails(scope.row, 'followUpSuccessInfo', '首次完成列表', '1')"> |
| | | <span class="button-zx">{{ scope.row.followUpSuccess }}</span> |
| | | <el-button |
| | | type="text" |
| | | @click=" |
| | | handleViewDetails( |
| | | scope.row, |
| | | 'followUpSuccessInfo', |
| | | '首次完成列表', |
| | | '1' |
| | | ) |
| | | " |
| | | > |
| | | <span class="button-zx">{{ |
| | | scope.row.followUpSuccess |
| | | }}</span> |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="首次失败" prop="followUpFail" align="center"> |
| | | <el-table-column |
| | | label="首次失败" |
| | | prop="followUpFail" |
| | | align="center" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleViewDetails(scope.row, 'followUpFailInfo', '首次失败列表', '1')"> |
| | | <el-button |
| | | type="text" |
| | | @click=" |
| | | handleViewDetails( |
| | | scope.row, |
| | | 'followUpFailInfo', |
| | | '首次失败列表', |
| | | '1' |
| | | ) |
| | | " |
| | | > |
| | | <span class="button-zx">{{ scope.row.followUpFail }}</span> |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column v-if="orgname != '景宁畲族自治县人民医院'" label="首次成功率" prop="successRate" align="center" :render-header="Tooltipcgl"> |
| | | <el-table-column |
| | | v-if="orgname != '景宁畲族自治县人民医院'" |
| | | label="首次成功率" |
| | | prop="successRate" |
| | | align="center" |
| | | :render-header="Tooltipcgl" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ calculateSuccessRate(scope.row.followUpSuccess, scope.row.needFollowUp, scope.row.pendingFollowUp) }}</span> |
| | | <span>{{ |
| | | calculateSuccessRate( |
| | | scope.row.followUpSuccess, |
| | | scope.row.needFollowUp, |
| | | scope.row.pendingFollowUp |
| | | ) |
| | | }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <!-- 再次随访(医生) --> |
| | | <el-table-column label="再次需随访" prop="needFollowUpAgain" align="center"> |
| | | <el-table-column |
| | | label="再次需随访" |
| | | prop="needFollowUpAgain" |
| | | align="center" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleViewDetails(scope.row, 'needFollowUpAgainInfo', '再次需随访列表', '1')"> |
| | | <span class="button-zx">{{ scope.row.needFollowUpAgain }}</span> |
| | | <el-button |
| | | 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="再次待随访" prop="pendingFollowUpAgain" align="center"> |
| | | <el-table-column |
| | | label="再次待随访" |
| | | prop="pendingFollowUpAgain" |
| | | align="center" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleViewDetails(scope.row, 'pendingFollowUpAgainInfo', '再次待随访列表', '1')"> |
| | | <span class="button-zx">{{ scope.row.pendingFollowUpAgain }}</span> |
| | | <el-button |
| | | 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="再次完成" prop="followUpSuccessAgain" align="center"> |
| | | <el-table-column |
| | | label="再次完成" |
| | | prop="followUpSuccessAgain" |
| | | align="center" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleViewDetails(scope.row, 'followUpSuccessAgainInfo', '再次完成列表', '1')"> |
| | | <span class="button-zx">{{ scope.row.followUpSuccessAgain }}</span> |
| | | <el-button |
| | | 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="再次失败" prop="followUpFailAgain" align="center"> |
| | | <el-table-column |
| | | label="再次失败" |
| | | prop="followUpFailAgain" |
| | | align="center" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleViewDetails(scope.row, 'followUpFailAgainInfo', '再次失败列表', '1')"> |
| | | <span class="button-zx">{{ scope.row.followUpFailAgain }}</span> |
| | | <el-button |
| | | 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 v-if="orgname != '景宁畲族自治县人民医院'" label="再次成功率" prop="successRateAgain" align="center" :render-header="Tooltipcgl"> |
| | | <el-table-column |
| | | v-if="orgname != '景宁畲族自治县人民医院'" |
| | | label="再次成功率" |
| | | prop="successRateAgain" |
| | | align="center" |
| | | :render-header="Tooltipcgl" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ calculateSuccessRate(scope.row.followUpSuccessAgain, scope.row.needFollowUpAgain, scope.row.pendingFollowUpAgain) }}</span> |
| | | <span>{{ |
| | | calculateSuccessRate( |
| | | scope.row.followUpSuccessAgain, |
| | | scope.row.needFollowUpAgain, |
| | | scope.row.pendingFollowUpAgain |
| | | ) |
| | | }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <!-- 新增计算指标(医生) --> |
| | | <el-table-column label="随访率" align="center" prop="followUpRate" :render-header="TooltipFollowUpRate"> |
| | | <el-table-column |
| | | label="随访率" |
| | | align="center" |
| | | prop="followUpRate" |
| | | :render-header="TooltipFollowUpRate" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ calculateFollowUpRate(scope.row) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="推送率" align="center" prop="pushRate" :render-header="TooltipPushRate"> |
| | | <el-table-column |
| | | label="推送率" |
| | | align="center" |
| | | prop="pushRate" |
| | | :render-header="TooltipPushRate" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ calculatePushRate(scope.row) }}</span> |
| | | </template> |
| | |
| | | <!-- 出院人次 --> |
| | | <el-table-column label="出院人次" align="center" prop="dischargeCount"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleViewDetails(scope.row, 'dischargeCountInfo', '出院患者列表')"> |
| | | <el-button |
| | | type="text" |
| | | @click=" |
| | | handleViewDetails( |
| | | scope.row, |
| | | 'dischargeCountInfo', |
| | | '出院患者列表' |
| | | ) |
| | | " |
| | | > |
| | | <span class="button-zx">{{ scope.row.dischargeCount }}</span> |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="无需随访" align="center" prop="nonFollowUp"> |
| | | <template slot-scope="scope"> |
| | | <el-button 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" prop="followUpNeeded"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleViewDetails(scope.row, 'followUpNeededInfo', '首次应随访列表')"> |
| | | <span class="button-zx">{{ scope.row.followUpNeeded }}</span> |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="无需随访" align="center" prop="nonFollowUp"> |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | 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" prop="followUpNeeded"> |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | 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" prop="needFollowUp"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleViewDetails(scope.row, 'needFollowUpInfo', '首次需随访列表')"> |
| | | <el-button |
| | | type="text" |
| | | @click=" |
| | | handleViewDetails( |
| | | scope.row, |
| | | 'needFollowUpInfo', |
| | | '首次需随访列表' |
| | | ) |
| | | " |
| | | > |
| | | <span class="button-zx">{{ scope.row.needFollowUp }}</span> |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="待随访" align="center" prop="pendingFollowUp"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleViewDetails(scope.row, 'pendingFollowUpInfo', '首次待随访列表')"> |
| | | <el-button |
| | | type="text" |
| | | @click=" |
| | | handleViewDetails( |
| | | scope.row, |
| | | 'pendingFollowUpInfo', |
| | | '首次待随访列表' |
| | | ) |
| | | " |
| | | > |
| | | <span class="button-zx">{{ scope.row.pendingFollowUp }}</span> |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="完成" align="center" prop="followUpSuccess"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleViewDetails(scope.row, 'followUpSuccessInfo', '首次完成列表')"> |
| | | <el-button |
| | | type="text" |
| | | @click=" |
| | | handleViewDetails( |
| | | scope.row, |
| | | 'followUpSuccessInfo', |
| | | '首次完成列表' |
| | | ) |
| | | " |
| | | > |
| | | <span class="button-zx">{{ scope.row.followUpSuccess }}</span> |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="失败" align="center" prop="followUpFail"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleViewDetails(scope.row, 'followUpFailInfo', '首次失败列表')"> |
| | | <el-button |
| | | type="text" |
| | | @click=" |
| | | handleViewDetails( |
| | | scope.row, |
| | | 'followUpFailInfo', |
| | | '首次失败列表' |
| | | ) |
| | | " |
| | | > |
| | | <span class="button-zx">{{ scope.row.followUpFail }}</span> |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column v-if="orgname != '景宁畲族自治县人民医院'" label="成功率" align="center" prop="successRate" :render-header="Tooltipcgl"> |
| | | <el-table-column |
| | | v-if="orgname != '景宁畲族自治县人民医院'" |
| | | label="成功率" |
| | | align="center" |
| | | prop="successRate" |
| | | :render-header="Tooltipcgl" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ calculateSuccessRate(scope.row.followUpSuccess, scope.row.needFollowUp, scope.row.pendingFollowUp) }}</span> |
| | | <span>{{ |
| | | calculateSuccessRate( |
| | | scope.row.followUpSuccess, |
| | | scope.row.needFollowUp, |
| | | scope.row.pendingFollowUp |
| | | ) |
| | | }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table-column> |
| | | |
| | | <!-- ===== 再次随访 ===== --> |
| | | <el-table-column align="center" label="再次随访"> |
| | | <el-table-column label="需随访" align="center" prop="needFollowUpAgain"> |
| | | <el-table-column |
| | | label="需随访" |
| | | align="center" |
| | | prop="needFollowUpAgain" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleViewDetails(scope.row, 'needFollowUpAgainInfo', '再次需随访列表')"> |
| | | <el-button |
| | | 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" prop="pendingFollowUpAgain"> |
| | | <el-table-column |
| | | label="待随访" |
| | | align="center" |
| | | prop="pendingFollowUpAgain" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleViewDetails(scope.row, 'pendingFollowUpAgainInfo', '再次待随访列表')"> |
| | | <span class="button-zx">{{ scope.row.pendingFollowUpAgain }}</span> |
| | | <el-button |
| | | 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" prop="followUpSuccessAgain"> |
| | | <el-table-column |
| | | label="完成" |
| | | align="center" |
| | | prop="followUpSuccessAgain" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleViewDetails(scope.row, 'followUpSuccessAgainInfo', '再次完成列表')"> |
| | | <span class="button-zx">{{ scope.row.followUpSuccessAgain }}</span> |
| | | <el-button |
| | | 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" prop="followUpFailAgain"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="handleViewDetails(scope.row, 'followUpFailAgainInfo', '再次失败列表')"> |
| | | <el-button |
| | | type="text" |
| | | @click=" |
| | | handleViewDetails( |
| | | scope.row, |
| | | 'followUpFailAgainInfo', |
| | | '再次失败列表' |
| | | ) |
| | | " |
| | | > |
| | | <span class="button-zx">{{ scope.row.followUpFailAgain }}</span> |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column v-if="orgname != '景宁畲族自治县人民医院'" label="成功率" align="center" prop="successRateAgain" :render-header="Tooltipcgl"> |
| | | <el-table-column |
| | | v-if="orgname != '景宁畲族自治县人民医院'" |
| | | label="成功率" |
| | | align="center" |
| | | prop="successRateAgain" |
| | | :render-header="Tooltipcgl" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ calculateSuccessRate(scope.row.followUpSuccessAgain, scope.row.needFollowUpAgain, scope.row.pendingFollowUpAgain) }}</span> |
| | | <span>{{ |
| | | calculateSuccessRate( |
| | | scope.row.followUpSuccessAgain, |
| | | scope.row.needFollowUpAgain, |
| | | scope.row.pendingFollowUpAgain |
| | | ) |
| | | }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table-column> |
| | | |
| | | <!-- ===== 新增计算指标 ===== --> |
| | | <el-table-column label="随访率" align="center" prop="followUpRate" :render-header="TooltipFollowUpRate"> |
| | | <el-table-column |
| | | label="随访率" |
| | | align="center" |
| | | prop="followUpRate" |
| | | :render-header="TooltipFollowUpRate" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ calculateFollowUpRate(scope.row) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="推送率" align="center" prop="pushRate" :render-header="TooltipPushRate"> |
| | | <el-table-column |
| | | label="推送率" |
| | | align="center" |
| | | prop="pushRate" |
| | | :render-header="TooltipPushRate" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ calculatePushRate(scope.row) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="已拨通" |
| | | align="center" |
| | | prop="manuallyCalled" |
| | | :render-header="TooltipPushRate" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | type="text" |
| | | @click=" |
| | | handleViewDetails( |
| | | scope.row, |
| | | 'manuallyCalledInfo', |
| | | '已拨通列表', |
| | | '1' |
| | | ) |
| | | " |
| | | > |
| | | <span class="button-zx">{{ scope.row.manuallyCalled }}</span> |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | const params = { |
| | | ...this.queryParams, |
| | | // 不传 visitCount,后端返回包含首次和再次的数据 |
| | | 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, |
| | |
| | | }, |
| | | |
| | | getAllWardCodes() { |
| | | return this.flatArrayhospit.filter((item) => item.value !== "all").map((item) => item.value); |
| | | return this.flatArrayhospit |
| | | .filter((item) => item.value !== "all") |
| | | .map((item) => item.value); |
| | | }, |
| | | getAllDeptCodes() { |
| | | return this.flatArraydept.filter((item) => item.value !== "all").map((item) => item.value); |
| | | return this.flatArraydept |
| | | .filter((item) => item.value !== "all") |
| | | .map((item) => item.value); |
| | | }, |
| | | |
| | | // ===================== 排序 ===================== |
| | | customSort(data) { |
| | | const order = [ |
| | | "一", "二", "三", "四", "五", "六", "七", "八", "九", "十", |
| | | "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十", |
| | | "二十一", "二十二", "二十三", "二十四", "二十五", "二十六", "二十七", "二十八", "二十九", "三十", |
| | | "三十一", "三十二", "三十三", "三十四", "三十五", "三十六", "三十七", "三十八", "三十九", "四十", |
| | | "四十一", "四十二", "四十三", "四十四", "四十五", |
| | | "一", |
| | | "二", |
| | | "三", |
| | | "四", |
| | | "五", |
| | | "六", |
| | | "七", |
| | | "八", |
| | | "九", |
| | | "十", |
| | | "十一", |
| | | "十二", |
| | | "十三", |
| | | "十四", |
| | | "十五", |
| | | "十六", |
| | | "十七", |
| | | "十八", |
| | | "十九", |
| | | "二十", |
| | | "二十一", |
| | | "二十二", |
| | | "二十三", |
| | | "二十四", |
| | | "二十五", |
| | | "二十六", |
| | | "二十七", |
| | | "二十八", |
| | | "二十九", |
| | | "三十", |
| | | "三十一", |
| | | "三十二", |
| | | "三十三", |
| | | "三十四", |
| | | "三十五", |
| | | "三十六", |
| | | "三十七", |
| | | "三十八", |
| | | "三十九", |
| | | "四十", |
| | | "四十一", |
| | | "四十二", |
| | | "四十三", |
| | | "四十四", |
| | | "四十五", |
| | | ]; |
| | | return data.sort((a, b) => { |
| | | const getIndex = (name) => { |
| | |
| | | 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; |
| | |
| | | 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 (match && match[1]) { |
| | | const chineseNum = match[1]; |
| | | return chineseNumMap[chineseNum] !== undefined ? chineseNumMap[chineseNum] : -1; |
| | | return chineseNumMap[chineseNum] !== undefined |
| | | ? chineseNumMap[chineseNum] |
| | | : -1; |
| | | } |
| | | const arabicMatch = text.match(/^(\d+)/); |
| | | if (arabicMatch && arabicMatch[1]) { |
| | |
| | | |
| | | // ===================== 行展开 ===================== |
| | | getRowKey(row) { |
| | | return row.statisticaltype === 1 ? row.leavehospitaldistrictcode : row.deptcode; |
| | | return row.statisticaltype === 1 |
| | | ? row.leavehospitaldistrictcode |
| | | : row.deptcode; |
| | | }, |
| | | |
| | | handleRowClick(row) { |
| | |
| | | const nonFollowUp = Number(row.nonFollowUp) || 0; |
| | | const followUpNeeded = Number(row.followUpNeeded) || 0; |
| | | const denominator = followUpNeeded + nonFollowUp; |
| | | console.log(successAgain,nonFollowUp,followUpNeeded); |
| | | console.log(successAgain, nonFollowUp, followUpNeeded); |
| | | |
| | | if (denominator <= 0) return "0.00%"; |
| | | return ((successAgain / denominator) * 100).toFixed(2) + "%"; |
| | |
| | | // 因为计算复杂,这里简化为 "-" |
| | | sums[index] = "-"; |
| | | } else if (prop === "followUpRate") { |
| | | const values = data.map((row) => parseFloat(this.calculateFollowUpRate(row).replace("%", ""))).filter(v => !isNaN(v)); |
| | | const values = data |
| | | .map((row) => |
| | | parseFloat(this.calculateFollowUpRate(row).replace("%", "")) |
| | | ) |
| | | .filter((v) => !isNaN(v)); |
| | | if (values.length === 0) sums[index] = "0.00%"; |
| | | else sums[index] = (values.reduce((a, b) => a + b, 0) / values.length).toFixed(2) + "%"; |
| | | else |
| | | sums[index] = |
| | | (values.reduce((a, b) => a + b, 0) / values.length).toFixed(2) + |
| | | "%"; |
| | | } else if (prop === "pushRate") { |
| | | const values = data.map((row) => parseFloat(this.calculatePushRate(row).replace("%", ""))).filter(v => !isNaN(v)); |
| | | const values = data |
| | | .map((row) => |
| | | parseFloat(this.calculatePushRate(row).replace("%", "")) |
| | | ) |
| | | .filter((v) => !isNaN(v)); |
| | | if (values.length === 0) sums[index] = "0.00%"; |
| | | else sums[index] = (values.reduce((a, b) => a + b, 0) / values.length).toFixed(2) + "%"; |
| | | else |
| | | sums[index] = |
| | | (values.reduce((a, b) => a + b, 0) / values.length).toFixed(2) + |
| | | "%"; |
| | | } else { |
| | | // 数字列求和 |
| | | const values = data.map((item) => Number(item[prop]) || 0); |
| | |
| | | if (prop === "successRate" || prop === "successRateAgain") { |
| | | sums[index] = "-"; |
| | | } else if (prop === "followUpRate") { |
| | | const values = data.map((row) => parseFloat(this.calculateFollowUpRate(row).replace("%", ""))).filter(v => !isNaN(v)); |
| | | sums[index] = values.length ? (values.reduce((a, b) => a + b, 0) / values.length).toFixed(2) + "%" : "0.00%"; |
| | | const values = data |
| | | .map((row) => |
| | | parseFloat(this.calculateFollowUpRate(row).replace("%", "")) |
| | | ) |
| | | .filter((v) => !isNaN(v)); |
| | | sums[index] = values.length |
| | | ? (values.reduce((a, b) => a + b, 0) / values.length).toFixed(2) + |
| | | "%" |
| | | : "0.00%"; |
| | | } else if (prop === "pushRate") { |
| | | const values = data.map((row) => parseFloat(this.calculatePushRate(row).replace("%", ""))).filter(v => !isNaN(v)); |
| | | sums[index] = values.length ? (values.reduce((a, b) => a + b, 0) / values.length).toFixed(2) + "%" : "0.00%"; |
| | | const values = data |
| | | .map((row) => |
| | | parseFloat(this.calculatePushRate(row).replace("%", "")) |
| | | ) |
| | | .filter((v) => !isNaN(v)); |
| | | sums[index] = values.length |
| | | ? (values.reduce((a, b) => a + b, 0) / values.length).toFixed(2) + |
| | | "%" |
| | | : "0.00%"; |
| | | } else { |
| | | const values = data.map((item) => Number(item[prop]) || 0); |
| | | sums[index] = values.reduce((a, b) => a + b, 0); |
| | |
| | | |
| | | // ===================== 点击钻取 ===================== |
| | | handleViewDetails(row, infoKey, titleSuffix, type) { |
| | | const title = `${row.leavehospitaldistrictname || row.deptname}${titleSuffix}`; |
| | | const title = `${ |
| | | row.leavehospitaldistrictname || row.deptname |
| | | }${titleSuffix}`; |
| | | this.$emit("view-details", row, infoKey, title, type); |
| | | }, |
| | | |
| | |
| | | try { |
| | | let dateRangeString = ""; |
| | | const isLishuiHospital = this.orgname === "丽水市中医院"; |
| | | if (this.queryParams.dateRange && this.queryParams.dateRange.length === 2) { |
| | | if ( |
| | | this.queryParams.dateRange && |
| | | this.queryParams.dateRange.length === 2 |
| | | ) { |
| | | const start = this.queryParams.dateRange[0]; |
| | | const end = this.queryParams.dateRange[1]; |
| | | if (isLishuiHospital) { |
| | |
| | | } |
| | | } else { |
| | | const now = new Date(); |
| | | dateRangeString = isLishuiHospital ? `${now.getFullYear()}年${now.getMonth() + 1}月` : `${now.getMonth() + 1}月`; |
| | | dateRangeString = isLishuiHospital |
| | | ? `${now.getFullYear()}年${now.getMonth() + 1}月` |
| | | : `${now.getMonth() + 1}月`; |
| | | } |
| | | |
| | | const serviceTypeLabel = this.getServiceTypeLabel(); |
| | | const serviceTypeSuffix = serviceTypeLabel ? `_${serviceTypeLabel}` : ""; |
| | | const serviceTypeSuffix = serviceTypeLabel |
| | | ? `_${serviceTypeLabel}` |
| | | : ""; |
| | | const excelName = `综合随访统计表${serviceTypeSuffix}_${dateRangeString}.xlsx`; |
| | | if (!this.tableData || this.tableData.length === 0) { |
| | | this.$message.warning("暂无数据可导出"); |
| | |
| | | const titleStyle = { |
| | | font: { name: "微软雅黑", size: 16, bold: true }, |
| | | alignment: { horizontal: "center", vertical: "middle" }, |
| | | fill: { type: "pattern", pattern: "solid", fgColor: { argb: "FFE6F3FF" } }, |
| | | border: { top: { style: "thin" }, left: { style: "thin" }, bottom: { style: "thin" }, right: { style: "thin" } }, |
| | | fill: { |
| | | type: "pattern", |
| | | pattern: "solid", |
| | | fgColor: { argb: "FFE6F3FF" }, |
| | | }, |
| | | border: { |
| | | top: { style: "thin" }, |
| | | left: { style: "thin" }, |
| | | bottom: { style: "thin" }, |
| | | right: { style: "thin" }, |
| | | }, |
| | | }; |
| | | const headerStyle = { |
| | | font: { name: "微软雅黑", size: 11, bold: true }, |
| | | fill: { type: "pattern", pattern: "solid", fgColor: { argb: "FFF5F7FA" } }, |
| | | 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" } }, |
| | | 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" } }, |
| | | border: { |
| | | top: { style: "thin" }, |
| | | left: { style: "thin" }, |
| | | bottom: { style: "thin" }, |
| | | right: { style: "thin" }, |
| | | }, |
| | | }; |
| | | const summaryStyle = { |
| | | ...cellStyle, |
| | | font: { ...cellStyle.font, bold: true, color: { argb: "FF409EFF" } }, |
| | | fill: { type: "pattern", pattern: "solid", fgColor: { argb: "FFF5F7FA" } }, |
| | | fill: { |
| | | type: "pattern", |
| | | pattern: "solid", |
| | | fgColor: { argb: "FFF5F7FA" }, |
| | | }, |
| | | }; |
| | | |
| | | // 标题行 |
| | | worksheet.mergeCells(1, 1, 1, 20); |
| | | worksheet.getCell(1, 1).value = `综合随访统计表${serviceTypeSuffix}_${dateRangeString}`; |
| | | worksheet.getCell( |
| | | 1, |
| | | 1 |
| | | ).value = `综合随访统计表${serviceTypeSuffix}_${dateRangeString}`; |
| | | worksheet.getCell(1, 1).style = titleStyle; |
| | | worksheet.getRow(1).height = 35; |
| | | |
| | |
| | | |
| | | // 病区/科室 |
| | | worksheet.mergeCells(2, 2, 3, 2); |
| | | worksheet.getCell(2, 2).value = this.queryParams.statisticaltype == 1 ? "出院病区" : "科室"; |
| | | worksheet.getCell(2, 2).value = |
| | | this.queryParams.statisticaltype == 1 ? "出院病区" : "科室"; |
| | | worksheet.getCell(2, 2).style = headerStyle; |
| | | |
| | | // 出院人次 |
| | |
| | | worksheet.mergeCells(2, 4, 2, 10); |
| | | worksheet.getCell(2, 4).value = "首次随访"; |
| | | worksheet.getCell(2, 4).style = headerStyle; |
| | | const firstCols = ["无需随访", "应随访", "需随访", "待随访", "完成", "失败", "成功率"]; |
| | | const firstCols = [ |
| | | "无需随访", |
| | | "应随访", |
| | | "需随访", |
| | | "待随访", |
| | | "完成", |
| | | "失败", |
| | | "成功率", |
| | | ]; |
| | | firstCols.forEach((label, idx) => { |
| | | const col = 4 + idx; |
| | | worksheet.getCell(3, col).value = label; |
| | |
| | | item.pendingFollowUp || 0, |
| | | item.followUpSuccess || 0, |
| | | item.followUpFail || 0, |
| | | this.calculateSuccessRate(item.followUpSuccess, item.needFollowUp, item.pendingFollowUp), |
| | | this.calculateSuccessRate( |
| | | item.followUpSuccess, |
| | | item.needFollowUp, |
| | | item.pendingFollowUp |
| | | ), |
| | | item.needFollowUpAgain || 0, |
| | | item.pendingFollowUpAgain || 0, |
| | | item.followUpSuccessAgain || 0, |
| | | item.followUpFailAgain || 0, |
| | | this.calculateSuccessRate(item.followUpSuccessAgain, item.needFollowUpAgain, item.pendingFollowUpAgain), |
| | | this.calculateSuccessRate( |
| | | item.followUpSuccessAgain, |
| | | item.needFollowUpAgain, |
| | | item.pendingFollowUpAgain |
| | | ), |
| | | this.calculateFollowUpRate(item), |
| | | this.calculatePushRate(item), |
| | | ]; |
| | | const row = worksheet.addRow(rowData); |
| | | row.eachCell((cell) => { cell.style = cellStyle; }); |
| | | row.eachCell((cell) => { |
| | | cell.style = cellStyle; |
| | | }); |
| | | row.height = 24; |
| | | }); |
| | | |
| | | // 合计行 |
| | | const summaries = this.getExportSummaries(); |
| | | const summaryRow = worksheet.addRow(summaries); |
| | | summaryRow.eachCell((cell) => { cell.style = summaryStyle; }); |
| | | summaryRow.eachCell((cell) => { |
| | | cell.style = summaryStyle; |
| | | }); |
| | | |
| | | // 列宽 |
| | | worksheet.columns = [ |
| | | { width: 8 }, |
| | | { width: 20 }, |
| | | { width: 12 }, |
| | | { width: 12 }, { width: 12 }, { width: 12 }, { width: 12 }, { width: 12 }, { width: 12 }, { width: 12 }, |
| | | { width: 12 }, { width: 12 }, { width: 12 }, { width: 12 }, { width: 12 }, |
| | | { width: 12 }, { width: 12 }, |
| | | { width: 12 }, |
| | | { width: 12 }, |
| | | { width: 12 }, |
| | | { width: 12 }, |
| | | { width: 12 }, |
| | | { width: 12 }, |
| | | { width: 12 }, |
| | | { width: 12 }, |
| | | { width: 12 }, |
| | | { width: 12 }, |
| | | { width: 12 }, |
| | | { width: 12 }, |
| | | { width: 12 }, |
| | | { width: 12 }, |
| | | ]; |
| | | }, |
| | | |
| | | getExportSummaries() { |
| | | // 提取数据,计算合计行 |
| | | const data = this.tableData; |
| | | const sums = ["合计", "/", 0, 0, 0, 0, 0, 0, 0, "0%", 0, 0, 0, 0, "0%", "0%", "0%"]; |
| | | const sums = [ |
| | | "合计", |
| | | "/", |
| | | 0, |
| | | 0, |
| | | 0, |
| | | 0, |
| | | 0, |
| | | 0, |
| | | 0, |
| | | "0%", |
| | | 0, |
| | | 0, |
| | | 0, |
| | | 0, |
| | | "0%", |
| | | "0%", |
| | | "0%", |
| | | ]; |
| | | // 数字列索引 |
| | | const numIndices = [2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13]; |
| | | data.forEach(row => { |
| | | numIndices.forEach(idx => { |
| | | data.forEach((row) => { |
| | | numIndices.forEach((idx) => { |
| | | const val = Number(row[this.getFieldByIndex(idx)]) || 0; |
| | | sums[idx] += val; |
| | | }); |
| | | }); |
| | | // 格式化数字 |
| | | numIndices.forEach(idx => { sums[idx] = this.formatNumber(sums[idx]); }); |
| | | numIndices.forEach((idx) => { |
| | | sums[idx] = this.formatNumber(sums[idx]); |
| | | }); |
| | | // 计算两个百分比列的平均值 |
| | | const followUpRates = data.map(row => parseFloat(this.calculateFollowUpRate(row).replace("%", ""))).filter(v => !isNaN(v)); |
| | | const pushRates = data.map(row => parseFloat(this.calculatePushRate(row).replace("%", ""))).filter(v => !isNaN(v)); |
| | | sums[15] = followUpRates.length ? (followUpRates.reduce((a,b)=>a+b,0)/followUpRates.length).toFixed(2)+"%" : "0.00%"; |
| | | sums[16] = pushRates.length ? (pushRates.reduce((a,b)=>a+b,0)/pushRates.length).toFixed(2)+"%" : "0.00%"; |
| | | const followUpRates = data |
| | | .map((row) => |
| | | parseFloat(this.calculateFollowUpRate(row).replace("%", "")) |
| | | ) |
| | | .filter((v) => !isNaN(v)); |
| | | const pushRates = data |
| | | .map((row) => parseFloat(this.calculatePushRate(row).replace("%", ""))) |
| | | .filter((v) => !isNaN(v)); |
| | | sums[15] = followUpRates.length |
| | | ? ( |
| | | followUpRates.reduce((a, b) => a + b, 0) / followUpRates.length |
| | | ).toFixed(2) + "%" |
| | | : "0.00%"; |
| | | sums[16] = pushRates.length |
| | | ? (pushRates.reduce((a, b) => a + b, 0) / pushRates.length).toFixed(2) + |
| | | "%" |
| | | : "0.00%"; |
| | | // 成功率的合计用整体法计算 |
| | | const totalSuccess = data.reduce((s, row) => s + (Number(row.followUpSuccess)||0), 0); |
| | | const totalNeed = data.reduce((s, row) => s + (Number(row.needFollowUp)||0), 0); |
| | | const totalPending = data.reduce((s, row) => s + (Number(row.pendingFollowUp)||0), 0); |
| | | const totalSuccess = data.reduce( |
| | | (s, row) => s + (Number(row.followUpSuccess) || 0), |
| | | 0 |
| | | ); |
| | | const totalNeed = data.reduce( |
| | | (s, row) => s + (Number(row.needFollowUp) || 0), |
| | | 0 |
| | | ); |
| | | const totalPending = data.reduce( |
| | | (s, row) => s + (Number(row.pendingFollowUp) || 0), |
| | | 0 |
| | | ); |
| | | const denom = totalNeed - totalPending; |
| | | sums[9] = denom > 0 ? ((totalSuccess/denom)*100).toFixed(2)+"%" : "0.00%"; |
| | | const totalSuccessAgain = data.reduce((s, row) => s + (Number(row.followUpSuccessAgain)||0), 0); |
| | | const totalNeedAgain = data.reduce((s, row) => s + (Number(row.needFollowUpAgain)||0), 0); |
| | | const totalPendingAgain = data.reduce((s, row) => s + (Number(row.pendingFollowUpAgain)||0), 0); |
| | | sums[9] = |
| | | denom > 0 ? ((totalSuccess / denom) * 100).toFixed(2) + "%" : "0.00%"; |
| | | const totalSuccessAgain = data.reduce( |
| | | (s, row) => s + (Number(row.followUpSuccessAgain) || 0), |
| | | 0 |
| | | ); |
| | | const totalNeedAgain = data.reduce( |
| | | (s, row) => s + (Number(row.needFollowUpAgain) || 0), |
| | | 0 |
| | | ); |
| | | const totalPendingAgain = data.reduce( |
| | | (s, row) => s + (Number(row.pendingFollowUpAgain) || 0), |
| | | 0 |
| | | ); |
| | | const denomAgain = totalNeedAgain - totalPendingAgain; |
| | | sums[14] = denomAgain > 0 ? ((totalSuccessAgain/denomAgain)*100).toFixed(2)+"%" : "0.00%"; |
| | | sums[14] = |
| | | denomAgain > 0 |
| | | ? ((totalSuccessAgain / denomAgain) * 100).toFixed(2) + "%" |
| | | : "0.00%"; |
| | | return sums; |
| | | }, |
| | | |
| | |
| | | // ===================== 导出医生子表 ===================== |
| | | async exportDoctorTable(row) { |
| | | try { |
| | | const areaName = row.leavehospitaldistrictname || row.deptname || "未知病区"; |
| | | const areaName = |
| | | row.leavehospitaldistrictname || row.deptname || "未知病区"; |
| | | let dateRangeString = ""; |
| | | if (this.queryParams.dateRange && this.queryParams.dateRange.length === 2) { |
| | | 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}`; |
| | |
| | | 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); |
| | | saveAs( |
| | | new Blob([buffer], { |
| | | type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", |
| | | }), |
| | | fileName |
| | | ); |
| | | this.$message.success("医生综合随访列表导出成功"); |
| | | } catch (err) { |
| | | console.error(err); |
| | |
| | | }, |
| | | |
| | | buildDoctorExportSheet(worksheet, data, areaName) { |
| | | const titleStyle = { font: { name: "微软雅黑", size: 16, bold: true }, alignment: { horizontal: "center", vertical: "middle" } }; |
| | | const titleStyle = { |
| | | font: { name: "微软雅黑", size: 16, bold: true }, |
| | | alignment: { horizontal: "center", vertical: "middle" }, |
| | | }; |
| | | const headerStyle = { |
| | | font: { name: "微软雅黑", size: 11, bold: true }, |
| | | fill: { type: "pattern", pattern: "solid", fgColor: { argb: "FFF5F7FA" } }, |
| | | 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" } }, |
| | | 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" } }, |
| | | border: { |
| | | top: { style: "thin" }, |
| | | left: { style: "thin" }, |
| | | bottom: { style: "thin" }, |
| | | right: { style: "thin" }, |
| | | }, |
| | | }; |
| | | const summaryStyle = { ...cellStyle, font: { ...cellStyle.font, bold: true } }; |
| | | const summaryStyle = { |
| | | ...cellStyle, |
| | | font: { ...cellStyle.font, bold: true }, |
| | | }; |
| | | |
| | | worksheet.mergeCells(1, 1, 1, 17); |
| | | worksheet.getCell(1, 1).value = `${areaName}医生综合随访列表`; |
| | |
| | | worksheet.getRow(1).height = 30; |
| | | |
| | | const headers = [ |
| | | "医生姓名", "科室", "出院人次", |
| | | "首次无需随访", "首次应随访", "首次需随访", "首次待随访", "首次完成", "首次失败", "首次成功率", |
| | | "再次需随访", "再次待随访", "再次完成", "再次失败", "再次成功率", |
| | | "随访率", "推送率" |
| | | "医生姓名", |
| | | "科室", |
| | | "出院人次", |
| | | "首次无需随访", |
| | | "首次应随访", |
| | | "首次需随访", |
| | | "首次待随访", |
| | | "首次完成", |
| | | "首次失败", |
| | | "首次成功率", |
| | | "再次需随访", |
| | | "再次待随访", |
| | | "再次完成", |
| | | "再次失败", |
| | | "再次成功率", |
| | | "随访率", |
| | | "推送率", |
| | | ]; |
| | | const headerRow = worksheet.addRow(headers); |
| | | headerRow.eachCell((cell) => { cell.style = headerStyle; }); |
| | | headerRow.eachCell((cell) => { |
| | | cell.style = headerStyle; |
| | | }); |
| | | worksheet.getRow(2).height = 25; |
| | | |
| | | data.forEach(item => { |
| | | data.forEach((item) => { |
| | | const row = worksheet.addRow([ |
| | | item.drname, |
| | | item.deptname, |
| | |
| | | item.pendingFollowUp, |
| | | item.followUpSuccess, |
| | | item.followUpFail, |
| | | this.calculateSuccessRate(item.followUpSuccess, item.needFollowUp, item.pendingFollowUp), |
| | | this.calculateSuccessRate( |
| | | item.followUpSuccess, |
| | | item.needFollowUp, |
| | | item.pendingFollowUp |
| | | ), |
| | | item.needFollowUpAgain, |
| | | item.pendingFollowUpAgain, |
| | | item.followUpSuccessAgain, |
| | | item.followUpFailAgain, |
| | | this.calculateSuccessRate(item.followUpSuccessAgain, item.needFollowUpAgain, item.pendingFollowUpAgain), |
| | | this.calculateSuccessRate( |
| | | item.followUpSuccessAgain, |
| | | item.needFollowUpAgain, |
| | | item.pendingFollowUpAgain |
| | | ), |
| | | this.calculateFollowUpRate(item), |
| | | this.calculatePushRate(item), |
| | | ]); |
| | | row.eachCell((cell) => { cell.style = cellStyle; }); |
| | | row.eachCell((cell) => { |
| | | cell.style = cellStyle; |
| | | }); |
| | | row.height = 24; |
| | | }); |
| | | |
| | | // 小计 |
| | | const summaryRow = worksheet.addRow(this.getDoctorExportSummary(data)); |
| | | summaryRow.eachCell((cell) => { cell.style = summaryStyle; }); |
| | | summaryRow.eachCell((cell) => { |
| | | cell.style = summaryStyle; |
| | | }); |
| | | |
| | | worksheet.columns = Array(17).fill({ width: 12 }); |
| | | worksheet.columns[0].width = 15; |
| | |
| | | }, |
| | | |
| | | getDoctorExportSummary(data) { |
| | | const sums = ["小计", "-", 0, 0, 0, 0, 0, 0, 0, "0%", 0, 0, 0, 0, "0%", "0%", "0%"]; |
| | | const sums = [ |
| | | "小计", |
| | | "-", |
| | | 0, |
| | | 0, |
| | | 0, |
| | | 0, |
| | | 0, |
| | | 0, |
| | | 0, |
| | | "0%", |
| | | 0, |
| | | 0, |
| | | 0, |
| | | 0, |
| | | "0%", |
| | | "0%", |
| | | "0%", |
| | | ]; |
| | | const numIndices = [2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13]; |
| | | data.forEach(row => { |
| | | numIndices.forEach(idx => { |
| | | data.forEach((row) => { |
| | | numIndices.forEach((idx) => { |
| | | const val = Number(row[this.getFieldByIndex(idx)]) || 0; |
| | | sums[idx] += val; |
| | | }); |
| | | }); |
| | | numIndices.forEach(idx => { sums[idx] = this.formatNumber(sums[idx]); }); |
| | | numIndices.forEach((idx) => { |
| | | sums[idx] = this.formatNumber(sums[idx]); |
| | | }); |
| | | // 平均值 |
| | | const followUpRates = data.map(row => parseFloat(this.calculateFollowUpRate(row).replace("%", ""))).filter(v => !isNaN(v)); |
| | | const pushRates = data.map(row => parseFloat(this.calculatePushRate(row).replace("%", ""))).filter(v => !isNaN(v)); |
| | | sums[15] = followUpRates.length ? (followUpRates.reduce((a,b)=>a+b,0)/followUpRates.length).toFixed(2)+"%" : "0.00%"; |
| | | sums[16] = pushRates.length ? (pushRates.reduce((a,b)=>a+b,0)/pushRates.length).toFixed(2)+"%" : "0.00%"; |
| | | const followUpRates = data |
| | | .map((row) => |
| | | parseFloat(this.calculateFollowUpRate(row).replace("%", "")) |
| | | ) |
| | | .filter((v) => !isNaN(v)); |
| | | const pushRates = data |
| | | .map((row) => parseFloat(this.calculatePushRate(row).replace("%", ""))) |
| | | .filter((v) => !isNaN(v)); |
| | | sums[15] = followUpRates.length |
| | | ? ( |
| | | followUpRates.reduce((a, b) => a + b, 0) / followUpRates.length |
| | | ).toFixed(2) + "%" |
| | | : "0.00%"; |
| | | sums[16] = pushRates.length |
| | | ? (pushRates.reduce((a, b) => a + b, 0) / pushRates.length).toFixed(2) + |
| | | "%" |
| | | : "0.00%"; |
| | | // 成功率整体法 |
| | | const totalSuccess = data.reduce((s, row) => s + (Number(row.followUpSuccess)||0), 0); |
| | | const totalNeed = data.reduce((s, row) => s + (Number(row.needFollowUp)||0), 0); |
| | | const totalPending = data.reduce((s, row) => s + (Number(row.pendingFollowUp)||0), 0); |
| | | const totalSuccess = data.reduce( |
| | | (s, row) => s + (Number(row.followUpSuccess) || 0), |
| | | 0 |
| | | ); |
| | | const totalNeed = data.reduce( |
| | | (s, row) => s + (Number(row.needFollowUp) || 0), |
| | | 0 |
| | | ); |
| | | const totalPending = data.reduce( |
| | | (s, row) => s + (Number(row.pendingFollowUp) || 0), |
| | | 0 |
| | | ); |
| | | const denom = totalNeed - totalPending; |
| | | sums[9] = denom > 0 ? ((totalSuccess/denom)*100).toFixed(2)+"%" : "0.00%"; |
| | | const totalSuccessAgain = data.reduce((s, row) => s + (Number(row.followUpSuccessAgain)||0), 0); |
| | | const totalNeedAgain = data.reduce((s, row) => s + (Number(row.needFollowUpAgain)||0), 0); |
| | | const totalPendingAgain = data.reduce((s, row) => s + (Number(row.pendingFollowUpAgain)||0), 0); |
| | | sums[9] = |
| | | denom > 0 ? ((totalSuccess / denom) * 100).toFixed(2) + "%" : "0.00%"; |
| | | const totalSuccessAgain = data.reduce( |
| | | (s, row) => s + (Number(row.followUpSuccessAgain) || 0), |
| | | 0 |
| | | ); |
| | | const totalNeedAgain = data.reduce( |
| | | (s, row) => s + (Number(row.needFollowUpAgain) || 0), |
| | | 0 |
| | | ); |
| | | const totalPendingAgain = data.reduce( |
| | | (s, row) => s + (Number(row.pendingFollowUpAgain) || 0), |
| | | 0 |
| | | ); |
| | | const denomAgain = totalNeedAgain - totalPendingAgain; |
| | | sums[14] = denomAgain > 0 ? ((totalSuccessAgain/denomAgain)*100).toFixed(2)+"%" : "0.00%"; |
| | | sums[14] = |
| | | denomAgain > 0 |
| | | ? ((totalSuccessAgain / denomAgain) * 100).toFixed(2) + "%" |
| | | : "0.00%"; |
| | | return sums; |
| | | }, |
| | | |
| | | // ===================== Tooltips ===================== |
| | | Tooltipcgl(h, { column }) { |
| | | return h("el-tooltip", { |
| | | props: { content: "随访成功/(需随访-待随访)", placement: "top", effect: "dark" }, |
| | | }, [h("span", column.label)]); |
| | | return h( |
| | | "el-tooltip", |
| | | { |
| | | props: { |
| | | content: "随访成功/(需随访-待随访)", |
| | | placement: "top", |
| | | effect: "dark", |
| | | }, |
| | | }, |
| | | [h("span", column.label)] |
| | | ); |
| | | }, |
| | | TooltipFollowUpRate(h, { column }) { |
| | | return h("el-tooltip", { |
| | | props: { content: "(首次完成+首次无需随访)/(首次应随访+首次无需随访)", placement: "top", effect: "dark" }, |
| | | }, [h("span", column.label)]); |
| | | return h( |
| | | "el-tooltip", |
| | | { |
| | | props: { |
| | | content: "(首次完成+首次无需随访)/(首次应随访+首次无需随访)", |
| | | placement: "top", |
| | | effect: "dark", |
| | | }, |
| | | }, |
| | | [h("span", column.label)] |
| | | ); |
| | | }, |
| | | TooltipPushRate(h, { column }) { |
| | | return h("el-tooltip", { |
| | | props: { content: "再次完成/(首次应随访+首次无需随访)", placement: "top", effect: "dark" }, |
| | | }, [h("span", column.label)]); |
| | | return h( |
| | | "el-tooltip", |
| | | { |
| | | props: { |
| | | content: "再次完成/(首次应随访+首次无需随访)", |
| | | placement: "top", |
| | | effect: "dark", |
| | | }, |
| | | }, |
| | | [h("span", column.label)] |
| | | ); |
| | | }, |
| | | }, |
| | | }; |