| | |
| | | > |
| | | <el-date-picker |
| | | v-model="queryParams.dateRange" |
| | | value-format="yyyy-MM-dd" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | type="daterange" |
| | | range-separator="至" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | :default-time="['00:00:00', '23:59:59']" |
| | | > |
| | | > |
| | | </el-date-picker> |
| | | </el-form-item> |
| | | |
| | |
| | | plain |
| | | icon="el-icon-download" |
| | | size="medium" |
| | | @click="handleExport" |
| | | @click="exportTable" |
| | | >导出</el-button |
| | | > |
| | | <el-button |
| | |
| | | </el-form> |
| | | <div class="your-table-container"> |
| | | <el-table |
| | | ref="exportTable" |
| | | id="exportTableid" |
| | | v-loading="loading" |
| | | :data="userList" |
| | | :border="true" |
| | |
| | | key="pendingFollowUp" |
| | | prop="pendingFollowUp" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="medium" |
| | | type="text" |
| | | @click=" |
| | | viewDetails( |
| | | scope.row.pendingFollowUpInfo, |
| | | scope.row.leavehospitaldistrictname + '待随访列表' |
| | | ) |
| | | " |
| | | ><span class="button-zx">{{ |
| | | scope.row.pendingFollowUp |
| | | }}</span></el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="随访成功" |
| | |
| | | key="followUpFail" |
| | | prop="followUpFail" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="medium" |
| | | type="text" |
| | | @click=" |
| | | viewDetails( |
| | | scope.row.followUpFailInfo, |
| | | scope.row.leavehospitaldistrictname + '随访失败列表' |
| | | ) |
| | | " |
| | | ><span class="button-zx">{{ |
| | | scope.row.followUpFail |
| | | }}</span></el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="随访率" |
| | |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | <!-- 各类详情 --> |
| | | <el-dialog |
| | | :title="infotitle" |
| | | :visible.sync="infotitleVisible" |
| | | v-loading="infotitloading" |
| | | width="70%" |
| | | :close-on-click-modal="false" |
| | | > |
| | | <div class="examine-jic"> |
| | | <div class="jic-value"> |
| | | <el-row :gutter="20"> |
| | | <!-- 选择患者列表 --> |
| | | <el-table :data="infotitlelist" height="660" style="width: 100%"> |
| | | <el-table-column |
| | | prop="sendname" |
| | | align="center" |
| | | label="姓名" |
| | | width="100" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | prop="taskName" |
| | | align="center" |
| | | width="200" |
| | | show-overflow-tooltip |
| | | label="任务名称" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | prop="sendstate" |
| | | align="center" |
| | | width="200" |
| | | label="任务状态" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <div v-if="scope.row.sendstate == 1"> |
| | | <el-tag type="primary" :disable-transitions="false" |
| | | >表单已领取</el-tag |
| | | > |
| | | </div> |
| | | <div v-if="scope.row.sendstate == 2"> |
| | | <el-tag type="primary" :disable-transitions="false" |
| | | >待随访</el-tag |
| | | > |
| | | </div> |
| | | <div v-if="scope.row.sendstate == 3"> |
| | | <el-tag type="success" :disable-transitions="false" |
| | | >表单已发送</el-tag |
| | | > |
| | | </div> |
| | | <div v-if="scope.row.sendstate == 4"> |
| | | <el-tag type="info" :disable-transitions="false" |
| | | >不执行</el-tag |
| | | > |
| | | </div> |
| | | <div v-if="scope.row.sendstate == 5"> |
| | | <el-tag type="danger" :disable-transitions="false" |
| | | >发送失败</el-tag |
| | | > |
| | | </div> |
| | | <div v-if="scope.row.sendstate == 6"> |
| | | <el-tag type="success" :disable-transitions="false" |
| | | >已完成</el-tag |
| | | > |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | prop="visitTime" |
| | | align="center" |
| | | label="应随访时间" |
| | | width="200" |
| | | show-overflow-tooltip |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | prop="finishtime" |
| | | align="center" |
| | | label="随访完成时间" |
| | | width="200" |
| | | show-overflow-tooltip |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="出院日期" |
| | | width="200" |
| | | align="center" |
| | | key="endtime" |
| | | prop="endtime" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ formatTime(scope.row.endtime) }}</span> |
| | | </template></el-table-column |
| | | > |
| | | <el-table-column |
| | | label="责任护士" |
| | | width="120" |
| | | align="center" |
| | | key="nurseName" |
| | | prop="nurseName" |
| | | /> |
| | | <el-table-column |
| | | label="主治医生" |
| | | width="120" |
| | | align="center" |
| | | key="drname" |
| | | prop="drname" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="结果状态" |
| | | align="center" |
| | | key="excep" |
| | | prop="excep" |
| | | width="120" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <dict-tag |
| | | :options="dict.type.sys_yujing" |
| | | :value="scope.row.excep" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="处理意见" |
| | | align="center" |
| | | key="suggest" |
| | | prop="suggest" |
| | | width="120" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <dict-tag |
| | | :options="dict.type.sys_suggest" |
| | | :value="scope.row.suggest" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | prop="templatename" |
| | | align="center" |
| | | label="服务模板" |
| | | width="200" |
| | | show-overflow-tooltip |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | prop="remark" |
| | | align="center" |
| | | label="服务记录" |
| | | width="200" |
| | | show-overflow-tooltip |
| | | > |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | prop="bankcardno" |
| | | align="center" |
| | | label="呼叫状态" |
| | | width="210" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="操作" |
| | | fixed="right" |
| | | align="center" |
| | | width="200" |
| | | class-name="small-padding fixed-width" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="medium" |
| | | type="text" |
| | | @click="SeedetailsgGo(scope.row)" |
| | | ><span class="button-zx" |
| | | ><i class="el-icon-s-order"></i>查看</span |
| | | ></el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-row> |
| | | <pagination |
| | | v-show="patienttotal > 0 && this.patientqueryParams.allhosp != 6" |
| | | :total="patienttotal" |
| | | :page.sync="patientqueryParams.pn" |
| | | :limit.sync="patientqueryParams.ps" |
| | | @pagination="Seedetails" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | } from "@/api/system/label"; |
| | | import store from "@/store"; |
| | | import { getSfStatistics, selectTimelyRate } from "@/api/system/user"; |
| | | |
| | | import * as XLSX from "xlsx"; |
| | | import FileSaver from "file-saver"; |
| | | import ExcelJS from "exceljs"; |
| | | import { saveAs } from "file-saver"; |
| | | import Treeselect from "@riophae/vue-treeselect"; |
| | | import "@riophae/vue-treeselect/dist/vue-treeselect.css"; |
| | | const shortcuts = [ |
| | |
| | | activeName: "first", //侧边选择 |
| | | orgname: "", |
| | | expands: [], |
| | | infotitlelist: [], |
| | | // 遮罩层 |
| | | loading: false, |
| | | Seedloading: false, |
| | | chartDialogVisible: false, |
| | | infotitleVisible: false, |
| | | infotitloading: false, |
| | | infotitle: "", |
| | | pieChart: null, |
| | | barLineChart: null, |
| | | // 选中数组 |
| | |
| | | sums[index] = "合计"; |
| | | return; |
| | | } |
| | | if (index === 1||index === 2) { |
| | | if (index === 1 || index === 2) { |
| | | sums[index] = "/"; |
| | | return; |
| | | } |
| | |
| | | this.Seedloading = false; |
| | | }); |
| | | }, |
| | | viewDetails(row, title) { |
| | | this.infotitleVisible = true; |
| | | this.infotitle = title; |
| | | this.infotitlelist = row; |
| | | }, |
| | | SeedetailsgGo(row) { |
| | | this.SeedetailsVisible = false; |
| | | let type = ""; |
| | |
| | | }) |
| | | .catch(() => {}); |
| | | }, |
| | | /** 导出按钮操作 */ |
| | | handleExport() { |
| | | const params = { |
| | | ...this.queryParams, |
| | | // 如果选择了"全部",则传所有病区/科室代码 |
| | | leavehospitaldistrictcodes: |
| | | this.queryParams.leavehospitaldistrictcodes.includes("all") |
| | | ? this.allWardCodes |
| | | : this.queryParams.leavehospitaldistrictcodes, |
| | | deptcodes: this.queryParams.deptcodes.includes("all") |
| | | ? this.allDeptCodes |
| | | : this.queryParams.deptcodes, |
| | | }; |
| | | delete params.leavehospitaldistrictcodes.all; |
| | | delete params.deptcodes.all; |
| | | this.download( |
| | | "smartor/serviceSubtask/getSfStatisticsExport", |
| | | { |
| | | ...params, |
| | | }, |
| | | `user_${new Date().getTime()}.xlsx` |
| | | ); |
| | | // 导出方法 |
| | | // 替换您原来的 exportTable 方法 |
| | | async exportTable() { |
| | | try { |
| | | // 获取当前日期 |
| | | const now = new Date(); |
| | | // 获取当前月份(注意月份从0开始,需要加1) |
| | | const currentMonth = now.getMonth() + 1; |
| | | // 构建文件名 |
| | | const excelName = `${currentMonth}月出院随访统计表.xlsx`; |
| | | // 创建新的工作簿和工作表 |
| | | const workbook = new ExcelJS.Workbook(); |
| | | const worksheet = workbook.addWorksheet(`${currentMonth}月出院随访统计表`); |
| | | // 定义样式(新增总标题样式) |
| | | 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" } }, |
| | | }, |
| | | }; |
| | | // 定义样式 |
| | | 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" }, |
| | | }, |
| | | 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" } }, |
| | | }, |
| | | }; |
| | | |
| | | const summaryStyle = { |
| | | 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" } }, |
| | | }, |
| | | }; |
| | | // 1. 添加总标题行(第一行) |
| | | worksheet.mergeCells(1, 1, 1, 23); // 合并A1到W1的所有列[1,4](@ref) |
| | | const titleCell = worksheet.getCell(1, 1); |
| | | titleCell.value = `${currentMonth}月出院随访统计表`; // 使用文件名作为总标题 |
| | | titleCell.style = titleStyle; |
| | | worksheet.getRow(1).height = 35; // 设置总标题行高 |
| | | // 1. 首先,创建并设置第二行(子表头)的所有单元格 |
| | | const secondRowHeaders = [ |
| | | "", // A2 展开列占位(其值将由第一行合并后的主单元格决定) |
| | | "出院病区", |
| | | "科室", |
| | | "出院人次", |
| | | "无需随访人次", |
| | | "应随访人次", // B2 to F2 |
| | | // 首次出院随访子表头 |
| | | "需随访", |
| | | "待随访", |
| | | "随访成功", |
| | | "随访失败", |
| | | "随访率", |
| | | "及时率", |
| | | "人工", |
| | | "短信", |
| | | "微信", |
| | | // 再次出院随访子表头 |
| | | "需随访", |
| | | "待随访", |
| | | "随访成功", |
| | | "随访失败", |
| | | "随访率", |
| | | "人工", |
| | | "短信", |
| | | "微信", |
| | | ]; |
| | | |
| | | // 添加第二行(原第一行下移) |
| | | secondRowHeaders.forEach((header, index) => { |
| | | const cell = worksheet.getCell(3, index + 1); // 改为第3行 |
| | | cell.value = header; |
| | | cell.style = headerStyle; |
| | | }); |
| | | |
| | | // 3. 调整原合并单元格位置(原第1行合并单元格下移到第2行) |
| | | // 合并 A2:A3 |
| | | worksheet.mergeCells(2, 1, 3, 1); |
| | | worksheet.getCell(2, 1).value = ""; |
| | | worksheet.getCell(2, 1).style = headerStyle; |
| | | |
| | | // 合并 B2:B3 |
| | | worksheet.mergeCells(2, 2, 3, 2); |
| | | worksheet.getCell(2, 2).value = "出院病区"; |
| | | worksheet.getCell(2, 2).style = headerStyle; |
| | | |
| | | // 合并 C2:C3 |
| | | worksheet.mergeCells(2, 3, 3, 3); |
| | | worksheet.getCell(2, 3).value = "科室"; |
| | | worksheet.getCell(2, 3).style = headerStyle; |
| | | |
| | | // 合并 D2:D3 |
| | | worksheet.mergeCells(2, 4, 3, 4); |
| | | worksheet.getCell(2, 4).value = "出院人次"; |
| | | worksheet.getCell(2, 4).style = headerStyle; |
| | | |
| | | // 合并 E2:E3 |
| | | worksheet.mergeCells(2, 5, 3, 5); |
| | | worksheet.getCell(2, 5).value = "无需随访人次"; |
| | | worksheet.getCell(2, 5).style = headerStyle; |
| | | |
| | | // 合并 F2:F3 |
| | | worksheet.mergeCells(2, 6, 3, 6); |
| | | worksheet.getCell(2, 6).value = "应随访人次"; |
| | | worksheet.getCell(2, 6).style = headerStyle; |
| | | |
| | | // 4. 调整横向合并标题位置(下移到第2行) |
| | | // 首次出院随访(合并G2:O2) |
| | | worksheet.mergeCells(2, 7, 2, 15); // G2:O2 |
| | | worksheet.getCell(2, 7).value = "首次出院随访"; |
| | | worksheet.getCell(2, 7).style = headerStyle; |
| | | |
| | | // 再次出院随访(合并P2:W2) |
| | | worksheet.mergeCells(2, 16, 2, 23); // P2:W2 |
| | | worksheet.getCell(2, 16).value = "再次出院随访"; |
| | | worksheet.getCell(2, 16).style = headerStyle; |
| | | |
| | | // 5. 设置行高 |
| | | worksheet.getRow(1).height = 35; // 总标题行高 |
| | | worksheet.getRow(2).height = 28; // 原第一行下移 |
| | | worksheet.getRow(3).height = 25; // 原第二行下移 |
| | | |
| | | // 6. 添加数据行(注意行索引需要+1,因为上面插入了一行) |
| | | this.userList.forEach((item, rowIndex) => { |
| | | const dataRow = worksheet.addRow([ |
| | | "", // 展开列 |
| | | item.leavehospitaldistrictname || "", |
| | | item.deptname || "", |
| | | item.dischargeCount || 0, |
| | | item.nonFollowUp || 0, |
| | | item.followUpNeeded || 0, |
| | | // 首次出院随访数据 |
| | | item.needFollowUp || 0, |
| | | item.pendingFollowUp || 0, |
| | | item.followUpSuccess || 0, |
| | | item.followUpFail || 0, |
| | | item.followUpRate || "0%", |
| | | item.rate ? (Number(item.rate) * 100).toFixed(2) + "%" : "0%", |
| | | item.manual || 0, |
| | | item.sms || 0, |
| | | item.weChat || 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); // 从第4行开始添加数据(原第3行) |
| | | |
| | | // 应用数据行样式 |
| | | dataRow.eachCell((cell) => { |
| | | cell.style = cellStyle; |
| | | }); |
| | | dataRow.height = 24; |
| | | }); |
| | | |
| | | // 添加合计行 |
| | | const summaries = this.getSummaries({ |
| | | columns: [ |
| | | { property: "" }, |
| | | { property: "leavehospitaldistrictname" }, |
| | | { property: "deptname" }, |
| | | { property: "dischargeCount" }, |
| | | { property: "nonFollowUp" }, |
| | | { property: "followUpNeeded" }, |
| | | { property: "needFollowUp" }, |
| | | { property: "pendingFollowUp" }, |
| | | { property: "followUpSuccess" }, |
| | | { property: "followUpFail" }, |
| | | { property: "followUpRate" }, |
| | | { property: "rate" }, |
| | | { property: "manual" }, |
| | | { property: "sms" }, |
| | | { property: "weChat" }, |
| | | { property: "needFollowUpAgain" }, |
| | | { property: "pendingFollowUpAgain" }, |
| | | { property: "followUpSuccessAgain" }, |
| | | { property: "followUpFailAgain" }, |
| | | { property: "followUpRateAgain" }, |
| | | { property: "manualAgain" }, |
| | | { property: "smsAgain" }, |
| | | { property: "weChatAgain" }, |
| | | ], |
| | | data: this.userList, |
| | | }); |
| | | |
| | | const summaryRow = worksheet.addRow(summaries); |
| | | summaryRow.eachCell((cell, colNumber) => { |
| | | cell.style = summaryStyle; |
| | | // 第一列显示"合计" |
| | | if (colNumber === 1) { |
| | | cell.value = "合计"; |
| | | } |
| | | }); |
| | | 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: 12 }, |
| | | { width: 8 }, |
| | | { width: 8 }, |
| | | { width: 8 }, |
| | | // 再次出院随访列 |
| | | { width: 10 }, |
| | | { width: 10 }, |
| | | { width: 10 }, |
| | | { width: 10 }, |
| | | { width: 12 }, |
| | | { width: 8 }, |
| | | { width: 8 }, |
| | | { width: 8 }, |
| | | ]; |
| | | |
| | | // 生成并下载文件 |
| | | const buffer = await workbook.xlsx.writeBuffer(); |
| | | const blob = new Blob([buffer], { |
| | | type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", |
| | | }); |
| | | saveAs(blob, excelName); |
| | | |
| | | this.$message.success("导出成功"); |
| | | return true; |
| | | } catch (error) { |
| | | console.error("导出失败:", error); |
| | | this.$message.error(`导出失败: ${error.message}`); |
| | | return false; |
| | | } |
| | | }, |
| | | |
| | | // 显示图表弹窗 |
| | | |
| | | showChartDialog() { |
| | |
| | | } |
| | | |
| | | // 百分比字段特殊样式 |
| | | .your-table-container ::v-deep .el-table__footer .el-table__cell[data-field="followUpRate"] .cell, |
| | | .your-table-container ::v-deep .el-table__footer .el-table__cell[data-field="rate"] .cell, |
| | | .your-table-container ::v-deep .el-table__footer .el-table__cell[data-field="followUpRateAgain"] .cell { |
| | | .your-table-container |
| | | ::v-deep |
| | | .el-table__footer |
| | | .el-table__cell[data-field="followUpRate"] |
| | | .cell, |
| | | .your-table-container |
| | | ::v-deep |
| | | .el-table__footer |
| | | .el-table__cell[data-field="rate"] |
| | | .cell, |
| | | .your-table-container |
| | | ::v-deep |
| | | .el-table__footer |
| | | .el-table__cell[data-field="followUpRateAgain"] |
| | | .cell { |
| | | color: #e6a23c !important; |
| | | font-weight: 700 !important; |
| | | } |