| | |
| | | data: data, |
| | | }); |
| | | } |
| | | // å»¶ç»æ¤çç»è®¡ |
| | | export function getContinueNerseCount(data) { |
| | | return request({ |
| | | url: "/smartor/serviceSubtask/getContinueNerseCount", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | // 满æåº¦ç»è®¡è¯¦æ
|
| | | export function getSfStatisticsJoyInfo(data) { |
| | | return request({ |
| | |
| | | return new Promise((resolve) => { |
| | | getQtemplatelist({ pageSize: 1000 }) |
| | | .then((res) => { |
| | | if (res.code === 200) { |
| | | console.log(res.rows, "res.rows"); |
| | | if (res.code == 200) { |
| | | console.log(res.rows, 2); |
| | | this.questionnaireTemplates = (res.rows || []).map((item) => ({ |
| | | id: item.svyid, |
| | | templateName: item.svyname, |
| | | isavailable: item.isavailable, |
| | | })); |
| | | console.log(this.followupTemplates, 3); |
| | | |
| | | } else { |
| | | this.$message.error(res.msg || "å è½½é®å·æ¨¡æ¿å¤±è´¥"); |
| | | } |
| | |
| | | return new Promise((resolve) => { |
| | | getFollowuplist({ pageSize: 1000 }) |
| | | .then((res) => { |
| | | if (res.code === 200) { |
| | | console.log(res.rows, "res.rows"); |
| | | if (res.code == 200) { |
| | | console.log(res.rows, 2); |
| | | |
| | | this.followupTemplates = (res.rows || []).map((item) => ({ |
| | | id: item.id, |
| | | templateName: item.templateName, |
| | | isavailable: item.isavailable, |
| | | })); |
| | | console.log(this.followupTemplates, 3); |
| | | } else { |
| | | this.$message.error(res.msg || "å è½½è¯é³æ¨¡æ¿å¤±è´¥"); |
| | | } |
| | |
| | | /** é
ç½®åæ´å¤ç */ |
| | | handleConfigChange(question) { |
| | | this.$nextTick(() => { |
| | | const index = this.filteredQuestionList.findIndex((q) => q.id === question.id); |
| | | console.log(index,'index'); |
| | | const index = this.filteredQuestionList.findIndex( |
| | | (q) => q.id === question.id |
| | | ); |
| | | console.log(index, "index"); |
| | | |
| | | if (index !== -1) { |
| | | const formRef = this.$refs.configForm && this.$refs.configForm[index]; |
| | |
| | | </el-form> |
| | | <el-divider></el-divider> |
| | | <el-row :gutter="10" class="mb8"> |
| | | <!-- <el-col :span="1.5"> |
| | | <el-col :span="1.5"> |
| | | <div class="documentf"> |
| | | <div class="document"> |
| | | <el-button |
| | |
| | | > |
| | | </div> |
| | | </div> |
| | | </el-col> --> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button |
| | | type="primary" |
| | |
| | | { |
| | | ...this.topqueryParams, |
| | | }, |
| | | `user_${new Date().getTime()}.xlsx` |
| | | `user_${new Date().getTime()}.xlsx`, |
| | | ); |
| | | }, |
| | | // å¼å¸¸å渲æ |
| | |
| | | <div class="scriptTopic-dev" :key="index" v-else> |
| | | <div class="dev-text"> |
| | | {{ index + 1 }}ã[é®ç]<span>{{ |
| | | item.scriptContent |
| | | item.questiontext |
| | | }}</span> |
| | | <span v-if="item.valueType == 3">(åªè½è¾å
¥æ°å)</span> |
| | | </div> |
| | |
| | | methods: { |
| | | // è·å䏻颿 ·å¼ç±» |
| | | getTopicClass(item) { |
| | | console.log(item.isabnormal, "getTopicClass"); |
| | | |
| | | // æ ¹æ®ç¶æå¼è¿å对åºçæ ·å¼ç±» |
| | | if (item.isabnormal == 1) { |
| | | return "scriptTopic-isabnormal"; // å¼å¸¸ - çº¢è² |
| | |
| | | this.tableDatatop = res.data.scriptResult; |
| | | |
| | | this.tableDatatop.forEach((item) => { |
| | | if (item.scriptType == 2) item.scriptResult = []; |
| | | if (item.scriptResultId && item.scriptType != 2) { |
| | | item.isoption = 3; |
| | | item.scriptResult = item.scriptResult; |
| | | } else if (item.scriptResultId && item.scriptType == 2) { |
| | | console.log(item.scriptResult, "item.scriptResult"); |
| | | item.scriptResult = item.scriptResult.split("&"); |
| | | item.isoption = 3; |
| | | } else if (!item.scriptResultId && item.scriptType == 2) { |
| | | item.scriptResult = []; |
| | | } |
| | | }); |
| | | this.taskname = res.data.taskName; |
| | |
| | | if (item.targetvalue) { |
| | | item.scriptResult = item.targetvalue.split("&"); |
| | | } else { |
| | | item.scriptResult = []; |
| | | item.scriptResult = item.asrtext; |
| | | } |
| | | }); |
| | | |
| | |
| | | item.scriptID = item.id; |
| | | item.id = null; |
| | | // ç±»å夿èµå¼ |
| | | if (item.ivrTaskScriptTargetoptionList) { |
| | | if (item.ivrTaskScriptTargetoptionList.length) { |
| | | item.targetvalue = 1; |
| | | item.questiontext = item.scriptContent; |
| | | |
| | |
| | | } |
| | | if (item.targetvalue) { |
| | | item.scriptResult = item.targetvalue.split("&"); |
| | | } else { |
| | | item.scriptResult = []; |
| | | } |
| | | }); |
| | | } |
| | |
| | | }, |
| | | // 廿¤äººåå卿°æ® |
| | | getdetail() { |
| | | console.log(1); |
| | | let excep = ""; |
| | | const promises = []; |
| | | |
| | | // å
å¤ç tableDatatop ä¸çæ°æ® |
| | | this.tableDatatop.forEach((item) => { |
| | | if (item.valueType == 3 && item.scriptResult) { |
| | | // éªè¯æ¯å¦ä¸ºæææ°å |
| | | if (!/^\d+$/.test(item.scriptResult)) { |
| | | this.$message.error(`é®é¢ "${item.scriptContent}" å¿
é¡»è¾å
¥æ°å`); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | var objs = item.svyTaskTemplateTargetoptions.find( |
| | | (items) => items.optioncontent == item.scriptResult |
| | | ); |
| | |
| | | this.selectedTag = objs.isabnormal; |
| | | } |
| | | } |
| | | console.log(excep, "excep"); |
| | | |
| | | let obj = { |
| | | asrtext: null, |
| | | patid: this.patid, |
| | | subId: this.id, |
| | | taskid: this.taskid, |
| | | scriptid: item.id, |
| | | excep: excep, |
| | | questiontext: item.scriptContent, |
| | | categoryid: item.categoryid, |
| | | answerps: item.answerps || null, // æ·»å éå ä¿¡æ¯ |
| | | }; |
| | | if (item.scriptType == 2 && item.scriptResult[0]) { |
| | | obj.asrtext = item.scriptResult.join("&"); |
| | | obj.ivrtext = item.scriptResult.join("&"); |
| | | // å¤ç scriptResultï¼ç´æ¥ä¿®æ¹åå§æ°æ® |
| | | if (item.scriptType == 2 && item.scriptResult) { |
| | | // å¤çæ°ç»ç±»åç scriptResult |
| | | if ( |
| | | Array.isArray(item.scriptResult) && |
| | | item.scriptResult.length > 0 |
| | | ) { |
| | | item.originalScriptResult = item.scriptResult; // ä¿ååå§æ°ç»ï¼å¯éï¼ |
| | | item.scriptResult = item.scriptResult.join("&"); // 转æ¢ä¸ºå符串 |
| | | } |
| | | } else if (item.scriptType != 2 && item.scriptResult) { |
| | | obj.asrtext = item.scriptResult; |
| | | obj.ivrtext = item.scriptResult; |
| | | // ç¡®ä¿éæ°ç»ç±»åå·²ç»æ¯å符串 |
| | | if (Array.isArray(item.scriptResult)) { |
| | | item.originalScriptResult = item.scriptResult; // ä¿ååå§æ°ç»ï¼å¯éï¼ |
| | | item.scriptResult = |
| | | item.scriptResult.length > 0 ? item.scriptResult[0] : ""; |
| | | } |
| | | } |
| | | |
| | | // if (item.isoption == 3) { |
| | | // promises.push(serviceSubtaskDetailedit(obj)); |
| | | // } else { |
| | | // promises.push(serviceSubtaskDetailadd(obj)); |
| | | // } |
| | | }); |
| | | console.log(this.tableDatatop); |
| | | |
| | | // åå»ºå¯æ¬ç¨äºä¿åï¼é¿å
å½±åæ¾ç¤º |
| | | const saveData = this.tableDatatop.map((item) => ({ |
| | | ...item, |
| | | // 妿éè¦ï¼å¯ä»¥å¨è¿éåæåçæ°æ®æ¸
ç |
| | | scriptResult: item.scriptResult || "", // ç¡®ä¿ä¸ä¸º undefined |
| | | })); |
| | | |
| | | let obj = { |
| | | svyTaskTemplateScriptVOS: this.tableDatatop, // æäº¤å¤çåç坿¬ |
| | | svyTaskTemplateScriptVOS: saveData, // 使ç¨å¤çåçæ°æ® |
| | | param1: this.taskid, |
| | | param2: this.patid, |
| | | param6: this.id, |
| | |
| | | }); |
| | | } |
| | | }); |
| | | // ä½¿ç¨ Promise.all çå¾
ææå¼æ¥æä½å®æ |
| | | // Promise.all(promises) |
| | | // .then((results) => { |
| | | // // ææå¼æ¥æä½æå宿åçé»è¾ |
| | | // results.forEach((res) => { |
| | | // if (res.code !== 200) { |
| | | // this.$modal.error("ä¿®æ¹å¤±è´¥"); |
| | | // } |
| | | // }); |
| | | // this.Editsingletasksonyic(6); |
| | | // const orgName = localStorage.getItem("orgname"); |
| | | // console.log(orgName, "orgName"); |
| | | |
| | | // if (this.form.isVisitAgain != 1 || orgName == "丽水å¸ä¸å»é¢") { |
| | | // this.Torouter(); |
| | | // return; |
| | | // } |
| | | // this.$modal |
| | | // .confirm( |
| | | // 'ä»»å¡ä¿åæåæ¯å¦é对æ£è
ï¼"' + |
| | | // this.userform.name + |
| | | // '"忬¡é访ï¼', |
| | | // "确认", |
| | | // { |
| | | // confirmButtonText: "ç¡®å®", |
| | | // cancelButtonText: "åæ¶", |
| | | // showCancelButton: true, |
| | | // dangerouslyUseHTMLString: true, |
| | | // confirmButtonClass: "custom-confirm-button", // èªå®ä¹ç¡®è®¤æé®çç±»å |
| | | // cancelButtonClass: "custom-cancel-button", // èªå®ä¹åæ¶æé®çç±»å |
| | | // } |
| | | // ) |
| | | // .then(() => { |
| | | // document.querySelector("#app").scrollTo(0, 0); |
| | | // this.formtidy(); |
| | | // this.dialogFormVisible = true; |
| | | // }) |
| | | // .catch(() => { |
| | | // this.Torouter(); |
| | | // }); |
| | | // }) |
| | | // .catch((error) => { |
| | | // // 妿æä»»ä½ä¸ä¸ªå¼æ¥æä½å¤±è´¥ï¼ä¼è¿å
¥è¿é |
| | | // console.error("åçé误ï¼", error); |
| | | // }); |
| | | }, |
| | | Torouter() { |
| | | if (this.form.serviceType == 13) { |
| | |
| | | }, |
| | | yuyingetdetail() { |
| | | const dataToSubmit = JSON.parse(JSON.stringify(this.tableDatatop)); |
| | | |
| | | dataToSubmit.forEach((item, index) => { |
| | | // 对æ·è´çæ°æ®è¿è¡æä½ï¼ä¸å½±ååå§ç scriptResult æ°ç» |
| | | item.scriptResult = item.scriptResult.join("&"); |
| | | if (item.targetvalue) { |
| | | item.scriptResult = item.scriptResult.join("&"); |
| | | item.asrtext = item.matchedtext; |
| | | item.ivrtext = item.matchedtext; |
| | | } else { |
| | | item.asrtext = item.scriptResult; |
| | | item.ivrtext = item.scriptResult; |
| | | } |
| | | item.templatequestionnum = index + 1; |
| | | item.subId = this.id; |
| | | |
| | | item.taskid = this.taskid; |
| | | item.asrtext = item.matchedtext; |
| | | item.ivrtext = item.matchedtext; |
| | | if (!item.id) { |
| | | item.isoperation = 1; |
| | | } |
| | | item.patid = this.patid; |
| | | item.templateid = item.templateID; |
| | | }); |
| | | console.log("c", 3); |
| | | |
| | | let obj = { |
| | | ivrTaskTemplateScriptVOList: dataToSubmit, // æäº¤å¤çåç坿¬ |
| | |
| | | param6: this.id, |
| | | type: 1, |
| | | }; |
| | | console.log("c", 4); |
| | | const orgName = localStorage.getItem("orgname"); |
| | | console.log(orgName, "orgName"); |
| | | |
| | |
| | | }) |
| | | .catch(() => {}); |
| | | }, |
| | | aahandleOptionChange(a, b, c) { |
| | | const result = c.find((item) => item.optioncontent == a); |
| | | if (result.nextQuestion == 0) { |
| | | this.tableDatatop = this.tableDatatop.reduce((acc, item, i) => { |
| | | acc.push(i > b ? { ...item, astrict: 1 } : item); |
| | | return acc; |
| | | }, []); |
| | | } else { |
| | | this.tableDatatop = this.tableDatatop.reduce((acc, item, i) => { |
| | | acc.push(i > b ? { ...item, astrict: 0 } : item); |
| | | return acc; |
| | | }, []); |
| | | } |
| | | if (this.Voicetype) { |
| | | var obj = this.tableDatatop[b].ivrTaskScriptTargetoptionList.find( |
| | | (item) => item.optioncontent == a |
| | | ); |
| | | } else { |
| | | var obj = this.tableDatatop[b].svyTaskTemplateTargetoptions.find( |
| | | (item) => item.optioncontent == a |
| | | ); |
| | | } |
| | | if (obj.isabnormal) { |
| | | this.tableDatatop[b].isabnormal = true; |
| | | } else { |
| | | this.tableDatatop[b].isabnormal = false; |
| | | } |
| | | this.$forceUpdate(); |
| | | }, |
| | | |
| | | handleRadioToggles(questionItem, optionValue) { |
| | | if (!questionItem.matchedtext) { |
| | | questionItem.matchedtext == ""; |
| | |
| | | this.tableDatatop[questionIndex].showAppendInput = |
| | | selectedOptionObj.appendflag == 1; |
| | | console.log(this.tableDatatop); |
| | | |
| | | if ( |
| | | selectedOptionObj.nextQuestion !== undefined && |
| | | selectedOptionObj.nextQuestion !== null |
| | | ) { |
| | | this.tableDatatop[questionIndex].nextScriptno = |
| | | selectedOptionObj.nextQuestion; |
| | | } |
| | | // if (!this.tableDatatop[questionIndex].showAppendInput) { |
| | | // this.tableDatatop[questionIndex].answerps = ""; // æ¸
é¤éå ä¿¡æ¯ |
| | | // } |
| | |
| | | hiddenByEnd: index === questionIndex + 1 ? false : item.hiddenByEnd, |
| | | })); |
| | | } |
| | | 2; |
| | | |
| | | this.$forceUpdate(); |
| | | }, |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-dialog |
| | | title="é访ç»è®¡è¶å¿å¾" |
| | | :visible.sync="visible" |
| | | width="80%" |
| | | :close-on-click-modal="false" |
| | | @close="handleClose" |
| | | > |
| | | <div class="chart-container"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <div class="chart-title">éè®¿ç¶æåå¸</div> |
| | | <div id="pieChart" style="width: 100%; height: 400px"></div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="chart-title">é访è¶å¿åæ</div> |
| | | <div id="barLineChart" style="width: 100%; height: 400px"></div> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | import * as echarts from 'echarts' |
| | | |
| | | export default { |
| | | name: 'ChartDialog', |
| | | props: { |
| | | visible: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | data: { |
| | | type: Array, |
| | | default: () => [] |
| | | }, |
| | | activeTab: { |
| | | type: String, |
| | | default: 'first' |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | pieChart: null, |
| | | barLineChart: null |
| | | } |
| | | }, |
| | | watch: { |
| | | visible(newVal) { |
| | | if (newVal) { |
| | | this.$nextTick(() => { |
| | | this.initCharts() |
| | | }) |
| | | } else { |
| | | this.destroyCharts() |
| | | } |
| | | } |
| | | }, |
| | | mounted() { |
| | | if (this.visible) { |
| | | this.$nextTick(() => { |
| | | this.initCharts() |
| | | }) |
| | | } |
| | | }, |
| | | beforeDestroy() { |
| | | this.destroyCharts() |
| | | }, |
| | | methods: { |
| | | initCharts() { |
| | | this.initPieChart() |
| | | this.initBarLineChart() |
| | | }, |
| | | |
| | | initPieChart() { |
| | | const pieDom = document.getElementById('pieChart') |
| | | if (!pieDom) return |
| | | |
| | | if (this.pieChart) { |
| | | this.pieChart.dispose() |
| | | } |
| | | |
| | | this.pieChart = echarts.init(pieDom) |
| | | |
| | | // æ ¹æ®å½åtab计ç®é¥¼å¾æ°æ® |
| | | const pieData = this.getPieChartData() |
| | | |
| | | const pieOption = { |
| | | title: { |
| | | text: 'éè®¿ç¶æåå¸', |
| | | left: 'center', |
| | | textStyle: { |
| | | color: '#333', |
| | | fontSize: 16 |
| | | } |
| | | }, |
| | | tooltip: { |
| | | trigger: 'item', |
| | | formatter: '{a} <br/>{b}: {c} ({d}%)' |
| | | }, |
| | | legend: { |
| | | orient: 'vertical', |
| | | left: 'left', |
| | | data: pieData.legendData, |
| | | textStyle: { |
| | | color: '#666' |
| | | } |
| | | }, |
| | | color: ['#FF9D4D', '#36B37E', '#FF5C5C'], |
| | | series: [ |
| | | { |
| | | name: 'éè®¿ç¶æ', |
| | | type: 'pie', |
| | | radius: ['40%', '70%'], |
| | | avoidLabelOverlap: true, |
| | | itemStyle: { |
| | | borderRadius: 10, |
| | | borderColor: '#fff', |
| | | borderWidth: 2 |
| | | }, |
| | | label: { |
| | | show: true, |
| | | formatter: '{b}: {c} ({d}%)', |
| | | color: '#333' |
| | | }, |
| | | emphasis: { |
| | | label: { |
| | | show: true, |
| | | fontSize: '18', |
| | | fontWeight: 'bold' |
| | | }, |
| | | itemStyle: { |
| | | shadowBlur: 10, |
| | | shadowOffsetX: 0, |
| | | shadowColor: 'rgba(0, 0, 0, 0.5)' |
| | | } |
| | | }, |
| | | data: pieData.seriesData |
| | | } |
| | | ] |
| | | } |
| | | |
| | | this.pieChart.setOption(pieOption) |
| | | window.addEventListener('resize', this.resizePieChart) |
| | | }, |
| | | |
| | | getPieChartData() { |
| | | let legendData = [] |
| | | let seriesData = [] |
| | | |
| | | if (this.activeTab === 'first') { |
| | | legendData = ['å¾
é访', 'é访æå', 'é访失败'] |
| | | const followUpData = { |
| | | pending: 0, |
| | | success: 0, |
| | | fail: 0 |
| | | } |
| | | |
| | | this.data.forEach((item) => { |
| | | followUpData.pending += item.pendingFollowUp || 0 |
| | | followUpData.success += item.followUpSuccess || 0 |
| | | followUpData.fail += item.followUpFail || 0 |
| | | }) |
| | | |
| | | seriesData = [ |
| | | { value: followUpData.pending, name: 'å¾
é访' }, |
| | | { value: followUpData.success, name: 'é访æå' }, |
| | | { value: followUpData.fail, name: 'é访失败' } |
| | | ] |
| | | } else if (this.activeTab === 'second') { |
| | | legendData = ['å¾
é访(忬¡)', 'é访æå(忬¡)', 'é访失败(忬¡)'] |
| | | const followUpData = { |
| | | pending: 0, |
| | | success: 0, |
| | | fail: 0 |
| | | } |
| | | |
| | | this.data.forEach((item) => { |
| | | followUpData.pending += item.pendingFollowUpAgain || 0 |
| | | followUpData.success += item.followUpSuccessAgain || 0 |
| | | followUpData.fail += item.followUpFailAgain || 0 |
| | | }) |
| | | |
| | | seriesData = [ |
| | | { value: followUpData.pending, name: 'å¾
é访(忬¡)' }, |
| | | { value: followUpData.success, name: 'é访æå(忬¡)' }, |
| | | { value: followUpData.fail, name: 'é访失败(忬¡)' } |
| | | ] |
| | | } else if (this.activeTab === 'continued') { |
| | | legendData = ['æ¤ç宿', 'æ¤çè¿è¡ä¸', 'æ¤çæªå¼å§'] |
| | | const careData = { |
| | | completed: 0, |
| | | inProgress: 0, |
| | | notStarted: 0 |
| | | } |
| | | |
| | | this.data.forEach((item) => { |
| | | careData.completed += item.careCompleted || 0 |
| | | careData.inProgress += item.careInProgress || 0 |
| | | careData.notStarted += item.careNotStarted || 0 |
| | | }) |
| | | |
| | | seriesData = [ |
| | | { value: careData.completed, name: 'æ¤ç宿' }, |
| | | { value: careData.inProgress, name: 'æ¤çè¿è¡ä¸' }, |
| | | { value: careData.notStarted, name: 'æ¤çæªå¼å§' } |
| | | ] |
| | | } |
| | | |
| | | return { legendData, seriesData } |
| | | }, |
| | | |
| | | initBarLineChart() { |
| | | const barDom = document.getElementById('barLineChart') |
| | | if (!barDom) return |
| | | |
| | | if (this.barLineChart) { |
| | | this.barLineChart.dispose() |
| | | } |
| | | |
| | | this.barLineChart = echarts.init(barDom) |
| | | |
| | | // å夿°æ® |
| | | const chartData = this.getBarLineChartData() |
| | | |
| | | const option = { |
| | | title: { |
| | | text: `${chartData.title}è¶å¿`, |
| | | left: 'center', |
| | | textStyle: { |
| | | color: '#333', |
| | | fontSize: 16 |
| | | } |
| | | }, |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | | type: 'cross', |
| | | crossStyle: { |
| | | color: '#999' |
| | | } |
| | | } |
| | | }, |
| | | legend: { |
| | | data: chartData.legendData, |
| | | top: 'bottom', |
| | | textStyle: { |
| | | color: '#666' |
| | | } |
| | | }, |
| | | color: chartData.colors, |
| | | xAxis: { |
| | | type: 'category', |
| | | data: chartData.categories, |
| | | axisLabel: { |
| | | interval: 0, |
| | | rotate: 30, |
| | | color: '#666' |
| | | }, |
| | | axisLine: { |
| | | lineStyle: { |
| | | color: '#ddd' |
| | | } |
| | | } |
| | | }, |
| | | yAxis: [ |
| | | { |
| | | type: 'value', |
| | | name: chartData.yAxisName1, |
| | | min: 0, |
| | | axisLabel: { |
| | | color: '#666' |
| | | }, |
| | | axisLine: { |
| | | lineStyle: { |
| | | color: '#ddd' |
| | | } |
| | | }, |
| | | splitLine: { |
| | | lineStyle: { |
| | | color: '#f0f0f0' |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | type: 'value', |
| | | name: 'ç¾åæ¯(%)', |
| | | min: 0, |
| | | max: 100, |
| | | axisLabel: { |
| | | color: '#666', |
| | | formatter: '{value}%' |
| | | }, |
| | | axisLine: { |
| | | lineStyle: { |
| | | color: '#ddd' |
| | | } |
| | | }, |
| | | splitLine: { |
| | | show: false |
| | | } |
| | | } |
| | | ], |
| | | series: chartData.series, |
| | | grid: { |
| | | top: '15%', |
| | | left: '3%', |
| | | right: '4%', |
| | | bottom: '15%', |
| | | containLabel: true |
| | | } |
| | | } |
| | | |
| | | this.barLineChart.setOption(option) |
| | | window.addEventListener('resize', this.resizeBarLineChart) |
| | | }, |
| | | |
| | | getBarLineChartData() { |
| | | const categories = this.data.map( |
| | | (item) => item.leavehospitaldistrictname || item.deptname |
| | | ) |
| | | |
| | | let title = 'ç§å®¤/ç
åº' |
| | | let yAxisName1 = '人次' |
| | | let legendData = [] |
| | | let colors = [] |
| | | let series = [] |
| | | |
| | | if (this.activeTab === 'first') { |
| | | title = '馿¬¡é访' |
| | | yAxisName1 = '人次' |
| | | legendData = ['åºé¢äººæ¬¡', 'åºé访人次', 'é访ç(%)', 'åæ¶ç(%)'] |
| | | colors = ['#5470C6', '#91CC75', '#EE6666', '#9A60B4'] |
| | | |
| | | const dischargeData = this.data.map((item) => item.dischargeCount || 0) |
| | | const followUpData = this.data.map((item) => item.followUpNeeded || 0) |
| | | const followUpRateData = this.data.map((item) => { |
| | | if (!item.followUpRate) return 0 |
| | | const rateStr = String(item.followUpRate).replace('%', '') |
| | | return parseFloat(rateStr) || 0 |
| | | }) |
| | | const timelyRateData = this.data.map((item) => |
| | | item.rate ? (Number(item.rate) * 100).toFixed(2) : 0 |
| | | ) |
| | | |
| | | series = [ |
| | | { |
| | | name: 'åºé¢äººæ¬¡', |
| | | type: 'bar', |
| | | barWidth: '25%', |
| | | data: dischargeData, |
| | | itemStyle: { |
| | | borderRadius: [4, 4, 0, 0] |
| | | } |
| | | }, |
| | | { |
| | | name: 'åºé访人次', |
| | | type: 'bar', |
| | | barWidth: '25%', |
| | | data: followUpData, |
| | | itemStyle: { |
| | | borderRadius: [4, 4, 0, 0] |
| | | } |
| | | }, |
| | | { |
| | | name: 'é访ç(%)', |
| | | type: 'line', |
| | | yAxisIndex: 1, |
| | | data: followUpRateData, |
| | | symbolSize: 8, |
| | | lineStyle: { |
| | | width: 3 |
| | | }, |
| | | markLine: { |
| | | silent: true, |
| | | data: [ |
| | | { |
| | | yAxis: 80, |
| | | lineStyle: { |
| | | color: '#EE6666', |
| | | type: 'dashed' |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | { |
| | | name: 'åæ¶ç(%)', |
| | | type: 'line', |
| | | yAxisIndex: 1, |
| | | data: timelyRateData, |
| | | symbolSize: 8, |
| | | lineStyle: { |
| | | width: 3, |
| | | type: 'dotted' |
| | | }, |
| | | markLine: { |
| | | silent: true, |
| | | data: [ |
| | | { |
| | | yAxis: 90, |
| | | lineStyle: { |
| | | color: '#9A60B4', |
| | | type: 'dashed' |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | } |
| | | ] |
| | | } else if (this.activeTab === 'second') { |
| | | title = '忬¡é访' |
| | | yAxisName1 = '人次' |
| | | legendData = ['åºé¢äººæ¬¡', 'åºé访人次', 'é访ç(%)'] |
| | | colors = ['#5470C6', '#91CC75', '#EE6666'] |
| | | |
| | | const dischargeData = this.data.map((item) => item.dischargeCount || 0) |
| | | const followUpData = this.data.map((item) => item.followUpNeeded || 0) |
| | | const followUpRateAgainData = this.data.map((item) => { |
| | | if (!item.followUpRateAgain) return 0 |
| | | const rateStr = String(item.followUpRateAgain).replace('%', '') |
| | | return parseFloat(rateStr) || 0 |
| | | }) |
| | | |
| | | series = [ |
| | | { |
| | | name: 'åºé¢äººæ¬¡', |
| | | type: 'bar', |
| | | barWidth: '25%', |
| | | data: dischargeData, |
| | | itemStyle: { |
| | | borderRadius: [4, 4, 0, 0] |
| | | } |
| | | }, |
| | | { |
| | | name: 'åºé访人次', |
| | | type: 'bar', |
| | | barWidth: '25%', |
| | | data: followUpData, |
| | | itemStyle: { |
| | | borderRadius: [4, 4, 0, 0] |
| | | } |
| | | }, |
| | | { |
| | | name: 'é访ç(%)', |
| | | type: 'line', |
| | | yAxisIndex: 1, |
| | | data: followUpRateAgainData, |
| | | symbolSize: 8, |
| | | lineStyle: { |
| | | width: 3 |
| | | }, |
| | | markLine: { |
| | | silent: true, |
| | | data: [ |
| | | { |
| | | yAxis: 80, |
| | | lineStyle: { |
| | | color: '#EE6666', |
| | | type: 'dashed' |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | } |
| | | ] |
| | | } else if (this.activeTab === 'continued') { |
| | | title = 'å»¶ç»æ¤ç' |
| | | yAxisName1 = '人次' |
| | | legendData = ['å»¶ç»æ¤ç人次', 'æ¤ç宿', '宿ç(%)'] |
| | | colors = ['#5470C6', '#91CC75', '#EE6666'] |
| | | |
| | | const continuedCareData = this.data.map((item) => item.continuedCareCount || 0) |
| | | const careCompletedData = this.data.map((item) => item.careCompleted || 0) |
| | | const completionRateData = this.data.map((item) => { |
| | | if (!item.completionRate) return 0 |
| | | const rateStr = String(item.completionRate).replace('%', '') |
| | | return parseFloat(rateStr) || 0 |
| | | }) |
| | | |
| | | series = [ |
| | | { |
| | | name: 'å»¶ç»æ¤ç人次', |
| | | type: 'bar', |
| | | barWidth: '25%', |
| | | data: continuedCareData, |
| | | itemStyle: { |
| | | borderRadius: [4, 4, 0, 0] |
| | | } |
| | | }, |
| | | { |
| | | name: 'æ¤ç宿', |
| | | type: 'bar', |
| | | barWidth: '25%', |
| | | data: careCompletedData, |
| | | itemStyle: { |
| | | borderRadius: [4, 4, 0, 0] |
| | | } |
| | | }, |
| | | { |
| | | name: '宿ç(%)', |
| | | type: 'line', |
| | | yAxisIndex: 1, |
| | | data: completionRateData, |
| | | symbolSize: 8, |
| | | lineStyle: { |
| | | width: 3 |
| | | }, |
| | | markLine: { |
| | | silent: true, |
| | | data: [ |
| | | { |
| | | yAxis: 85, |
| | | lineStyle: { |
| | | color: '#EE6666', |
| | | type: 'dashed' |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | |
| | | return { |
| | | title, |
| | | yAxisName1, |
| | | categories, |
| | | legendData, |
| | | colors, |
| | | series |
| | | } |
| | | }, |
| | | |
| | | resizePieChart() { |
| | | if (this.pieChart) { |
| | | this.pieChart.resize() |
| | | } |
| | | }, |
| | | |
| | | resizeBarLineChart() { |
| | | if (this.barLineChart) { |
| | | this.barLineChart.resize() |
| | | } |
| | | }, |
| | | |
| | | destroyCharts() { |
| | | if (this.pieChart) { |
| | | this.pieChart.dispose() |
| | | this.pieChart = null |
| | | } |
| | | if (this.barLineChart) { |
| | | this.barLineChart.dispose() |
| | | this.barLineChart = null |
| | | } |
| | | window.removeEventListener('resize', this.resizePieChart) |
| | | window.removeEventListener('resize', this.resizeBarLineChart) |
| | | }, |
| | | |
| | | handleClose() { |
| | | this.destroyCharts() |
| | | this.$emit('close') |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .chart-container { |
| | | .chart-title { |
| | | text-align: center; |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | margin-bottom: 20px; |
| | | color: #333; |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="continued-care"> |
| | | <div class="your-table-container"> |
| | | <el-table |
| | | v-loading="loading" |
| | | :data="tableData" |
| | | :border="true" |
| | | show-summary |
| | | :summary-method="getSummaries" |
| | | > |
| | | <!-- è¡¨æ ¼åå®ä¹ --> |
| | | <el-table-column |
| | | label="åºå·" |
| | | type="index" |
| | | align="center" |
| | | width="60" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="ç
åºåç§°" |
| | | align="center" |
| | | prop="wardName" |
| | | width="200" |
| | | :show-overflow-tooltip="true" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="å·²å»¶ç»æ°é" |
| | | align="center" |
| | | prop="continuedCount" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="medium" |
| | | type="text" |
| | | @click="handleViewDetails(scope.row, 'continued', '已延ç»å表')" |
| | | > |
| | | <span class="button-zx">{{ scope.row.continuedCount }}</span> |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="æªå»¶ç»æ°é" |
| | | align="center" |
| | | prop="unContinuedCount" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="medium" |
| | | type="text" |
| | | @click="handleViewDetails(scope.row, 'uncontinued', 'æªå»¶ç»å表')" |
| | | > |
| | | <span class="button-zx">{{ scope.row.unContinuedCount }}</span> |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="å»¶ç»ç" |
| | | align="center" |
| | | prop="continuedRate" |
| | | width="120" |
| | | /> |
| | | |
| | | <!-- <el-table-column |
| | | label="æä½" |
| | | align="center" |
| | | width="150" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="small" |
| | | type="primary" |
| | | @click="handleRowClick(scope.row)" |
| | | > |
| | | æ¥çæ¤å£«è¯¦æ
|
| | | </el-button> |
| | | </template> |
| | | </el-table-column> --> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <!-- æ¤å£«è¯¦æ
å¼¹çª --> |
| | | <el-dialog |
| | | title="æ¤å£«å»¶ç»æ¤ç详æ
" |
| | | :visible.sync="nurseDialogVisible" |
| | | width="80%" |
| | | :close-on-click-modal="false" |
| | | > |
| | | <div v-if="currentWardData"> |
| | | <el-table |
| | | v-loading="nurseLoading" |
| | | :data="nurseData" |
| | | :border="true" |
| | | > |
| | | <el-table-column |
| | | label="æ¤å£«å§å" |
| | | prop="nurseName" |
| | | align="center" |
| | | width="120" |
| | | /> |
| | | <el-table-column |
| | | label="ç§å®¤" |
| | | prop="deptName" |
| | | align="center" |
| | | width="150" |
| | | /> |
| | | <el-table-column |
| | | label="å·²å»¶ç»æ°é" |
| | | prop="continuedCount" |
| | | align="center" |
| | | /> |
| | | <el-table-column |
| | | label="æªå»¶ç»æ°é" |
| | | prop="unContinuedCount" |
| | | align="center" |
| | | /> |
| | | <el-table-column |
| | | label="å»¶ç»ç" |
| | | prop="continuedRate" |
| | | align="center" |
| | | width="120" |
| | | /> |
| | | </el-table> |
| | | </div> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getContinueNerseCount, getNurseContinuedDetail } from "@/api/system/user"; |
| | | import ExcelJS from "exceljs"; |
| | | import { saveAs } from "file-saver"; |
| | | |
| | | export default { |
| | | name: "ContinuedCare", |
| | | props: { |
| | | queryParams: { |
| | | type: Object, |
| | | required: true, |
| | | }, |
| | | flatArrayhospit: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | flatArraydept: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | options: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | orgname: { |
| | | type: String, |
| | | default: "", |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | tableData: [], |
| | | loading: false, |
| | | nurseDialogVisible: false, |
| | | nurseLoading: false, |
| | | currentWardData: null, |
| | | nurseData: [], |
| | | originalData: {}, |
| | | totalData: { |
| | | continued: 0, |
| | | uncontinued: 0 |
| | | } |
| | | }; |
| | | }, |
| | | methods: { |
| | | loadData() { |
| | | this.loading = true; |
| | | |
| | | const params = { |
| | | leavehospitaldistrictcodes: |
| | | this.queryParams.leavehospitaldistrictcodes.includes("all") |
| | | ? this.getAllWardCodes() |
| | | : this.queryParams.leavehospitaldistrictcodes, |
| | | deptcodes: this.queryParams.deptcodes.includes("all") |
| | | ? this.getAllDeptCodes() |
| | | : this.queryParams.deptcodes, |
| | | |
| | | }; |
| | | |
| | | delete params.leavehospitaldistrictcodes.all; |
| | | delete params.deptcodes.all; |
| | | |
| | | getContinueNerseCount(params) |
| | | .then((response) => { |
| | | this.originalData = response.data; |
| | | this.processData(response.data); |
| | | }) |
| | | .catch((error) => { |
| | | console.error("è·åå»¶ç»æ¤çæ°æ®å¤±è´¥:", error); |
| | | this.$message.error("è·åå»¶ç»æ¤çæ°æ®å¤±è´¥"); |
| | | }) |
| | | .finally(() => { |
| | | this.loading = false; |
| | | }); |
| | | }, |
| | | |
| | | processData(data) { |
| | | this.totalData = { |
| | | continued: data.å·²å»¶ç»æ»æ°é || 0, |
| | | uncontinued: data.æªå»¶ç»æ»æ°é || 0 |
| | | }; |
| | | |
| | | const processedData = []; |
| | | |
| | | if (data.详æ
&& Array.isArray(data.详æ
)) { |
| | | data.详æ
.forEach((item) => { |
| | | // æåç
åºåç§°åæ°æ® |
| | | Object.keys(item).forEach(key => { |
| | | if (key.startsWith('已延ç»_')) { |
| | | const wardName = key.replace('已延ç»_', ''); |
| | | const continuedCount = item[key]; |
| | | const unContinuedCount = item[`æªå»¶ç»_${wardName}`] || 0; |
| | | const total = continuedCount + unContinuedCount; |
| | | const continuedRate = total > 0 ? ((continuedCount / total) * 100).toFixed(2) + '%' : '0.00%'; |
| | | |
| | | processedData.push({ |
| | | wardName, |
| | | continuedCount, |
| | | unContinuedCount, |
| | | continuedRate, |
| | | originalData: item |
| | | }); |
| | | } |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | // æåº |
| | | this.tableData = this.customSort(processedData); |
| | | }, |
| | | |
| | | getAllWardCodes() { |
| | | 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); |
| | | }, |
| | | |
| | | customSort(data) { |
| | | const order = [ |
| | | "ä¸", "äº", "ä¸", "å", "äº", "å
", "ä¸", "å
«", "ä¹", "å", |
| | | "åä¸", "åäº", "åä¸", "åå", "åäº", "åå
", "åä¸", "åå
«", "åä¹", "äºå", |
| | | "äºåä¸", "äºåäº", "äºåä¸", "äºåå", "äºåäº", "äºåå
", "äºåä¸", "äºåå
«", "äºåä¹", "ä¸å", |
| | | "ä¸åä¸", "ä¸åäº", "ä¸åä¸", "ä¸åå", "ä¸åäº", "ä¸åå
", "ä¸åä¸", "ä¸åå
«", "ä¸åä¹", "åå", |
| | | "ååä¸", "ååäº", "ååä¸", "ååå", "ååäº" |
| | | ]; |
| | | |
| | | return data.sort((a, b) => { |
| | | const getIndex = (name) => { |
| | | if (!name || typeof name !== "string") return -1; |
| | | const chineseMatch = name.match(/^(\d+)-/); |
| | | if (chineseMatch && chineseMatch[1]) { |
| | | const num = parseInt(chineseMatch[1], 10); |
| | | if (num >= 1 && num <= 45) { |
| | | return num - 1; |
| | | } |
| | | } |
| | | |
| | | // å°è¯å¹é
䏿æ°å |
| | | for (let i = 0; i < order.length; i++) { |
| | | if (name.includes(order[i])) { |
| | | return i; |
| | | } |
| | | } |
| | | return -1; |
| | | }; |
| | | |
| | | const indexA = getIndex(a.wardName); |
| | | const indexB = getIndex(b.wardName); |
| | | |
| | | if (indexA === -1 && indexB === -1) { |
| | | return (a.wardName || "").localeCompare(b.wardName || ""); |
| | | } |
| | | if (indexA === -1) return 1; |
| | | if (indexB === -1) return -1; |
| | | return indexA - indexB; |
| | | }); |
| | | }, |
| | | |
| | | getSummaries(param) { |
| | | const { columns, data } = param; |
| | | const sums = []; |
| | | |
| | | columns.forEach((column, index) => { |
| | | if (index === 0) { |
| | | sums[index] = "å计"; |
| | | return; |
| | | } |
| | | |
| | | if (index === 1) { // ç
åºåç§°å |
| | | sums[index] = "/"; |
| | | return; |
| | | } |
| | | |
| | | if (index === 2) { // å·²å»¶ç»æ°éå计 |
| | | const totalContinued = this.tableData.reduce((sum, item) => sum + item.continuedCount, 0); |
| | | sums[index] = this.formatNumber(totalContinued); |
| | | } else if (index === 3) { // æªå»¶ç»æ°éå计 |
| | | const totalUnContinued = this.tableData.reduce((sum, item) => sum + item.unContinuedCount, 0); |
| | | sums[index] = this.formatNumber(totalUnContinued); |
| | | } else if (index === 4) { // å»¶ç»çå¹³åå¼ |
| | | const totalContinued = this.tableData.reduce((sum, item) => sum + item.continuedCount, 0); |
| | | const totalUnContinued = this.tableData.reduce((sum, item) => sum + item.unContinuedCount, 0); |
| | | const total = totalContinued + totalUnContinued; |
| | | const avgRate = total > 0 ? ((totalContinued / total) * 100).toFixed(2) + '%' : '0.00%'; |
| | | sums[index] = avgRate; |
| | | } else { |
| | | sums[index] = ""; |
| | | } |
| | | }); |
| | | |
| | | return sums; |
| | | }, |
| | | |
| | | formatNumber(num) { |
| | | if (isNaN(num)) return "-"; |
| | | return Number.isInteger(num) ? num.toString() : num.toFixed(0); |
| | | }, |
| | | |
| | | handleViewDetails(row, type, titleSuffix) { |
| | | const title = `${row.wardName}${titleSuffix}`; |
| | | // è¿ééè¦æ ¹æ®ä½ çå®é
æ
åµè·å详æ
æ°æ® |
| | | // ä½ å¯ä»¥ä»row.originalDataä¸è·åï¼æè
è°ç¨æ°çAPI |
| | | const detailData = this.getMockDetailData(row, type); |
| | | this.$emit("view-details", detailData, title); |
| | | }, |
| | | |
| | | handleRowClick(row) { |
| | | this.currentWardData = row; |
| | | this.nurseDialogVisible = true; |
| | | this.loadNurseData(row.wardName); |
| | | }, |
| | | |
| | | async loadNurseData(wardName) { |
| | | this.nurseLoading = true; |
| | | try { |
| | | const params = { |
| | | wardName: wardName, |
| | | startTime: this.queryParams.startTime, |
| | | endTime: this.queryParams.endTime |
| | | }; |
| | | |
| | | const response = await getNurseContinuedDetail(params); |
| | | this.nurseData = this.processNurseData(response.data); |
| | | } catch (error) { |
| | | console.error("è·åæ¤å£«è¯¦æ
失败:", error); |
| | | this.$message.error("è·åæ¤å£«è¯¦æ
失败"); |
| | | } finally { |
| | | this.nurseLoading = false; |
| | | } |
| | | }, |
| | | |
| | | processNurseData(data) { |
| | | // æ ¹æ®ä½ çå®é
APIååºç»æå¤çæ°æ® |
| | | // è¿éæ¯ä¸ä¸ªç¤ºä¾ |
| | | return [ |
| | | { |
| | | nurseName: "æ¤å£«A", |
| | | deptName: this.currentWardData.wardName, |
| | | continuedCount: Math.floor(this.currentWardData.continuedCount * 0.3), |
| | | unContinuedCount: Math.floor(this.currentWardData.unContinuedCount * 0.3), |
| | | continuedRate: "75.00%" |
| | | }, |
| | | { |
| | | nurseName: "æ¤å£«B", |
| | | deptName: this.currentWardData.wardName, |
| | | continuedCount: Math.floor(this.currentWardData.continuedCount * 0.4), |
| | | unContinuedCount: Math.floor(this.currentWardData.unContinuedCount * 0.4), |
| | | continuedRate: "80.00%" |
| | | }, |
| | | { |
| | | nurseName: "æ¤å£«C", |
| | | deptName: this.currentWardData.wardName, |
| | | continuedCount: Math.floor(this.currentWardData.continuedCount * 0.3), |
| | | unContinuedCount: Math.floor(this.currentWardData.unContinuedCount * 0.3), |
| | | continuedRate: "70.00%" |
| | | } |
| | | ]; |
| | | }, |
| | | |
| | | getMockDetailData(row, type) { |
| | | // 模æè¯¦æ
æ°æ®ï¼å®é
åºè¯¥è°ç¨API |
| | | const detailData = []; |
| | | const count = type === 'continued' ? row.continuedCount : row.unContinuedCount; |
| | | |
| | | for (let i = 1; i <= Math.min(count, 10); i++) { |
| | | detailData.push({ |
| | | sendname: `æ£è
${i}`, |
| | | taskName: `${row.wardName}å»¶ç»æ¤ç`, |
| | | sendstate: type === 'continued' ? 6 : 2, |
| | | preachform: ["人工é访", "çµè¯é访"], |
| | | visitTime: "2024-01-15 10:00:00", |
| | | finishtime: type === 'continued' ? "2024-01-15 11:00:00" : "", |
| | | endtime: "2024-01-10 09:00:00", |
| | | nurseName: "æ¤å£«A", |
| | | drname: "å»çA", |
| | | excep: 1, |
| | | suggest: 2, |
| | | templatename: "å»¶ç»æ¤çæå¡æ¨¡æ¿", |
| | | remark: type === 'continued' ? "å·²å®æå»¶ç»æ¤ç" : "æªå¼å§å»¶ç»æ¤ç", |
| | | bankcardno: "已宿" |
| | | }); |
| | | } |
| | | |
| | | return detailData; |
| | | }, |
| | | |
| | | async exportTable() { |
| | | try { |
| | | 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]; |
| | | const formatDateForDisplay = (dateTimeStr) => { |
| | | 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 excelName = `å»¶ç»æ¤çç»è®¡è¡¨_${dateRangeString}.xlsx`; |
| | | const worksheetName = `å»¶ç»æ¤çç»è®¡_${sheetNameSuffix}`; |
| | | |
| | | if (!this.tableData || this.tableData.length === 0) { |
| | | this.$message.warning("ææ å»¶ç»æ¤çæ°æ®å¯å¯¼åº"); |
| | | return false; |
| | | } |
| | | |
| | | const workbook = new ExcelJS.Workbook(); |
| | | const worksheet = workbook.addWorksheet(worksheetName); |
| | | |
| | | this.buildExportSheet(worksheet, sheetNameSuffix); |
| | | |
| | | 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; |
| | | } |
| | | }, |
| | | |
| | | 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" } }, |
| | | }, |
| | | }; |
| | | |
| | | 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" } }, |
| | | }, |
| | | }; |
| | | |
| | | // æ·»å æ é¢è¡ |
| | | worksheet.mergeCells(1, 1, 1, 6); |
| | | const titleCell = worksheet.getCell(1, 1); |
| | | titleCell.value = `å»¶ç»æ¤çç»è®¡è¡¨_${sheetNameSuffix}`; |
| | | titleCell.style = titleStyle; |
| | | worksheet.getRow(1).height = 35; |
| | | |
| | | // 表头 |
| | | const headers = ["åºå·", "ç
åºåç§°", "å·²å»¶ç»æ°é", "æªå»¶ç»æ°é", "å»¶ç»ç", "æä½"]; |
| | | |
| | | headers.forEach((header, index) => { |
| | | const cell = worksheet.getCell(2, index + 1); |
| | | cell.value = header; |
| | | cell.style = headerStyle; |
| | | }); |
| | | |
| | | worksheet.getRow(2).height = 25; |
| | | |
| | | // æ°æ®è¡ |
| | | this.tableData.forEach((item, rowIndex) => { |
| | | const dataRow = worksheet.addRow( |
| | | [ |
| | | rowIndex + 1, |
| | | item.wardName, |
| | | item.continuedCount, |
| | | item.unContinuedCount, |
| | | item.continuedRate, |
| | | "æ¥çæ¤å£«è¯¦æ
" |
| | | ], |
| | | rowIndex + 3 |
| | | ); |
| | | |
| | | dataRow.eachCell((cell) => { |
| | | cell.style = cellStyle; |
| | | }); |
| | | dataRow.height = 24; |
| | | }); |
| | | |
| | | // åè®¡è¡ |
| | | const totalContinued = this.tableData.reduce((sum, item) => sum + item.continuedCount, 0); |
| | | const totalUnContinued = this.tableData.reduce((sum, item) => sum + item.unContinuedCount, 0); |
| | | const total = totalContinued + totalUnContinued; |
| | | const totalRate = total > 0 ? ((totalContinued / total) * 100).toFixed(2) + '%' : '0.00%'; |
| | | |
| | | const summaryRow = worksheet.addRow([ |
| | | "å计", |
| | | "/", |
| | | totalContinued, |
| | | totalUnContinued, |
| | | totalRate, |
| | | "/" |
| | | ]); |
| | | |
| | | summaryRow.eachCell((cell, colNumber) => { |
| | | cell.style = summaryStyle; |
| | | }); |
| | | summaryRow.height = 28; |
| | | |
| | | // å宽 |
| | | worksheet.columns = [ |
| | | { width: 8 }, |
| | | { width: 30 }, |
| | | { width: 15 }, |
| | | { width: 15 }, |
| | | { width: 12 }, |
| | | { width: 15 } |
| | | ]; |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .continued-care { |
| | | .your-table-container { |
| | | margin-top: 10px; |
| | | } |
| | | |
| | | .button-zx { |
| | | color: rgb(70, 204, 238); |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-dialog |
| | | :title="title" |
| | | :visible.sync="visible" |
| | | v-loading="loading" |
| | | width="70%" |
| | | :close-on-click-modal="false" |
| | | @close="handleClose" |
| | | > |
| | | <div class="detail-dialog"> |
| | | <div style="margin-bottom: 16px; display: flex; align-items: center"> |
| | | <span style="margin-right: 10px; font-weight: bold">æ£è
å§åæ¥è¯¢:</span> |
| | | <el-input |
| | | v-model="searchName" |
| | | placeholder="请è¾å
¥æ£è
å§åè¿è¡çé" |
| | | clearable |
| | | style="width: 300px" |
| | | @input="handleSearch" |
| | | @clear="handleSearch" |
| | | /> |
| | | <span style="margin-left: 10px; color: rgb(35, 81, 233); font-size: 16px"> |
| | | å
± {{ displayList.length }} æ¡è®°å½ |
| | | </span> |
| | | </div> |
| | | |
| | | <div class="examine-jic"> |
| | | <div class="jic-value"> |
| | | <el-row :gutter="20"> |
| | | <div class="data-list" ref="dataList" @scroll="handleScroll" v-loading="loading"> |
| | | <el-table :data="currentDisplayList" height="660" style="width: 100%"> |
| | | <el-table-column prop="sendname" align="center" label="å§å" width="100" /> |
| | | <el-table-column prop="taskName" align="center" width="200" show-overflow-tooltip label="ä»»å¡åç§°" /> |
| | | |
| | | <el-table-column prop="sendstate" align="center" width="200" label="ä»»å¡ç¶æ"> |
| | | <template slot-scope="scope"> |
| | | <el-tag |
| | | :type="getStateTagType(scope.row.sendstate)" |
| | | :disable-transitions="false" |
| | | > |
| | | {{ getStateText(scope.row.sendstate) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="任塿§è¡æ¹å¼" |
| | | align="center" |
| | | key="preachform" |
| | | prop="preachform" |
| | | width="160" |
| | | :show-overflow-tooltip="true" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span v-for="(item, index) in scope.row.preachform" :key="index"> |
| | | {{ item }}{{ index < scope.row.preachform.length - 1 ? 'ã' : '' }} |
| | | </span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | prop="visitTime" |
| | | align="center" |
| | | label="åºé访æ¶é´" |
| | | width="200" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | prop="finishtime" |
| | | align="center" |
| | | label="éè®¿å®ææ¶é´" |
| | | width="200" |
| | | show-overflow-tooltip |
| | | /> |
| | | <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 prop="remark" align="center" label="æå¡è®°å½" width="200" show-overflow-tooltip /> |
| | | |
| | | <el-table-column prop="bankcardno" align="center" label="å¼å«ç¶æ" width="210" /> |
| | | |
| | | <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="handleDetailsGo(scope.row)"> |
| | | <span class="button-zx"> |
| | | <i class="el-icon-s-order"></i>æ¥ç |
| | | </span> |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </el-row> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'DetailDialog', |
| | | dicts: ['sys_yujing', 'sys_suggest'], |
| | | props: { |
| | | visible: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | title: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | data: { |
| | | type: Array, |
| | | default: () => [] |
| | | }, |
| | | searchName: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | loading: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | localSearchName: '', |
| | | displayList: [], |
| | | currentDisplayList: [], |
| | | loadIndex: 0, |
| | | pageSize: 100, |
| | | isLoading: false |
| | | } |
| | | }, |
| | | watch: { |
| | | data: { |
| | | immediate: true, |
| | | handler(newData) { |
| | | this.initializeData(newData) |
| | | } |
| | | }, |
| | | searchName(newVal) { |
| | | this.localSearchName = newVal |
| | | this.handleSearch() |
| | | } |
| | | }, |
| | | mounted() { |
| | | if (this.data && this.data.length > 0) { |
| | | this.initializeData(this.data) |
| | | } |
| | | }, |
| | | methods: { |
| | | initializeData(data) { |
| | | this.displayList = [...data] |
| | | this.formatPreachformData() |
| | | this.loadIndex = 0 |
| | | this.currentDisplayList = [] |
| | | this.$nextTick(() => { |
| | | this.loadMoreData() |
| | | }) |
| | | }, |
| | | |
| | | formatPreachformData() { |
| | | this.displayList.forEach((item) => { |
| | | if (item.preachform) { |
| | | if (item.endtime) { |
| | | item.preachformson = item.preachform |
| | | const idArray = item.preachform.split(',') |
| | | |
| | | item.preachform = idArray.map((value) => { |
| | | const checkboxlist = this.$store.getters.checkboxlist |
| | | const foundItem = checkboxlist.find((item) => item.value == value) |
| | | return foundItem ? foundItem.label : null |
| | | }).filter(label => label !== null) |
| | | } |
| | | } |
| | | }) |
| | | }, |
| | | |
| | | handleSearch() { |
| | | if (!this.localSearchName.trim()) { |
| | | this.displayList = [...this.data] |
| | | this.formatPreachformData() |
| | | } else { |
| | | const keyword = this.localSearchName.toLowerCase() |
| | | this.displayList = this.data.filter((item) => { |
| | | return item.sendname && item.sendname.toLowerCase().includes(keyword) |
| | | }) |
| | | this.formatPreachformData() |
| | | } |
| | | |
| | | this.loadIndex = 0 |
| | | this.currentDisplayList = [] |
| | | this.$nextTick(() => { |
| | | this.loadMoreData() |
| | | }) |
| | | |
| | | this.$emit('search', this.localSearchName) |
| | | }, |
| | | |
| | | loadMoreData() { |
| | | if (this.isLoading || this.loadIndex >= this.displayList.length) return |
| | | |
| | | this.isLoading = true |
| | | |
| | | setTimeout(() => { |
| | | const nextChunk = this.displayList.slice( |
| | | this.loadIndex, |
| | | this.loadIndex + this.pageSize |
| | | ) |
| | | this.currentDisplayList = this.currentDisplayList.concat(nextChunk) |
| | | this.loadIndex += this.pageSize |
| | | this.isLoading = false |
| | | }, 200) |
| | | }, |
| | | |
| | | handleScroll(event) { |
| | | const scrollContainer = event.target |
| | | const isAtBottom = |
| | | scrollContainer.scrollTop + scrollContainer.clientHeight >= |
| | | scrollContainer.scrollHeight - 10 |
| | | |
| | | if ( |
| | | isAtBottom && |
| | | !this.isLoading && |
| | | this.loadIndex < this.displayList.length |
| | | ) { |
| | | this.loadMoreData() |
| | | } |
| | | }, |
| | | |
| | | getStateTagType(state) { |
| | | const stateMap = { |
| | | 1: 'primary', // 表åå·²é¢å |
| | | 2: 'primary', // å¾
é访 |
| | | 3: 'success', // 表åå·²åé |
| | | 4: 'info', // 䏿§è¡ |
| | | 5: 'danger', // åé失败 |
| | | 6: 'success' // 已宿 |
| | | } |
| | | return stateMap[state] || 'info' |
| | | }, |
| | | |
| | | getStateText(state) { |
| | | const stateTextMap = { |
| | | 1: '表åå·²é¢å', |
| | | 2: 'å¾
é访', |
| | | 3: '表åå·²åé', |
| | | 4: '䏿§è¡', |
| | | 5: 'åé失败', |
| | | 6: '已宿' |
| | | } |
| | | return stateTextMap[state] || 'æªç¥ç¶æ' |
| | | }, |
| | | |
| | | formatTime(time) { |
| | | if (!time) return '' |
| | | return this.parseTime(time) |
| | | }, |
| | | |
| | | handleDetailsGo(row) { |
| | | this.$emit('details-go', row) |
| | | }, |
| | | |
| | | handleClose() { |
| | | this.$emit('close') |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .detail-dialog { |
| | | .data-list { |
| | | max-height: 800px; |
| | | overflow-y: auto; |
| | | } |
| | | |
| | | .button-zx { |
| | | color: rgb(70, 204, 238); |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="first-follow-up"> |
| | | <div class="your-table-container"> |
| | | <el-table |
| | | ref="exportTable" |
| | | id="exportTableid" |
| | | v-loading="loading" |
| | | :data="tableData" |
| | | :border="true" |
| | | @selection-change="handleSelectionChange" |
| | | @expand-change="handleRowClick" |
| | | :row-key="getRowKey" |
| | | show-summary |
| | | :summary-method="getSummaries" |
| | | :expand-row-keys="expands" |
| | | > |
| | | <!-- å±å¼è¡ç®å¤´å --> |
| | | <el-table-column type="expand"> |
| | | <template slot-scope="props"> |
| | | <el-table |
| | | :data="props.row.doctorStats" |
| | | border |
| | | style="width: 95%; margin: 0 auto" |
| | | class="inner-table" |
| | | show-summary |
| | | :summary-method="getInnerSummaries" |
| | | > |
| | | <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" 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 align="center" label="馿¬¡åºé¢é访"> |
| | | <el-table-column label="éé访" align="center" key="needFollowUp" prop="needFollowUp" /> |
| | | <el-table-column label="å¾
é访" align="center" key="pendingFollowUp" prop="pendingFollowUp" /> |
| | | <el-table-column label="é访æå" align="center" key="followUpSuccess" prop="followUpSuccess" /> |
| | | <el-table-column label="é访失败" align="center" key="followUpFail" prop="followUpFail" /> |
| | | <el-table-column label="é访ç" align="center" width="120" key="followUpRate" prop="followUpRate" /> |
| | | <el-table-column v-if="orgname != '丽水å¸ä¸å»é¢'" label="åæ¶ç" align="center" width="120" key="rate" prop="rate"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="medium" type="text" @click="handleSeeDetails(scope.row)"> |
| | | <span class="button-zx">{{ (Number(scope.row.rate) * 100).toFixed(2) }}%</span> |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="人工" align="center" key="manual" prop="manual" /> |
| | | <el-table-column label="çä¿¡" align="center" key="sms" prop="sms" /> |
| | | <el-table-column label="微信" align="center" key="weChat" prop="weChat" /> |
| | | </el-table-column> |
| | | </el-table> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <!-- è¡¨æ ¼åå®ä¹ --> |
| | | <el-table-column |
| | | label="åºé¢ç
åº" |
| | | align="center" |
| | | sortable |
| | | key="leavehospitaldistrictname" |
| | | prop="leavehospitaldistrictname" |
| | | width="150" |
| | | :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 align="center" label="馿¬¡åºé¢é访"> |
| | | <el-table-column label="éé访" align="center" key="needFollowUp" prop="needFollowUp"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="medium" 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" key="pendingFollowUp" prop="pendingFollowUp"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="medium" 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" key="followUpSuccess" prop="followUpSuccess"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="medium" 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" key="followUpFail" prop="followUpFail"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'followUpFailInfo', 'é访失败å表')"> |
| | | <span class="button-zx">{{ scope.row.followUpFail }}</span> |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="é访ç" align="center" width="120" key="followUpRate" prop="followUpRate" /> |
| | | <el-table-column v-if="orgname != '丽水å¸ä¸å»é¢'" label="åæ¶ç" align="center" width="120" key="rate" prop="rate"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="medium" type="text" @click="handleSeeDetails(scope.row)"> |
| | | <span class="button-zx">{{ (Number(scope.row.rate) * 100).toFixed(2) }}%</span> |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="人工" align="center" key="manual" prop="manual"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'manualInfo', '人工é访å表')"> |
| | | <span class="button-zx">{{ scope.row.manual }}</span> |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="çä¿¡" align="center" key="sms" prop="sms"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'smsInfo', 'çä¿¡é访å表')"> |
| | | <span class="button-zx">{{ scope.row.sms }}</span> |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="微信" align="center" key="weChat" prop="weChat"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'weChatInfo', '微信é访å表')"> |
| | | <span class="button-zx">{{ scope.row.weChat }}</span> |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table-column> |
| | | |
| | | <!-- é访æ
åµåï¼ä»
丽水å¸ä¸å»é¢æ¾ç¤ºï¼ --> |
| | | <el-table-column v-if="orgname == '丽水å¸ä¸å»é¢'" align="center" label="é访æ
åµ"> |
| | | <el-table-column label="æ£å¸¸è¯é³" align="center" width="100" key="taskSituation1" prop="taskSituation1" /> |
| | | <el-table-column label="æ£è
ææ¥ææè®¿" align="center" width="100" key="taskSituation2" prop="taskSituation2" /> |
| | | <el-table-column label="é¢è®¿æè
æ¥è¯" align="center" width="100" key="taskSituation3" prop="taskSituation3" /> |
| | | <el-table-column label="微信é访" align="center" width="100" key="taskSituation4" prop="taskSituation4" /> |
| | | <el-table-column label="é访çµè¯ä¸æ£ç¡®" align="center" width="100" key="taskSituation5" prop="taskSituation5" /> |
| | | <el-table-column label="å
¶ä»æ
åµä¸å®é访" align="center" width="100" key="taskSituation6" prop="taskSituation6" /> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getSfStatistics, selectTimelyRate } from "@/api/system/user"; |
| | | import ExcelJS from "exceljs"; |
| | | import { saveAs } from "file-saver"; |
| | | |
| | | export default { |
| | | name: 'FirstFollowUp', |
| | | props: { |
| | | queryParams: { |
| | | type: Object, |
| | | required: true |
| | | }, |
| | | flatArrayhospit: { |
| | | type: Array, |
| | | default: () => [] |
| | | }, |
| | | flatArraydept: { |
| | | type: Array, |
| | | default: () => [] |
| | | }, |
| | | options: { |
| | | type: Array, |
| | | default: () => [] |
| | | }, |
| | | orgname: { |
| | | type: String, |
| | | default: '' |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | tableData: [], |
| | | loading: false, |
| | | expands: [], |
| | | ids: [] |
| | | } |
| | | }, |
| | | methods: { |
| | | loadData() { |
| | | this.loading = true |
| | | const params = { |
| | | ...this.queryParams, |
| | | visitCount: 1, |
| | | leavehospitaldistrictcodes: this.queryParams.leavehospitaldistrictcodes.includes("all") |
| | | ? this.getAllWardCodes() |
| | | : this.queryParams.leavehospitaldistrictcodes, |
| | | deptcodes: this.queryParams.deptcodes.includes("all") |
| | | ? this.getAllDeptCodes() |
| | | : this.queryParams.deptcodes |
| | | } |
| | | |
| | | delete params.leavehospitaldistrictcodes.all |
| | | delete params.deptcodes.all |
| | | |
| | | getSfStatistics(params) |
| | | .then(response => { |
| | | this.tableData = this.customSort(response.data) |
| | | }) |
| | | .catch(error => { |
| | | console.error("è·å馿¬¡éè®¿æ°æ®å¤±è´¥:", error) |
| | | this.$message.error("è·å馿¬¡éè®¿æ°æ®å¤±è´¥") |
| | | }) |
| | | .finally(() => { |
| | | this.loading = false |
| | | }) |
| | | }, |
| | | |
| | | getAllWardCodes() { |
| | | 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) |
| | | }, |
| | | |
| | | customSort(data) { |
| | | const order = [ |
| | | "ä¸","äº","ä¸","å","äº","å
","ä¸","å
«","ä¹","å", |
| | | "åä¸","åäº","åä¸","åå","åäº","åå
","åä¸","åå
«","åä¹","äºå", |
| | | "äºåä¸","äºåäº","äºåä¸","äºåå","äºåäº","äºåå
","äºåä¸","äºåå
«","äºåä¹","ä¸å", |
| | | "ä¸åä¸","ä¸åäº","ä¸åä¸","ä¸åå","ä¸åäº","ä¸åå
","ä¸åä¸","ä¸åå
«","ä¸åä¹","åå", |
| | | "ååä¸","ååäº","ååä¸","ååå","ååäº" |
| | | ] |
| | | |
| | | return data.sort((a, b) => { |
| | | const getIndex = (name) => { |
| | | if (!name || typeof name !== "string") return -1 |
| | | const chineseMatch = name.match(/^([ä¸äºä¸åäºå
ä¸å
«ä¹å]+)/) |
| | | if (chineseMatch && chineseMatch[1]) { |
| | | return order.indexOf(chineseMatch[1]) |
| | | } |
| | | const arabicMatch = name.match(/^(\d+)/) |
| | | if (arabicMatch && arabicMatch[1]) { |
| | | const num = parseInt(arabicMatch[1], 10) |
| | | if (num >= 1 && num <= 45) { |
| | | return num - 1 |
| | | } |
| | | } |
| | | return -1 |
| | | } |
| | | |
| | | const indexA = getIndex(a.leavehospitaldistrictname) |
| | | const indexB = getIndex(b.leavehospitaldistrictname) |
| | | |
| | | if (indexA === -1 && indexB === -1) { |
| | | return (a.leavehospitaldistrictname || "").localeCompare(b.leavehospitaldistrictname || "") |
| | | } |
| | | 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 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 |
| | | } |
| | | |
| | | 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 |
| | | } |
| | | const arabicMatch = text.match(/^(\d+)/) |
| | | if (arabicMatch && arabicMatch[1]) { |
| | | const num = parseInt(arabicMatch[1], 10) |
| | | return num >= 1 && num <= 45 ? num : -1 |
| | | } |
| | | return -1 |
| | | } |
| | | |
| | | const numA = getNumberFromText(a) |
| | | const numB = getNumberFromText(b) |
| | | |
| | | if (numA === -1 && numB === -1) { |
| | | return (a || "").localeCompare(b || "") |
| | | } |
| | | if (numA === -1) return 1 |
| | | if (numB === -1) return -1 |
| | | return numA - numB |
| | | }, |
| | | |
| | | getRowKey(row) { |
| | | return row.statisticaltype === 1 ? row.leavehospitaldistrictcode : row.deptcode |
| | | }, |
| | | |
| | | handleRowClick(row) { |
| | | if (this.expands.includes(this.getRowKey(row))) { |
| | | this.expands = [] |
| | | return |
| | | } |
| | | |
| | | const params = { |
| | | ...this.queryParams, |
| | | deptcodes: this.queryParams.deptcodes.includes("all") |
| | | ? this.getAllDeptCodes() |
| | | : this.queryParams.deptcodes, |
| | | leavehospitaldistrictcodes: [row.leavehospitaldistrictcode], |
| | | drcode: "1", |
| | | visitCount: 1 |
| | | } |
| | | |
| | | delete params.leavehospitaldistrictcodes.all |
| | | delete params.deptcodes.all |
| | | |
| | | if (!row.doctorStats) { |
| | | this.loading = true |
| | | getSfStatistics(params).then((res) => { |
| | | this.$set(row, "doctorStats", res.data) |
| | | this.expands = [this.getRowKey(row)] |
| | | this.loading = false |
| | | }) |
| | | } else { |
| | | this.expands = [this.getRowKey(row)] |
| | | } |
| | | }, |
| | | |
| | | getSummaries(param) { |
| | | const { columns, data } = param |
| | | const sums = [] |
| | | |
| | | columns.forEach((column, index) => { |
| | | if (index === 0) { |
| | | sums[index] = "å计" |
| | | return |
| | | } |
| | | if (index === 1 || index === 2) { |
| | | sums[index] = "/" |
| | | return |
| | | } |
| | | |
| | | if (column.property === "followUpRate" || column.property === "rate") { |
| | | const percentageValues = data |
| | | .map((item) => { |
| | | 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 |
| | | } else { |
| | | const numValue = parseFloat(value) |
| | | return isNaN(numValue) ? null : numValue |
| | | } |
| | | }) |
| | | .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) + "%" |
| | | } else { |
| | | 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 |
| | | }) |
| | | |
| | | if (!values.every((value) => isNaN(value))) { |
| | | sums[index] = values.reduce((prev, curr) => prev + curr, 0) |
| | | sums[index] = this.formatNumber(sums[index]) |
| | | } else { |
| | | sums[index] = "-" |
| | | } |
| | | } |
| | | }) |
| | | |
| | | return sums |
| | | }, |
| | | |
| | | getInnerSummaries(param) { |
| | | const { columns, data } = param |
| | | const sums = [] |
| | | |
| | | columns.forEach((column, index) => { |
| | | if (index === 0) { |
| | | sums[index] = "å°è®¡" |
| | | return |
| | | } |
| | | |
| | | if (column.property === "drname" || column.property === "deptname") { |
| | | sums[index] = "-" |
| | | return |
| | | } |
| | | |
| | | if (column.property === "followUpRate" || column.property === "rate") { |
| | | const percentageValues = data |
| | | .map((item) => { |
| | | 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 |
| | | } else { |
| | | const numValue = parseFloat(value) |
| | | return isNaN(numValue) ? null : numValue |
| | | } |
| | | }) |
| | | .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) + "%" |
| | | } else { |
| | | 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 |
| | | }) |
| | | |
| | | if (!values.every((value) => isNaN(value))) { |
| | | sums[index] = values.reduce((prev, curr) => prev + curr, 0) |
| | | sums[index] = this.formatNumber(sums[index]) |
| | | } else { |
| | | sums[index] = "-" |
| | | } |
| | | } |
| | | }) |
| | | |
| | | return sums |
| | | }, |
| | | |
| | | formatNumber(num) { |
| | | if (isNaN(num)) return "-" |
| | | return Number.isInteger(num) ? num.toString() : num.toFixed(0) |
| | | }, |
| | | |
| | | handleSelectionChange(selection) { |
| | | 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) |
| | | }, |
| | | |
| | | handleSeeDetails(row) { |
| | | this.$emit('see-details', row) |
| | | }, |
| | | |
| | | async exportTable() { |
| | | try { |
| | | 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] |
| | | const formatDateForDisplay = (dateTimeStr) => { |
| | | 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 excelName = `馿¬¡åºé¢é访ç»è®¡è¡¨_${dateRangeString}.xlsx` |
| | | const worksheetName = `馿¬¡é访ç»è®¡_${sheetNameSuffix}` |
| | | |
| | | if (!this.tableData || this.tableData.length === 0) { |
| | | this.$message.warning("ææ é¦æ¬¡éè®¿æ°æ®å¯å¯¼åº") |
| | | return false |
| | | } |
| | | |
| | | const workbook = new ExcelJS.Workbook() |
| | | const worksheet = workbook.addWorksheet(worksheetName) |
| | | |
| | | // æå»ºè¡¨æ ¼ |
| | | this.buildExportSheet(worksheet, sheetNameSuffix) |
| | | |
| | | 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 |
| | | } |
| | | }, |
| | | |
| | | 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" } } |
| | | } |
| | | } |
| | | |
| | | 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" } } |
| | | } |
| | | } |
| | | |
| | | // æ·»å æ é¢è¡ |
| | | worksheet.mergeCells(1, 1, 1, 16) |
| | | 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 |
| | | }) |
| | | |
| | | // åå¹¶åå
æ ¼ |
| | | for (let i = 1; i <= 6; i++) { |
| | | 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.mergeCells(2, 7, 2, 15) |
| | | worksheet.getCell(2, 7).value = "馿¬¡åºé¢é访" |
| | | worksheet.getCell(2, 7).style = headerStyle |
| | | |
| | | 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.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 |
| | | ], rowIndex + 4) |
| | | |
| | | dataRow.eachCell((cell) => { |
| | | cell.style = cellStyle |
| | | }) |
| | | dataRow.height = 24 |
| | | }) |
| | | |
| | | // åè®¡è¡ |
| | | const summaries = this.getExportSummaries() |
| | | 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 } |
| | | ] |
| | | }, |
| | | |
| | | getExportSummaries() { |
| | | const summaries = ["å计", "/", "/", 0, 0, 0, 0, 0, 0, 0, "0%", "0%", 0, 0, 0] |
| | | |
| | | 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.needFollowUp) || 0 |
| | | summaries[7] += Number(item.pendingFollowUp) || 0 |
| | | summaries[8] += Number(item.followUpSuccess) || 0 |
| | | summaries[9] += Number(item.followUpFail) || 0 |
| | | summaries[12] += Number(item.manual) || 0 |
| | | summaries[13] += Number(item.sms) || 0 |
| | | summaries[14] += Number(item.weChat) || 0 |
| | | }) |
| | | |
| | | const followUpRateValues = this.tableData |
| | | .map((item) => this.extractPercentageValue(item.followUpRate)) |
| | | .filter((value) => value !== null) |
| | | |
| | | const rateValues = this.tableData |
| | | .map((item) => this.extractPercentageValue(item.rate)) |
| | | .filter((value) => value !== null) |
| | | |
| | | if (followUpRateValues.length > 0) { |
| | | const avgFollowUpRate = followUpRateValues.reduce((sum, val) => sum + val, 0) / followUpRateValues.length |
| | | summaries[10] = (avgFollowUpRate * 100).toFixed(2) + "%" |
| | | } |
| | | |
| | | if (rateValues.length > 0) { |
| | | const avgRate = rateValues.reduce((sum, val) => sum + val, 0) / rateValues.length |
| | | summaries[11] = (avgRate * 100).toFixed(2) + "%" |
| | | } |
| | | |
| | | 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[12] = this.formatNumber(summaries[12]) |
| | | summaries[13] = this.formatNumber(summaries[13]) |
| | | summaries[14] = this.formatNumber(summaries[14]) |
| | | |
| | | return summaries |
| | | }, |
| | | |
| | | extractPercentageValue(value) { |
| | | 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) |
| | | return isNaN(num) ? null : num |
| | | }, |
| | | |
| | | selectTimelyRate(row, dateRange) { |
| | | const params = { |
| | | ...this.patientqueryParams, |
| | | starttime: this.parseTime(dateRange[0]), |
| | | endtime: this.parseTime(dateRange[1]), |
| | | deptcode: row.deptcode |
| | | } |
| | | return selectTimelyRate(params) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .first-follow-up { |
| | | .your-table-container { |
| | | margin-top: 10px; |
| | | } |
| | | |
| | | .button-zx { |
| | | color: rgb(70, 204, 238); |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="second-follow-up"> |
| | | <div class="your-table-container"> |
| | | <el-table |
| | | ref="exportTableSecond" |
| | | id="exportTableidSecond" |
| | | v-loading="loading" |
| | | :data="tableData" |
| | | :border="true" |
| | | @selection-change="handleSelectionChange" |
| | | @expand-change="handleRowClick" |
| | | :row-key="getRowKey" |
| | | show-summary |
| | | :summary-method="getSummaries" |
| | | :expand-row-keys="expands" |
| | | > |
| | | <!-- å±å¼è¡ç®å¤´å --> |
| | | <el-table-column type="expand"> |
| | | <template slot-scope="props"> |
| | | <el-table |
| | | :data="props.row.doctorStats" |
| | | border |
| | | style="width: 95%; margin: 0 auto" |
| | | class="inner-table" |
| | | show-summary |
| | | :summary-method="getInnerSummaries" |
| | | > |
| | | <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 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 label="人工" align="center" key="manualAgain" prop="manualAgain" /> |
| | | <el-table-column label="çä¿¡" align="center" key="smsAgain" prop="smsAgain" /> |
| | | <el-table-column label="微信" align="center" key="weChatAgain" prop="weChatAgain" /> |
| | | </el-table-column> |
| | | </el-table> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <!-- è¡¨æ ¼åå®ä¹ --> |
| | | <el-table-column |
| | | label="åºé¢ç
åº" |
| | | align="center" |
| | | sortable |
| | | key="leavehospitaldistrictname" |
| | | prop="leavehospitaldistrictname" |
| | | width="150" |
| | | :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 align="center" label="忬¡åºé¢é访"> |
| | | <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', '忬¡é访éé访å表')"> |
| | | <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', '忬¡é访å¾
é访å表')"> |
| | | <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', '忬¡é访é访æåå表')"> |
| | | <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', '忬¡é访é访失败å表')"> |
| | | <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 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 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 label="微信" align="center" key="weChatAgain" prop="weChatAgain"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'weChatAgainInfo', '忬¡é访微信é访å表')"> |
| | | <span class="button-zx">{{ scope.row.weChatAgain }}</span> |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getSfStatistics } from "@/api/system/user"; |
| | | import ExcelJS from "exceljs"; |
| | | import { saveAs } from "file-saver"; |
| | | |
| | | export default { |
| | | name: 'SecondFollowUp', |
| | | props: { |
| | | queryParams: { |
| | | type: Object, |
| | | required: true |
| | | }, |
| | | flatArrayhospit: { |
| | | type: Array, |
| | | default: () => [] |
| | | }, |
| | | flatArraydept: { |
| | | type: Array, |
| | | default: () => [] |
| | | }, |
| | | options: { |
| | | type: Array, |
| | | default: () => [] |
| | | }, |
| | | orgname: { |
| | | type: String, |
| | | default: '' |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | tableData: [], |
| | | loading: false, |
| | | expands: [], |
| | | ids: [] |
| | | } |
| | | }, |
| | | methods: { |
| | | loadData() { |
| | | this.loading = true |
| | | const params = { |
| | | ...this.queryParams, |
| | | visitCount: 2, |
| | | leavehospitaldistrictcodes: this.queryParams.leavehospitaldistrictcodes.includes("all") |
| | | ? this.getAllWardCodes() |
| | | : this.queryParams.leavehospitaldistrictcodes, |
| | | deptcodes: this.queryParams.deptcodes.includes("all") |
| | | ? this.getAllDeptCodes() |
| | | : this.queryParams.deptcodes |
| | | } |
| | | |
| | | delete params.leavehospitaldistrictcodes.all |
| | | delete params.deptcodes.all |
| | | |
| | | getSfStatistics(params) |
| | | .then(response => { |
| | | this.tableData = this.customSort(response.data) |
| | | }) |
| | | .catch(error => { |
| | | console.error("è·å忬¡éè®¿æ°æ®å¤±è´¥:", error) |
| | | this.$message.error("è·å忬¡éè®¿æ°æ®å¤±è´¥") |
| | | }) |
| | | .finally(() => { |
| | | this.loading = false |
| | | }) |
| | | }, |
| | | |
| | | getAllWardCodes() { |
| | | 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) |
| | | }, |
| | | |
| | | customSort(data) { |
| | | const order = [ |
| | | "ä¸","äº","ä¸","å","äº","å
","ä¸","å
«","ä¹","å", |
| | | "åä¸","åäº","åä¸","åå","åäº","åå
","åä¸","åå
«","åä¹","äºå", |
| | | "äºåä¸","äºåäº","äºåä¸","äºåå","äºåäº","äºåå
","äºåä¸","äºåå
«","äºåä¹","ä¸å", |
| | | "ä¸åä¸","ä¸åäº","ä¸åä¸","ä¸åå","ä¸åäº","ä¸åå
","ä¸åä¸","ä¸åå
«","ä¸åä¹","åå", |
| | | "ååä¸","ååäº","ååä¸","ååå","ååäº" |
| | | ] |
| | | |
| | | return data.sort((a, b) => { |
| | | const getIndex = (name) => { |
| | | if (!name || typeof name !== "string") return -1 |
| | | const chineseMatch = name.match(/^([ä¸äºä¸åäºå
ä¸å
«ä¹å]+)/) |
| | | if (chineseMatch && chineseMatch[1]) { |
| | | return order.indexOf(chineseMatch[1]) |
| | | } |
| | | const arabicMatch = name.match(/^(\d+)/) |
| | | if (arabicMatch && arabicMatch[1]) { |
| | | const num = parseInt(arabicMatch[1], 10) |
| | | if (num >= 1 && num <= 45) { |
| | | return num - 1 |
| | | } |
| | | } |
| | | return -1 |
| | | } |
| | | |
| | | const indexA = getIndex(a.leavehospitaldistrictname) |
| | | const indexB = getIndex(b.leavehospitaldistrictname) |
| | | |
| | | if (indexA === -1 && indexB === -1) { |
| | | return (a.leavehospitaldistrictname || "").localeCompare(b.leavehospitaldistrictname || "") |
| | | } |
| | | 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 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 |
| | | } |
| | | |
| | | 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 |
| | | } |
| | | const arabicMatch = text.match(/^(\d+)/) |
| | | if (arabicMatch && arabicMatch[1]) { |
| | | const num = parseInt(arabicMatch[1], 10) |
| | | return num >= 1 && num <= 45 ? num : -1 |
| | | } |
| | | return -1 |
| | | } |
| | | |
| | | const numA = getNumberFromText(a) |
| | | const numB = getNumberFromText(b) |
| | | |
| | | if (numA === -1 && numB === -1) { |
| | | return (a || "").localeCompare(b || "") |
| | | } |
| | | if (numA === -1) return 1 |
| | | if (numB === -1) return -1 |
| | | return numA - numB |
| | | }, |
| | | |
| | | getRowKey(row) { |
| | | return row.statisticaltype === 1 ? row.leavehospitaldistrictcode : row.deptcode |
| | | }, |
| | | |
| | | handleRowClick(row) { |
| | | if (this.expands.includes(this.getRowKey(row))) { |
| | | this.expands = [] |
| | | return |
| | | } |
| | | |
| | | const params = { |
| | | ...this.queryParams, |
| | | deptcodes: this.queryParams.deptcodes.includes("all") |
| | | ? this.getAllDeptCodes() |
| | | : this.queryParams.deptcodes, |
| | | leavehospitaldistrictcodes: [row.leavehospitaldistrictcode], |
| | | drcode: "1", |
| | | visitCount: 2 |
| | | } |
| | | |
| | | delete params.leavehospitaldistrictcodes.all |
| | | delete params.deptcodes.all |
| | | |
| | | if (!row.doctorStats) { |
| | | this.loading = true |
| | | getSfStatistics(params).then((res) => { |
| | | this.$set(row, "doctorStats", res.data) |
| | | this.expands = [this.getRowKey(row)] |
| | | this.loading = false |
| | | }) |
| | | } else { |
| | | this.expands = [this.getRowKey(row)] |
| | | } |
| | | }, |
| | | |
| | | getSummaries(param) { |
| | | const { columns, data } = param |
| | | const sums = [] |
| | | |
| | | columns.forEach((column, index) => { |
| | | if (index === 0) { |
| | | sums[index] = "å计" |
| | | return |
| | | } |
| | | if (index === 1 || index === 2) { |
| | | sums[index] = "/" |
| | | return |
| | | } |
| | | |
| | | if (column.property === "followUpRateAgain") { |
| | | const percentageValues = data |
| | | .map((item) => { |
| | | 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 |
| | | } else { |
| | | const numValue = parseFloat(value) |
| | | return isNaN(numValue) ? null : numValue |
| | | } |
| | | }) |
| | | .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) + "%" |
| | | } else { |
| | | 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 |
| | | }) |
| | | |
| | | if (!values.every((value) => isNaN(value))) { |
| | | sums[index] = values.reduce((prev, curr) => prev + curr, 0) |
| | | sums[index] = this.formatNumber(sums[index]) |
| | | } else { |
| | | sums[index] = "-" |
| | | } |
| | | } |
| | | }) |
| | | |
| | | return sums |
| | | }, |
| | | |
| | | getInnerSummaries(param) { |
| | | const { columns, data } = param |
| | | const sums = [] |
| | | |
| | | columns.forEach((column, index) => { |
| | | if (index === 0) { |
| | | sums[index] = "å°è®¡" |
| | | return |
| | | } |
| | | |
| | | if (column.property === "drname" || column.property === "deptname") { |
| | | sums[index] = "-" |
| | | return |
| | | } |
| | | |
| | | if (column.property === "followUpRateAgain") { |
| | | const percentageValues = data |
| | | .map((item) => { |
| | | 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 |
| | | } else { |
| | | const numValue = parseFloat(value) |
| | | return isNaN(numValue) ? null : numValue |
| | | } |
| | | }) |
| | | .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) + "%" |
| | | } else { |
| | | 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 |
| | | }) |
| | | |
| | | if (!values.every((value) => isNaN(value))) { |
| | | sums[index] = values.reduce((prev, curr) => prev + curr, 0) |
| | | sums[index] = this.formatNumber(sums[index]) |
| | | } else { |
| | | sums[index] = "-" |
| | | } |
| | | } |
| | | }) |
| | | |
| | | return sums |
| | | }, |
| | | |
| | | formatNumber(num) { |
| | | if (isNaN(num)) return "-" |
| | | return Number.isInteger(num) ? num.toString() : num.toFixed(0) |
| | | }, |
| | | |
| | | handleSelectionChange(selection) { |
| | | 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) |
| | | }, |
| | | |
| | | async exportTable() { |
| | | try { |
| | | 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] |
| | | const formatDateForDisplay = (dateTimeStr) => { |
| | | 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 excelName = `忬¡åºé¢é访ç»è®¡è¡¨_${dateRangeString}.xlsx` |
| | | const worksheetName = `忬¡é访ç»è®¡_${sheetNameSuffix}` |
| | | |
| | | if (!this.tableData || this.tableData.length === 0) { |
| | | this.$message.warning("ææ åæ¬¡éè®¿æ°æ®å¯å¯¼åº") |
| | | return false |
| | | } |
| | | |
| | | const workbook = new ExcelJS.Workbook() |
| | | const worksheet = workbook.addWorksheet(worksheetName) |
| | | |
| | | // æå»ºè¡¨æ ¼ |
| | | this.buildExportSheet(worksheet, sheetNameSuffix) |
| | | |
| | | 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 |
| | | } |
| | | }, |
| | | |
| | | 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" } } |
| | | } |
| | | } |
| | | |
| | | 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" } } |
| | | } |
| | | } |
| | | |
| | | // æ·»å æ é¢è¡ |
| | | 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 |
| | | }) |
| | | |
| | | // åå¹¶åå
æ ¼ |
| | | for (let i = 1; i <= 6; i++) { |
| | | 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.mergeCells(2, 7, 2, 14) |
| | | worksheet.getCell(2, 7).value = "忬¡åºé¢é访" |
| | | worksheet.getCell(2, 7).style = headerStyle |
| | | |
| | | 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) |
| | | |
| | | dataRow.eachCell((cell) => { |
| | | cell.style = cellStyle |
| | | }) |
| | | dataRow.height = 24 |
| | | }) |
| | | |
| | | // åè®¡è¡ |
| | | const summaries = this.getExportSummaries() |
| | | 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: 8 }, { width: 8 }, { width: 8 } |
| | | ] |
| | | }, |
| | | |
| | | getExportSummaries() { |
| | | const summaries = ["å计", "/", "/", 0, 0, 0, 0, 0, 0, 0, "0%", 0, 0, 0] |
| | | |
| | | 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 |
| | | }) |
| | | |
| | | const followUpRateAgainValues = this.tableData |
| | | .map((item) => this.extractPercentageValue(item.followUpRateAgain)) |
| | | .filter((value) => value !== null) |
| | | |
| | | if (followUpRateAgainValues.length > 0) { |
| | | const avgFollowUpRateAgain = followUpRateAgainValues.reduce((sum, val) => sum + val, 0) / followUpRateAgainValues.length |
| | | summaries[10] = (avgFollowUpRateAgain * 100).toFixed(2) + "%" |
| | | } |
| | | |
| | | 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]) |
| | | |
| | | return summaries |
| | | }, |
| | | |
| | | extractPercentageValue(value) { |
| | | 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) |
| | | return isNaN(num) ? null : num |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .second-follow-up { |
| | | .your-table-container { |
| | | margin-top: 10px; |
| | | } |
| | | |
| | | .button-zx { |
| | | color: rgb(70, 204, 238); |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-dialog |
| | | title="æªåæ¶é访æ£è
æå¡" |
| | | :visible.sync="visible" |
| | | v-loading="loading" |
| | | width="70%" |
| | | :close-on-click-modal="false" |
| | | @close="handleClose" |
| | | > |
| | | <div class="timely-rate-dialog"> |
| | | <div class="examine-jic"> |
| | | <div class="jic-value"> |
| | | <el-row :gutter="20"> |
| | | <!-- æç´¢è¡¨å --> |
| | | <el-form |
| | | :model="queryParams" |
| | | ref="queryForm" |
| | | size="small" |
| | | :inline="true" |
| | | label-width="98px" |
| | | class="search-form" |
| | | > |
| | | <el-form-item label="æ£è
ï¼"> |
| | | <el-input |
| | | v-model="queryParams.name" |
| | | placeholder="请è¾å
¥æ£è
å§å" |
| | | @keyup.enter.native="handleSearch" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="æ£è
è¯æï¼"> |
| | | <el-input |
| | | v-model="queryParams.leavediagname" |
| | | placeholder="请è¾å
¥æ£è
è¯æ" |
| | | @keyup.enter.native="handleSearch" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | | icon="el-icon-search" |
| | | size="medium" |
| | | @click="handleSearch" |
| | | > |
| | | æç´¢ |
| | | </el-button> |
| | | <el-button |
| | | icon="el-icon-refresh" |
| | | size="medium" |
| | | @click="resetQuery" |
| | | > |
| | | éç½® |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <!-- æ£è
å表 --> |
| | | <el-table :data="data" style="width: 100%" v-loading="loading"> |
| | | <el-table-column prop="sendname" align="center" label="å§å" width="100" /> |
| | | <el-table-column prop="taskName" align="center" width="200" show-overflow-tooltip label="ä»»å¡åç§°" /> |
| | | |
| | | <el-table-column prop="sendstate" align="center" width="200" label="ä»»å¡ç¶æ"> |
| | | <template slot-scope="scope"> |
| | | <el-tag |
| | | :type="getStateTagType(scope.row.sendstate)" |
| | | :disable-transitions="false" |
| | | > |
| | | {{ getStateText(scope.row.sendstate) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column prop="visitTime" align="center" label="åºé访æ¶é´" width="200" show-overflow-tooltip /> |
| | | <el-table-column prop="finishtime" align="center" label="éè®¿å®ææ¶é´" width="200" show-overflow-tooltip /> |
| | | |
| | | <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 prop="remark" align="center" label="æå¡è®°å½" width="200" show-overflow-tooltip /> |
| | | |
| | | <el-table-column prop="bankcardno" align="center" label="å¼å«ç¶æ" width="210" /> |
| | | |
| | | <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="handleDetailsGo(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="total > 0" |
| | | :total="total" |
| | | :page.sync="queryParams.pn" |
| | | :limit.sync="queryParams.ps" |
| | | @pagination="handlePagination" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | import Pagination from '@/components/Pagination' |
| | | |
| | | export default { |
| | | name: 'TimelyRateDialog', |
| | | components: { |
| | | Pagination |
| | | }, |
| | | dicts: ['sys_yujing', 'sys_suggest'], |
| | | props: { |
| | | visible: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | loading: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | data: { |
| | | type: Array, |
| | | default: () => [] |
| | | }, |
| | | total: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | queryParams: { |
| | | type: Object, |
| | | default: () => ({ |
| | | pn: 1, |
| | | ps: 10 |
| | | }) |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | localQueryParams: { ...this.queryParams } |
| | | } |
| | | }, |
| | | watch: { |
| | | queryParams: { |
| | | deep: true, |
| | | handler(newParams) { |
| | | this.localQueryParams = { ...newParams } |
| | | } |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.localQueryParams = { ...this.queryParams } |
| | | }, |
| | | methods: { |
| | | handleSearch() { |
| | | this.$emit('search', this.localQueryParams) |
| | | }, |
| | | |
| | | resetQuery() { |
| | | this.localQueryParams = { |
| | | pn: 1, |
| | | ps: 10, |
| | | name: '', |
| | | leavediagname: '' |
| | | } |
| | | this.$emit('search', this.localQueryParams) |
| | | }, |
| | | |
| | | handlePagination(pagination) { |
| | | this.localQueryParams.pn = pagination.page |
| | | this.localQueryParams.ps = pagination.limit |
| | | this.$emit('search', this.localQueryParams) |
| | | }, |
| | | |
| | | getStateTagType(state) { |
| | | const stateMap = { |
| | | 1: 'primary', |
| | | 2: 'primary', |
| | | 3: 'success', |
| | | 4: 'info', |
| | | 5: 'danger', |
| | | 6: 'success' |
| | | } |
| | | return stateMap[state] || 'info' |
| | | }, |
| | | |
| | | getStateText(state) { |
| | | const stateTextMap = { |
| | | 1: '表åå·²é¢å', |
| | | 2: 'å¾
é访', |
| | | 3: '表åå·²åé', |
| | | 4: '䏿§è¡', |
| | | 5: 'åé失败', |
| | | 6: '已宿' |
| | | } |
| | | return stateTextMap[state] || 'æªç¥ç¶æ' |
| | | }, |
| | | |
| | | formatTime(time) { |
| | | if (!time) return '' |
| | | return this.parseTime(time) |
| | | }, |
| | | |
| | | handleDetailsGo(row) { |
| | | this.$emit('details-go', row) |
| | | }, |
| | | |
| | | handleClose() { |
| | | this.$emit('close') |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .timely-rate-dialog { |
| | | .search-form { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .button-zx { |
| | | color: rgb(70, 204, 238); |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // å
¨å±æ ·å¼ |
| | | .follow-up-statistics, |
| | | .first-follow-up, |
| | | .second-follow-up, |
| | | .continued-care { |
| | | .your-table-container { |
| | | margin-top: 10px; |
| | | } |
| | | |
| | | .button-zx { |
| | | color: rgb(70, 204, 238); |
| | | } |
| | | |
| | | // ç¾ååè®¡è¡æ ·å¼ |
| | | ::v-deep .el-table__footer { |
| | | .el-table__cell { |
| | | background-color: #f5f7fa; |
| | | font-weight: 600; |
| | | color: #409eff; |
| | | |
| | | .cell { |
| | | font-weight: 600; |
| | | color: #409eff; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // å
é¨è¡¨æ ¼åè®¡è¡æ ·å¼ |
| | | ::v-deep .inner-table .el-table__footer { |
| | | .el-table__cell { |
| | | background-color: #ecf5ff; |
| | | font-weight: 500; |
| | | color: #67c23a; |
| | | |
| | | .cell { |
| | | font-weight: 500; |
| | | color: #67c23a; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // ç¾åæ¯åæ®µç¹æ®æ ·å¼ |
| | | ::v-deep .el-table__footer .el-table__cell[data-field="followUpRate"] .cell, |
| | | ::v-deep .el-table__footer .el-table__cell[data-field="rate"] .cell, |
| | | ::v-deep .el-table__footer .el-table__cell[data-field="followUpRateAgain"] .cell, |
| | | ::v-deep .el-table__footer .el-table__cell[data-field="completionRate"] .cell { |
| | | color: #e6a23c !important; |
| | | font-weight: 700 !important; |
| | | } |
| | | |
| | | // å
å±å»çè¡¨æ ¼æ ·å¼ |
| | | .inner-table { |
| | | ::v-deep .el-table__header-wrapper { |
| | | background-color: #f0f7ff !important; |
| | | |
| | | th { |
| | | background-color: #f0f7ff !important; |
| | | } |
| | | } |
| | | |
| | | ::v-deep .el-table__body-wrapper { |
| | | tr { |
| | | background-color: #f9fbfe !important; |
| | | |
| | | &:hover { |
| | | background-color: #e6f1ff !important; |
| | | } |
| | | } |
| | | } |
| | | |
| | | ::v-deep .el-table--border { |
| | | border-color: #d9e8ff !important; |
| | | |
| | | td, th { |
| | | border-color: #d9e8ff !important; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* ä½¿è¡ææåæé */ |
| | | ::v-deep .el-table__row { |
| | | cursor: pointer; |
| | | } |
| | | |
| | | /* å±å¼è¡æ ·å¼ */ |
| | | ::v-deep .el-table__expanded-cell { |
| | | padding: 10px 0 !important; |
| | | background: #f8f8f8; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="Questionnairemanagement"> |
| | | <div class="leftvlue"> |
| | | <div class="leftvlue-bg"> |
| | | <el-row :gutter="20"> |
| | | <!--æ ç¾æ°æ®--> |
| | | <el-col :span="24" :xs="24"> |
| | | <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" |
| | | label-width="98px"> |
| | | <el-form-item label="ç»è®¡ç±»å" prop="userName"> |
| | | <el-select v-model="queryParams.statisticaltype" placeholder="è¯·éæ©ç»è®¡ç±»å"> |
| | | <el-option v-for="item in Statisticallist" :key="item.value" :label="item.label" :value="item.value"> |
| | | </el-option> |
| | | </el-select> |
| | | <el-select style="margin-left: 10px" v-if="queryParams.statisticaltype == 1" |
| | | v-model="queryParams.leavehospitaldistrictcodes" size="medium" multiple filterable |
| | | placeholder="è¯·éæ©ç
åº"> |
| | | <el-option v-for="item in flatArrayhospit" :key="item.value" :label="item.label" :value="item.value"> |
| | | </el-option> |
| | | </el-select> |
| | | <el-select v-else-if="queryParams.statisticaltype == 2" v-model="queryParams.deptcodes" size="medium" |
| | | multiple filterable placeholder="è¯·éæ©ç§å®¤"> |
| | | <el-option v-for="item in flatArraydept" :key="item.value" :label="item.label" :value="item.value"> |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="æå¡ç±»å" prop="userName"> |
| | | <el-select v-model="queryParams.serviceType" multiple placeholder="è¯·éæ©"> |
| | | <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label-width="200" label="åºé访æ¶é´èå´" prop="userName"> |
| | | <el-date-picker v-model="queryParams.dateRange" 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> |
| | | |
| | | <el-form-item> |
| | | <el-button type="primary" icon="el-icon-search" size="medium" @click="handleQuery">æç´¢</el-button> |
| | | <el-button icon="el-icon-refresh" size="medium" @click="resetQuery">éç½®</el-button> |
| | | </el-form-item> |
| | | <el-button type="warning" plain icon="el-icon-download" size="medium" @click="exportTable">导åº</el-button> |
| | | <el-button type="primary" plain icon="el-icon-data-line" size="medium" |
| | | @click="showChartDialog">ç»è®¡è¶å¿å¾</el-button> |
| | | </el-form> |
| | | |
| | | <!-- æ°å¢ï¼Tabæ ç¾é¡µ --> |
| | | <el-tabs v-model="activeTab" @tab-click="handleTabClick"> |
| | | <el-tab-pane label="馿¬¡é访" name="first"> |
| | | <div class="your-table-container"> |
| | | <el-table ref="exportTable" id="exportTableid" v-loading="loading" :data="firstFollowUpList" |
| | | :border="true" @selection-change="handleSelectionChange" @expand-change="handleRowClick" |
| | | :row-key="getRowKey" show-summary :summary-method="getSummaries" :expand-row-keys="expands"> |
| | | <!-- å±å¼è¡ç®å¤´å --> |
| | | <el-table-column type="expand"> |
| | | <template slot-scope="props"> |
| | | <el-table :data="props.row.doctorStats" border style="width: 95%; margin: 0 auto" |
| | | class="inner-table" show-summary :summary-method="getInnerSummaries"> |
| | | <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" key="dischargeCount" prop="dischargeCount"> |
| | | </el-table-column> |
| | | |
| | | <el-table-column label="æ éé访人次" align="center" width="100" key="nonFollowUp" |
| | | prop="nonFollowUp"> |
| | | </el-table-column> |
| | | <el-table-column label="åºé访人次" align="center" width="100" key="followUpNeeded" |
| | | prop="followUpNeeded"> |
| | | </el-table-column> |
| | | <el-table-column align="center" label="馿¬¡åºé¢é访"> |
| | | <el-table-column label="éé访" align="center" key="needFollowUp" prop="needFollowUp"> |
| | | </el-table-column> |
| | | <el-table-column label="å¾
é访" align="center" key="pendingFollowUp" prop="pendingFollowUp"> |
| | | </el-table-column> |
| | | <el-table-column label="é访æå" align="center" key="followUpSuccess" prop="followUpSuccess"> |
| | | </el-table-column> |
| | | <el-table-column label="é访失败" align="center" key="followUpFail" prop="followUpFail"> |
| | | </el-table-column> |
| | | <el-table-column label="é访ç" align="center" width="120" key="followUpRate" |
| | | prop="followUpRate"> |
| | | </el-table-column> |
| | | <el-table-column v-if="orgname != '丽水å¸ä¸å»é¢'" label="åæ¶ç" align="center" width="120" |
| | | key="rate" prop="rate"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="medium" type="text" @click="Seedetails(scope.row)"><span |
| | | class="button-zx">{{ |
| | | (Number(scope.row.rate) * 100).toFixed(2) |
| | | }}%</span></el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="人工" align="center" key="manual" prop="manual"> |
| | | </el-table-column> |
| | | <el-table-column label="çä¿¡" align="center" key="sms" prop="sms"> |
| | | </el-table-column> |
| | | <el-table-column label="微信" align="center" key="weChat" prop="weChat"> |
| | | </el-table-column> |
| | | </el-table-column> |
| | | </el-table> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="åºé¢ç
åº" align="center" sortable key="leavehospitaldistrictname" |
| | | prop="leavehospitaldistrictname" width="150" :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> |
| | | |
| | | <el-table-column label="æ éé访人次" align="center" width="100" key="nonFollowUp" prop="nonFollowUp"> |
| | | </el-table-column> |
| | | <el-table-column label="åºé访人次" align="center" width="100" key="followUpNeeded" |
| | | prop="followUpNeeded"> |
| | | </el-table-column> |
| | | <el-table-column align="center" label="馿¬¡åºé¢é访"> |
| | | <el-table-column label="éé访" align="center" key="needFollowUp" prop="needFollowUp"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="medium" type="text" @click=" |
| | | viewDetails( |
| | | scope.row.needFollowUpInfo, |
| | | scope.row.leavehospitaldistrictname + |
| | | 'éé访å表' |
| | | ) |
| | | "><span class="button-zx">{{ |
| | | scope.row.needFollowUp |
| | | }}</span></el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="å¾
é访" align="center" 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="é访æå" align="center" key="followUpSuccess" prop="followUpSuccess"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="medium" type="text" @click=" |
| | | viewDetails( |
| | | scope.row.followUpSuccessInfo, |
| | | scope.row.leavehospitaldistrictname + |
| | | 'é访æåå表' |
| | | ) |
| | | "><span class="button-zx">{{ |
| | | scope.row.followUpSuccess |
| | | }}</span></el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="é访失败" align="center" 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="é访ç" align="center" width="120" key="followUpRate" prop="followUpRate"> |
| | | </el-table-column> |
| | | <el-table-column v-if="orgname != '丽水å¸ä¸å»é¢'" label="åæ¶ç" align="center" width="120" key="rate" |
| | | prop="rate"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="medium" type="text" @click="Seedetails(scope.row)"><span class="button-zx">{{ |
| | | (Number(scope.row.rate) * 100).toFixed(2) |
| | | }}%</span></el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="人工" align="center" key="manual" prop="manual"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="medium" type="text" @click=" |
| | | viewDetails( |
| | | scope.row.manualInfo, |
| | | scope.row.leavehospitaldistrictname + |
| | | '人工é访å表' |
| | | ) |
| | | "><span class="button-zx">{{ |
| | | scope.row.manual |
| | | }}</span></el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="çä¿¡" align="center" key="sms" prop="sms"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="medium" type="text" @click=" |
| | | viewDetails( |
| | | scope.row.smsInfo, |
| | | scope.row.leavehospitaldistrictname + |
| | | 'çä¿¡é访å表' |
| | | ) |
| | | "><span class="button-zx">{{ |
| | | scope.row.sms |
| | | }}</span></el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="微信" align="center" key="weChat" prop="weChat"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="medium" type="text" @click=" |
| | | viewDetails( |
| | | scope.row.weChatInfo, |
| | | scope.row.leavehospitaldistrictname + |
| | | '微信é访å表' |
| | | ) |
| | | "><span class="button-zx">{{ |
| | | scope.row.weChat |
| | | }}</span></el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table-column> |
| | | |
| | | <!-- é访æ
åµåï¼ä»
丽水å¸ä¸å»é¢æ¾ç¤ºï¼ --> |
| | | <el-table-column v-if="orgname == '丽水å¸ä¸å»é¢'" align="center" label="é访æ
åµ"> |
| | | <el-table-column label="æ£å¸¸è¯é³" align="center" width="100" key="taskSituation1" |
| | | prop="taskSituation1"> |
| | | </el-table-column><el-table-column label="æ£è
ææ¥ææè®¿" align="center" width="100" key="taskSituation2" |
| | | prop="taskSituation2"> |
| | | </el-table-column><el-table-column label="é¢è®¿æè
æ¥è¯" align="center" width="100" key="taskSituation3" |
| | | prop="taskSituation3"> |
| | | </el-table-column><el-table-column label="微信é访" align="center" width="100" key="taskSituation4" |
| | | prop="taskSituation4"> |
| | | </el-table-column><el-table-column label="é访çµè¯ä¸æ£ç¡®" align="center" width="100" key="taskSituation5" |
| | | prop="taskSituation5"> |
| | | </el-table-column><el-table-column label="å
¶ä»æ
åµä¸å®é访" align="center" width="100" |
| | | key="taskSituation6" prop="taskSituation6"> |
| | | </el-table-column> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </el-tab-pane> |
| | | |
| | | <el-tab-pane label="忬¡é访" name="second"> |
| | | <div class="your-table-container"> |
| | | <el-table ref="exportTableSecond" id="exportTableidSecond" v-loading="loadingSecond" |
| | | :data="secondFollowUpList" :border="true" @selection-change="handleSelectionChangeSecond" |
| | | @expand-change="handleRowClickSecond" :row-key="getRowKey" show-summary |
| | | :summary-method="getSummariesSecond" :expand-row-keys="expandsSecond"> |
| | | <!-- å±å¼è¡ç®å¤´å --> |
| | | <el-table-column type="expand"> |
| | | <template slot-scope="props"> |
| | | <el-table :data="props.row.doctorStats" border style="width: 95%; margin: 0 auto" |
| | | class="inner-table" show-summary :summary-method="getInnerSummariesSecond"> |
| | | <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" key="dischargeCount" prop="dischargeCount"> |
| | | </el-table-column> |
| | | |
| | | <el-table-column label="æ éé访人次" align="center" width="100" key="nonFollowUp" |
| | | prop="nonFollowUp"> |
| | | </el-table-column> |
| | | <el-table-column label="åºé访人次" align="center" width="100" key="followUpNeeded" |
| | | prop="followUpNeeded"> |
| | | </el-table-column> |
| | | <el-table-column align="center" label="忬¡åºé¢é访"> |
| | | <el-table-column label="éé访" align="center" key="needFollowUpAgain" |
| | | prop="needFollowUpAgain"> |
| | | </el-table-column> |
| | | <el-table-column label="å¾
é访" align="center" key="pendingFollowUpAgain" |
| | | prop="pendingFollowUpAgain"> |
| | | </el-table-column> |
| | | <el-table-column label="é访æå" align="center" key="followUpSuccessAgain" |
| | | prop="followUpSuccessAgain"> |
| | | </el-table-column> |
| | | <el-table-column label="é访失败" align="center" key="followUpFailAgain" |
| | | prop="followUpFailAgain"> |
| | | </el-table-column> |
| | | <el-table-column label="é访ç" align="center" width="120" key="followUpRateAgain" |
| | | prop="followUpRateAgain"> |
| | | </el-table-column> |
| | | <el-table-column label="人工" align="center" key="manualAgain" prop="manualAgain"> |
| | | </el-table-column> |
| | | <el-table-column label="çä¿¡" align="center" key="smsAgain" prop="smsAgain"> |
| | | </el-table-column> |
| | | <el-table-column label="微信" align="center" key="weChatAgain" prop="weChatAgain"> |
| | | </el-table-column> |
| | | </el-table-column> |
| | | </el-table> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="åºé¢ç
åº" align="center" sortable key="leavehospitaldistrictname" |
| | | prop="leavehospitaldistrictname" width="150" :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> |
| | | |
| | | <el-table-column label="æ éé访人次" align="center" width="100" key="nonFollowUp" prop="nonFollowUp"> |
| | | </el-table-column> |
| | | <el-table-column label="åºé访人次" align="center" width="100" key="followUpNeeded" |
| | | prop="followUpNeeded"> |
| | | </el-table-column> |
| | | <el-table-column align="center" label="忬¡åºé¢é访"> |
| | | <el-table-column label="éé访" align="center" key="needFollowUpAgain" prop="needFollowUpAgain"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="medium" type="text" @click=" |
| | | viewDetails( |
| | | scope.row.needFollowUpAgainInfo, |
| | | scope.row.leavehospitaldistrictname + |
| | | '忬¡é访éé访å表' |
| | | ) |
| | | "><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=" |
| | | viewDetails( |
| | | scope.row.pendingFollowUpAgainInfo, |
| | | scope.row.leavehospitaldistrictname + |
| | | '忬¡é访å¾
é访å表' |
| | | ) |
| | | "><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=" |
| | | viewDetails( |
| | | scope.row.followUpSuccessAgainInfo, |
| | | scope.row.leavehospitaldistrictname + |
| | | '忬¡é访é访æåå表' |
| | | ) |
| | | "><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=" |
| | | viewDetails( |
| | | scope.row.followUpFailAgainInfo, |
| | | scope.row.leavehospitaldistrictname + |
| | | '忬¡é访é访失败å表' |
| | | ) |
| | | "><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> |
| | | <el-table-column label="人工" align="center" key="manualAgain" prop="manualAgain"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="medium" type="text" @click=" |
| | | viewDetails( |
| | | scope.row.manualAgainInfo, |
| | | scope.row.leavehospitaldistrictname + |
| | | '忬¡é访人工é访å表' |
| | | ) |
| | | "><span class="button-zx">{{ |
| | | scope.row.manualAgain |
| | | }}</span></el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="çä¿¡" align="center" key="smsAgain" prop="smsAgain"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="medium" type="text" @click=" |
| | | viewDetails( |
| | | scope.row.smsAgainInfo, |
| | | scope.row.leavehospitaldistrictname + |
| | | '忬¡é访çä¿¡é访å表' |
| | | ) |
| | | "><span class="button-zx">{{ |
| | | scope.row.smsAgain |
| | | }}</span></el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="微信" align="center" key="weChatAgain" prop="weChatAgain"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="medium" type="text" @click=" |
| | | viewDetails( |
| | | scope.row.weChatAgainInfo, |
| | | scope.row.leavehospitaldistrictname + |
| | | '忬¡é访微信é访å表' |
| | | ) |
| | | "><span class="button-zx">{{ |
| | | scope.row.weChatAgain |
| | | }}</span></el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | </div> |
| | | <!-- ç»è®¡è¶å¿å¾å¼¹çª --> |
| | | <el-dialog title="é访ç»è®¡è¶å¿å¾" :visible.sync="chartDialogVisible" width="80%" :close-on-click-modal="false"> |
| | | <div class="chart-container"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <div class="chart-title">éè®¿ç¶æåå¸</div> |
| | | <div id="pieChart" style="width: 100%; height: 400px"></div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="chart-title">é访è¶å¿åæ</div> |
| | | <div id="barLineChart" style="width: 100%; height: 400px"></div> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | </el-dialog> |
| | | <el-dialog title="æªåæ¶é访æ£è
æå¡" :visible.sync="SeedetailsVisible" v-loading="Seedloading" width="70%" |
| | | :close-on-click-modal="false"> |
| | | <div class="examine-jic"> |
| | | <div class="jic-value"> |
| | | <el-row :gutter="20"> |
| | | <!--ç¨æ·æ°æ®--> |
| | | <el-form :model="patientqueryParams" ref="queryForm" size="small" :inline="true" label-width="98px"> |
| | | <el-form-item label="æ£è
ï¼"> |
| | | <el-input v-model="patientqueryParams.name" @keyup.enter.native="handleQuery"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="æ£è
è¯æï¼"> |
| | | <el-input v-model="patientqueryParams.leavediagname" @keyup.enter.native="handleQuery"></el-input> |
| | | </el-form-item> |
| | | |
| | | <el-form-item> |
| | | <el-button type="primary" icon="el-icon-search" size="medium" @click="handleQuery">æç´¢</el-button> |
| | | <el-button icon="el-icon-refresh" size="medium" @click="resetQuery">åæ¶å建</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | <!-- éæ©æ£è
å表 --> |
| | | <el-table :data="logsheetlist" 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="Seedetailstion" /> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | <!-- å类详æ
--> |
| | | <el-dialog :title="infotitle" :visible.sync="infotitleVisible" v-loading="infotitloading" width="70%" |
| | | :close-on-click-modal="false"> |
| | | <div style="margin-bottom: 16px; display: flex; align-items: center"> |
| | | <span style="margin-right: 10px; font-weight: bold">æ£è
å§åæ¥è¯¢:</span> |
| | | <el-input v-model="searchName" placeholder="请è¾å
¥æ£è
å§åè¿è¡çé" clearable style="width: 300px" @input="handleSearch" |
| | | @clear="handleSearch"> |
| | | </el-input> |
| | | <span style="margin-left: 10px; color: rgb(35, 81, 233); font-size: 16px"> |
| | | å
± {{ infotitlelist.length }} æ¡è®°å½ |
| | | </span> |
| | | </div> |
| | | <div class="examine-jic"> |
| | | <div class="jic-value"> |
| | | <el-row :gutter="20"> |
| | | <!-- éæ©æ£è
å表 --> |
| | | <div class="data-list" ref="dataList" @scroll="handleScroll" v-loading="infotitloading"> |
| | | <el-table :data="currentDisplayList" 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 label="任塿§è¡æ¹å¼" align="center" key="preachform" prop="preachform" width="160" |
| | | :show-overflow-tooltip="true"> |
| | | <template slot-scope="scope"> |
| | | <span v-for="item in scope.row.preachform">{{ item }}ã |
| | | </span> |
| | | </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> |
| | | </div> |
| | | </el-row> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { |
| | | toamendtag, |
| | | addapitag, |
| | | deletetag, |
| | | changetagcategory, |
| | | } 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 = [ |
| | | { |
| | | text: "ä»å¤©", |
| | | onClick(picker) { |
| | | picker.$emit("pick", new Date()); |
| | | }, |
| | | }, |
| | | { |
| | | text: "æ¨å¤©", |
| | | onClick(picker) { |
| | | const date = new Date(); |
| | | date.setTime(date.getTime() - 3600 * 1000 * 24); |
| | | picker.$emit("pick", date); |
| | | }, |
| | | }, |
| | | { |
| | | text: "ä¸å¨å", |
| | | onClick(picker) { |
| | | const date = new Date(); |
| | | date.setTime(date.getTime() - 3600 * 1000 * 24 * 7); |
| | | picker.$emit("pick", date); |
| | | }, |
| | | }, |
| | | ]; |
| | | |
| | | export default { |
| | | name: "Percentage", |
| | | dicts: ["sys_normal_disable", "sys_user_sex"], |
| | | components: { Treeselect }, |
| | | data() { |
| | | return { |
| | | // æ°å¢ï¼Tabæ ç¾é¡µæ§å¶ |
| | | activeTab: "first", // å½åæ¿æ´»çtabï¼first-馿¬¡é访ï¼second-忬¡é访 |
| | | |
| | | // åç¦»çæ°æ®å表 |
| | | firstFollowUpList: [], // 馿¬¡éè®¿æ°æ® |
| | | secondFollowUpList: [], // 忬¡éè®¿æ°æ® |
| | | |
| | | // å离çå è½½ç¶æ |
| | | loading: false, // 馿¬¡éè®¿è¡¨æ ¼å è½½ç¶æ |
| | | loadingSecond: false, // 忬¡éè®¿è¡¨æ ¼å è½½ç¶æ |
| | | |
| | | // å离çå±å¼ç¶æ |
| | | expands: [], // 馿¬¡éè®¿è¡¨æ ¼å±å¼è¡ |
| | | expandsSecond: [], // 忬¡éè®¿è¡¨æ ¼å±å¼è¡ |
| | | |
| | | // å离çéæ©ç¶æ |
| | | ids: [], // 馿¬¡é访éä¸é¡¹ |
| | | idsSecond: [], // 忬¡é访éä¸é¡¹ |
| | | |
| | | orgname: "", |
| | | infotitlelist: [], |
| | | currentDisplayList: [], |
| | | loadIndex: 0, |
| | | pageSize: 100, |
| | | isLoading: false, |
| | | |
| | | Seedloading: false, |
| | | chartDialogVisible: false, |
| | | infotitleVisible: false, |
| | | searchName: "", |
| | | infotitloading: false, |
| | | infotitle: "", |
| | | pieChart: null, |
| | | barLineChart: null, |
| | | |
| | | single: true, |
| | | multiple: true, |
| | | showSearch: true, |
| | | idds: "", |
| | | total: 0, |
| | | flatArrayhospit: [], |
| | | flatArraydept: [], |
| | | patienttotal: 0, |
| | | logsheetlist: [], |
| | | Statisticallist: [ |
| | | { |
| | | label: "ç
åºç»è®¡", |
| | | value: 1, |
| | | }, |
| | | { |
| | | label: "ç§å®¤ç»è®¡", |
| | | value: 2, |
| | | }, |
| | | ], |
| | | patientqueryParams: { |
| | | pn: 1, |
| | | ps: 10, |
| | | }, |
| | | amendtag: false, |
| | | lstamendtag: false, |
| | | scavisible: false, |
| | | deleteVisible: false, |
| | | deletefenl: "é«è¡å", |
| | | tagform: { |
| | | isupload: "", |
| | | tagname: "", |
| | | tagcategoryid: "", |
| | | tagdescription: "", |
| | | }, |
| | | classifyform: { |
| | | categoryname: "", |
| | | }, |
| | | title: "", |
| | | open: false, |
| | | dateRange: [], |
| | | postOptions: [], |
| | | roleOptions: [], |
| | | allDeptCodes: [], |
| | | allWardCodes: [], |
| | | checkboxlist: [], |
| | | form: {}, |
| | | forms: { |
| | | name: "", |
| | | }, |
| | | numberlb: 22, |
| | | dialogFormVisible: false, |
| | | lstamendtagVisible: false, |
| | | goQRCodeVisible: false, |
| | | sidecolumnval: "", |
| | | propss: { multiple: true }, |
| | | SeedetailsVisible: false, |
| | | options: store.getters.tasktypes, |
| | | pickerOptions: { |
| | | disabledDate(time) { |
| | | return time.getTime() < Date.now() - 3600 * 1000 * 24; |
| | | }, |
| | | shortcuts: shortcuts, |
| | | }, |
| | | pickerOptionsa: { |
| | | disabledDate(time) { |
| | | return time.getTime() > Date.now(); |
| | | }, |
| | | shortcuts: shortcuts, |
| | | }, |
| | | queryParams: { |
| | | serviceType: [2], |
| | | dateRange: [], |
| | | statisticaltype: 1, |
| | | leavehospitaldistrictcodes: ["all"], |
| | | deptcodes: [], |
| | | visitCount: 1, // æ°å¢ï¼é访次æ°åæ°ï¼1-馿¬¡ï¼2-忬¡ |
| | | }, |
| | | columns: [ |
| | | { key: 0, label: `æ ç¾ç¼å·`, visible: true }, |
| | | { key: 1, label: `æ ç¾åç§°`, visible: true }, |
| | | { key: 2, label: `æ ç¾æµç§°`, visible: true }, |
| | | { key: 3, label: `é¨é¨`, visible: true }, |
| | | { key: 4, label: `ææºå·ç `, visible: true }, |
| | | { key: 5, label: `ç¶æ`, visible: true }, |
| | | { key: 6, label: `å建æ¶é´`, visible: true }, |
| | | ], |
| | | }; |
| | | }, |
| | | watch: {}, |
| | | created() { |
| | | this.getDeptTree(); |
| | | this.getFirstFollowUpList(); // é»è®¤å è½½é¦æ¬¡éè®¿æ°æ® |
| | | this.checkboxlist = store.getters.checkboxlist; |
| | | this.orgname = localStorage.getItem("orgname"); |
| | | }, |
| | | |
| | | methods: { |
| | | /** æ¥è¯¢é¦æ¬¡é访å表 */ |
| | | async getFirstFollowUpList() { |
| | | this.loading = true; |
| | | this.queryParams.visitCount = 1; // 设置é访次æ°ä¸ºé¦æ¬¡ |
| | | |
| | | 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; |
| | | |
| | | try { |
| | | const response = await getSfStatistics(params); |
| | | this.firstFollowUpList = this.customSort(response.data); |
| | | this.total = response.total; |
| | | } catch (error) { |
| | | console.error("è·å馿¬¡éè®¿æ°æ®å¤±è´¥:", error); |
| | | this.$message.error("è·å馿¬¡éè®¿æ°æ®å¤±è´¥"); |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | |
| | | /** æ¥è¯¢å次é访å表 */ |
| | | async getSecondFollowUpList() { |
| | | this.loadingSecond = true; |
| | | this.queryParams.visitCount = 2; // 设置é访次æ°ä¸ºå次 |
| | | |
| | | 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; |
| | | |
| | | try { |
| | | const response = await getSfStatistics(params); |
| | | this.secondFollowUpList = this.customSort(response.data); |
| | | this.total = response.total; |
| | | } catch (error) { |
| | | console.error("è·å忬¡éè®¿æ°æ®å¤±è´¥:", error); |
| | | this.$message.error("è·å忬¡éè®¿æ°æ®å¤±è´¥"); |
| | | } finally { |
| | | this.loadingSecond = false; |
| | | } |
| | | }, |
| | | |
| | | /** Tab忢äºä»¶ */ |
| | | handleTabClick(tab) { |
| | | if (tab.name === "first") { |
| | | if (this.firstFollowUpList.length === 0) { |
| | | this.getFirstFollowUpList(); |
| | | } |
| | | } else if (tab.name === "second") { |
| | | if (this.secondFollowUpList.length === 0) { |
| | | this.getSecondFollowUpList(); |
| | | } |
| | | } |
| | | }, |
| | | sortChineseNumber(aRow, bRow) { |
| | | const a = aRow.leavehospitaldistrictname; |
| | | const b = bRow.leavehospitaldistrictname; |
| | | |
| | | // 䏿æ°åå°é¿æä¼¯æ°åçæ å°ï¼æ©å±å°45ï¼ |
| | | 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, |
| | | }; |
| | | |
| | | // æå䏿æ°å |
| | | 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; |
| | | } |
| | | |
| | | // å¦ææ²¡æå¹é
å°ä¸ææ°åï¼å°è¯å¹é
é¿æä¼¯æ°å |
| | | const arabicMatch = text.match(/^(\d+)/); |
| | | if (arabicMatch && arabicMatch[1]) { |
| | | const num = parseInt(arabicMatch[1], 10); |
| | | return num >= 1 && num <= 45 ? num : -1; |
| | | } |
| | | |
| | | return -1; |
| | | }; |
| | | |
| | | const numA = getNumberFromText(a); |
| | | const numB = getNumberFromText(b); |
| | | |
| | | // å¤çæ æ³è§£æçæ
åµ |
| | | if (numA === -1 && numB === -1) { |
| | | return (a || "").localeCompare(b || ""); |
| | | } |
| | | if (numA === -1) return 1; |
| | | if (numB === -1) return -1; |
| | | |
| | | return numA - numB; |
| | | }, |
| | | // æç´¢å¤ç彿° |
| | | handleSearch() { |
| | | if (!this.searchName.trim()) { |
| | | // 妿æç´¢æ¡ä¸ºç©ºï¼æ¾ç¤ºæææ°æ® |
| | | this.currentDisplayList = [...this.infotitlelist]; |
| | | } else { |
| | | // æ ¹æ®æ£è
å§åè¿è¡çéï¼ä¸åºå大å°åï¼ |
| | | const keyword = this.searchName.toLowerCase(); |
| | | this.currentDisplayList = this.infotitlelist.filter((item) => { |
| | | return item.sendname && item.sendname.toLowerCase().includes(keyword); |
| | | }); |
| | | } |
| | | }, |
| | | customSort(data) { |
| | | // å®ä¹æ¨ææçç
åºé¡ºåºï¼æ©å±å°ååäºï¼ |
| | | const order = [ |
| | | "ä¸", |
| | | "äº", |
| | | "ä¸", |
| | | "å", |
| | | "äº", |
| | | "å
", |
| | | "ä¸", |
| | | "å
«", |
| | | "ä¹", |
| | | "å", |
| | | "åä¸", |
| | | "åäº", |
| | | "åä¸", |
| | | "åå", |
| | | "åäº", |
| | | "åå
", |
| | | "åä¸", |
| | | "åå
«", |
| | | "åä¹", |
| | | "äºå", |
| | | "äºåä¸", |
| | | "äºåäº", |
| | | "äºåä¸", |
| | | "äºåå", |
| | | "äºåäº", |
| | | "äºåå
", |
| | | "äºåä¸", |
| | | "äºåå
«", |
| | | "äºåä¹", |
| | | "ä¸å", |
| | | "ä¸åä¸", |
| | | "ä¸åäº", |
| | | "ä¸åä¸", |
| | | "ä¸åå", |
| | | "ä¸åäº", |
| | | "ä¸åå
", |
| | | "ä¸åä¸", |
| | | "ä¸åå
«", |
| | | "ä¸åä¹", |
| | | "åå", |
| | | "ååä¸", |
| | | "ååäº", |
| | | "ååä¸", |
| | | "ååå", |
| | | "ååäº", |
| | | ]; |
| | | |
| | | return data.sort((a, b) => { |
| | | // æåç
åºåç§°ä¸ç䏿æ°åé¨å |
| | | const getIndex = (name) => { |
| | | if (!name || typeof name !== "string") return -1; |
| | | |
| | | // å¹é
䏿æ°å |
| | | const chineseMatch = name.match(/^([ä¸äºä¸åäºå
ä¸å
«ä¹å]+)/); |
| | | if (chineseMatch && chineseMatch[1]) { |
| | | return order.indexOf(chineseMatch[1]); |
| | | } |
| | | |
| | | // å¹é
é¿æä¼¯æ°å |
| | | const arabicMatch = name.match(/^(\d+)/); |
| | | if (arabicMatch && arabicMatch[1]) { |
| | | const num = parseInt(arabicMatch[1], 10); |
| | | if (num >= 1 && num <= 45) { |
| | | return num - 1; // å 为æ°ç»ç´¢å¼ä»0å¼å§ |
| | | } |
| | | } |
| | | |
| | | return -1; |
| | | }; |
| | | |
| | | const indexA = getIndex(a.leavehospitaldistrictname); |
| | | const indexB = getIndex(b.leavehospitaldistrictname); |
| | | |
| | | // æåºé»è¾ |
| | | if (indexA === -1 && indexB === -1) { |
| | | return (a.leavehospitaldistrictname || "").localeCompare( |
| | | b.leavehospitaldistrictname || "" |
| | | ); |
| | | } |
| | | if (indexA === -1) return 1; |
| | | if (indexB === -1) return -1; |
| | | return indexA - indexB; |
| | | }); |
| | | }, |
| | | getRowKey(row) { |
| | | return row.statisticaltype === 1 |
| | | ? row.leavehospitaldistrictcode |
| | | : row.deptcode; |
| | | }, |
| | | |
| | | // å¤çè¡ç¹å»å±å¼ |
| | | handleRowClick(row) { |
| | | console.log(row, "row"); |
| | | |
| | | // 妿已ç»å±å¼åæ¶èµ· |
| | | if (this.expands.includes(this.getRowKey(row))) { |
| | | this.expands = []; |
| | | return; |
| | | } |
| | | // å¤çæ¥è¯¢åæ° |
| | | const params = { |
| | | ...this.queryParams, |
| | | // 妿鿩äº"å
¨é¨"ï¼åä¼ ææç
åº/ç§å®¤ä»£ç |
| | | deptcodes: this.queryParams.deptcodes.includes("all") |
| | | ? this.allDeptCodes |
| | | : this.queryParams.deptcodes, |
| | | leavehospitaldistrictcodes: [row.leavehospitaldistrictcode], |
| | | drcode: "1", |
| | | visitCount: 1, // è®¾ç½®ä¸ºé¦æ¬¡é访 |
| | | }; |
| | | |
| | | // ç§»é¤å¯è½åå¨ç"all"å¼ |
| | | delete params.leavehospitaldistrictcodes.all; |
| | | delete params.deptcodes.all; |
| | | // å¦æè¯¥è¡è¿æ²¡æå è½½å»çæ°æ®ï¼åå è½½ |
| | | if (!row.doctorStats) { |
| | | this.loading = true; |
| | | getSfStatistics(params).then((res) => { |
| | | this.$set(row, "doctorStats", res.data); |
| | | this.expands = [this.getRowKey(row)]; |
| | | this.loading = false; |
| | | }); |
| | | } else { |
| | | this.expands = [this.getRowKey(row)]; |
| | | } |
| | | }, |
| | | getSummaries(param) { |
| | | const { columns, data } = param; |
| | | const sums = []; |
| | | |
| | | columns.forEach((column, index) => { |
| | | if (index === 0) { |
| | | sums[index] = "å计"; |
| | | return; |
| | | } |
| | | if (index === 1 || index === 2) { |
| | | sums[index] = "/"; |
| | | return; |
| | | } |
| | | |
| | | // 对ç¾åæ¯åæ®µç¹æ®å¤ç - åå¹³åå¼ |
| | | if ( |
| | | column.property === "followUpRate" || |
| | | column.property === "rate" || |
| | | column.property === "followUpRateAgain" |
| | | ) { |
| | | // æåææææç¾åæ¯å¼å¹¶è½¬æ¢ä¸ºå°æ° |
| | | const percentageValues = data |
| | | .map((item) => { |
| | | 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; |
| | | } else { |
| | | // å¤çå·²ç»æ¯å°æ°çæ°æ® |
| | | const numValue = parseFloat(value); |
| | | return isNaN(numValue) ? null : numValue; |
| | | } |
| | | }) |
| | | .filter((value) => value !== null && value !== 0); // è¿æ»¤ænullå0å¼ |
| | | |
| | | if (percentageValues.length > 0) { |
| | | const average = |
| | | percentageValues.reduce((sum, value) => sum + value, 0) / |
| | | percentageValues.length; |
| | | sums[index] = (average * 100).toFixed(2) + "%"; |
| | | } else { |
| | | 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; |
| | | }); |
| | | |
| | | if (!values.every((value) => isNaN(value))) { |
| | | sums[index] = values.reduce((prev, curr) => prev + curr, 0); |
| | | sums[index] = this.formatNumber(sums[index]); |
| | | } else { |
| | | sums[index] = "-"; |
| | | } |
| | | } |
| | | }); |
| | | |
| | | return sums; |
| | | }, |
| | | |
| | | // å
é¨è¡¨æ ¼å计è¡è®¡ç®æ¹æ³ |
| | | getInnerSummaries(param) { |
| | | const { columns, data } = param; |
| | | const sums = []; |
| | | |
| | | columns.forEach((column, index) => { |
| | | if (index === 0) { |
| | | sums[index] = "å°è®¡"; |
| | | return; |
| | | } |
| | | |
| | | if (column.property === "drname" || column.property === "deptname") { |
| | | sums[index] = "-"; |
| | | return; |
| | | } |
| | | |
| | | // 对ç¾åæ¯åæ®µç¹æ®å¤ç - åå¹³åå¼ |
| | | if (column.property === "followUpRate" || column.property === "rate") { |
| | | // æåææææç¾åæ¯å¼å¹¶è½¬æ¢ä¸ºå°æ° |
| | | const percentageValues = data |
| | | .map((item) => { |
| | | 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; |
| | | } else { |
| | | // å¤çå·²ç»æ¯å°æ°çæ°æ® |
| | | const numValue = parseFloat(value); |
| | | return isNaN(numValue) ? null : numValue; |
| | | } |
| | | }) |
| | | .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) + "%"; |
| | | } else { |
| | | 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; |
| | | }); |
| | | |
| | | if (!values.every((value) => isNaN(value))) { |
| | | sums[index] = values.reduce((prev, curr) => prev + curr, 0); |
| | | sums[index] = this.formatNumber(sums[index]); |
| | | } else { |
| | | sums[index] = "-"; |
| | | } |
| | | } |
| | | }); |
| | | |
| | | return sums; |
| | | }, |
| | | |
| | | // è¾
婿¹æ³ï¼æåç¾åæ¯æ°å¼ |
| | | extractPercentageValue(value) { |
| | | if (!value) return null; |
| | | |
| | | if (typeof value === "string") { |
| | | // å¤ç带ç¾åå·çå符串 |
| | | if (value.includes("%")) { |
| | | const num = parseFloat(value.replace("%", "")); |
| | | return isNaN(num) ? null : num / 100; |
| | | } |
| | | // å¤ç纯æ°åå符串 |
| | | const num = parseFloat(value); |
| | | return isNaN(num) ? null : num; |
| | | } |
| | | |
| | | // å¤çæ°åç±»å |
| | | return typeof value === "number" ? value : null; |
| | | }, |
| | | |
| | | // æ°åæ ¼å¼åæ¹æ³ |
| | | formatNumber(num) { |
| | | if (isNaN(num)) return "-"; |
| | | return Number.isInteger(num) ? num.toString() : num.toFixed(0); |
| | | }, |
| | | /** ä¿®æ¹æ ç¾ */ |
| | | handleUpdate(row) { |
| | | console.log(row, "ä¿®æ¹æ ç¾"); |
| | | this.lstamendtagVisible = true; |
| | | this.lstamendtag = true; |
| | | this.tagform = { |
| | | isupload: row.isupload, |
| | | tagname: row.tagname, |
| | | tagcategoryid: row.tagcategoryid, |
| | | tagdescription: row.tagdescription, |
| | | tagid: row.tagid, |
| | | }; |
| | | }, |
| | | // è·åç§å®¤æ |
| | | getDeptTree() { |
| | | // ç§å®¤å表 |
| | | this.flatArraydept = store.getters.belongDepts.map((dept) => { |
| | | return { |
| | | label: dept.deptName, |
| | | value: dept.deptCode, |
| | | }; |
| | | }); |
| | | // å卿æç§å®¤ä»£ç |
| | | this.allDeptCodes = store.getters.belongDepts.map( |
| | | (dept) => dept.deptCode |
| | | ); |
| | | |
| | | // ç
åºå表 |
| | | this.flatArrayhospit = store.getters.belongWards.map((ward) => { |
| | | return { |
| | | label: ward.districtName, |
| | | value: ward.districtCode, |
| | | }; |
| | | }); |
| | | |
| | | // å卿æç
åºä»£ç |
| | | this.allWardCodes = store.getters.belongWards.map( |
| | | (ward) => ward.districtCode |
| | | ); |
| | | this.flatArraydept.push({ label: "å
¨é¨", value: "all" }); |
| | | this.flatArrayhospit.push({ label: "å
¨é¨", value: "all" }); |
| | | }, |
| | | flattenArray(multiArray) { |
| | | let result = []; |
| | | |
| | | // éå½å½æ°ï¼ç¨äºå°å¤çº§æ°ç»è½¬æ¢ä¸ºä¸ç»´æ°ç»ï¼åªå
嫿åºå±çå
ç´ |
| | | function flatten(element) { |
| | | // 妿å½åå
ç´ æåå
ç´ ï¼ç»§ç»éå½ |
| | | if (element.children && element.children.length > 0) { |
| | | element.children.forEach((child) => flatten(child)); |
| | | } else { |
| | | // å
éå
ç´ ä»¥é¿å
ä¿®æ¹åå§æ°æ® |
| | | let item = JSON.parse(JSON.stringify(element)); |
| | | result.push(item); // å°æåºå±çå
ç´ æ·»å å°ç»ææ°ç» |
| | | } |
| | | } |
| | | |
| | | // ä»é¡¶å±å
ç´ å¼å§éå½ |
| | | multiArray.forEach((element) => flatten(element)); |
| | | return result; // è¿ååªå
嫿åºå±å
ç´ çä¸ç»´æ°ç» |
| | | }, |
| | | addladeltag() { |
| | | this.lstamendtagVisible = true; |
| | | this.lstamendtag = false; |
| | | this.tagform = { |
| | | isupload: "", |
| | | tagname: "", |
| | | tagcategoryid: "", |
| | | tagdescription: "", |
| | | tagid: "", |
| | | }; |
| | | }, |
| | | Seedetails(row) { |
| | | this.SeedetailsVisible = true; |
| | | this.Seedloading = true; |
| | | this.patientqueryParams.starttime = this.parseTime( |
| | | this.queryParams.dateRange[0] |
| | | ); |
| | | this.patientqueryParams.endtime = this.parseTime( |
| | | this.queryParams.dateRange[1] |
| | | ); |
| | | this.patientqueryParams.deptcode = row.deptcode; |
| | | selectTimelyRate(this.patientqueryParams).then((response) => { |
| | | this.logsheetlist = response.data.detail; |
| | | this.patienttotal = response.data.total; |
| | | this.Seedloading = false; |
| | | }); |
| | | }, |
| | | Seedetailstion() { |
| | | selectTimelyRate(this.patientqueryParams).then((response) => { |
| | | this.logsheetlist = response.data.detail; |
| | | this.patienttotal = response.data.total; |
| | | this.Seedloading = false; |
| | | }); |
| | | }, |
| | | viewDetails(row, title) { |
| | | this.infotitleVisible = true; |
| | | this.infotitle = title; |
| | | this.infotitlelist = row; // å设rowå°±æ¯éè¦å±ç¤ºçè¯¦ç»æ°ç» |
| | | console.log(this.infotitlelist, "this.infotitlelist"); |
| | | |
| | | this.infotitlelist.forEach((item) => { |
| | | let idArray = null; |
| | | |
| | | if (item.preachform) { |
| | | if (item.endtime) { |
| | | item.preachformson = item.preachform; |
| | | idArray = item.preachform.split(","); |
| | | } |
| | | |
| | | item.preachform = idArray.map((value) => { |
| | | // æ¥æ¾id对åºç对象 |
| | | const item = this.checkboxlist.find((item) => item.value == value); |
| | | // 妿æ¾å°å¯¹åºçidï¼è¿ålabelå¼ï¼å¦åè¿ånull |
| | | return item ? item.label : null; |
| | | }); |
| | | } |
| | | }); |
| | | // åå§åå è½½ |
| | | this.loadIndex = 0; |
| | | this.currentDisplayList = []; |
| | | this.$nextTick(() => { |
| | | this.loadMoreData(); |
| | | }); |
| | | }, |
| | | loadMoreData() { |
| | | if (this.isLoading) return; |
| | | this.isLoading = true; |
| | | |
| | | // 模æå¼æ¥å è½½ï¼å®é
å¯è½æ¯ç´æ¥åçæ¬å°æ°æ® |
| | | setTimeout(() => { |
| | | console.log(this.infotitlelist, "this.infotitlelist"); |
| | | |
| | | const nextChunk = this.infotitlelist.slice( |
| | | this.loadIndex, |
| | | this.loadIndex + this.pageSize |
| | | ); |
| | | this.currentDisplayList = this.currentDisplayList.concat(nextChunk); |
| | | this.loadIndex += this.pageSize; |
| | | this.isLoading = false; |
| | | }, 200); |
| | | }, |
| | | handleScroll(event) { |
| | | const scrollContainer = event.target; |
| | | // 夿æ¯å¦æ»å¨å°åºé¨ |
| | | const isAtBottom = |
| | | scrollContainer.scrollTop + scrollContainer.clientHeight >= |
| | | scrollContainer.scrollHeight - 10; |
| | | |
| | | if ( |
| | | isAtBottom && |
| | | !this.isLoading && |
| | | this.loadIndex < this.infotitlelist.length |
| | | ) { |
| | | this.loadMoreData(); |
| | | } |
| | | }, |
| | | SeedetailsgGo(row) { |
| | | this.SeedetailsVisible = false; |
| | | let type = ""; |
| | | if (row.preachformson && row.preachformson.includes("3")) { |
| | | type = 1; |
| | | } |
| | | setTimeout(() => { |
| | | this.$router.push({ |
| | | path: "/followvisit/record/detailpage/", |
| | | query: { |
| | | taskid: row.taskid, |
| | | patid: row.patid, |
| | | id: row.id, |
| | | Voicetype: type, |
| | | // visitCount: this.topqueryParams.visitCount, |
| | | }, |
| | | }); |
| | | }, 300); |
| | | }, |
| | | // æ·»å /ä¿®æ¹æ ç¾ |
| | | Maintenancetag() { |
| | | if (this.lstamendtag) { |
| | | toamendtag(this.addDateRange(this.tagform)).then((response) => { |
| | | console.log(response); |
| | | this.getList(); |
| | | }); |
| | | } else { |
| | | addapitag(this.addDateRange(this.tagform)).then((response) => { |
| | | console.log(response); |
| | | this.getList(); |
| | | }); |
| | | } |
| | | this.tagform = { |
| | | isupload: "", |
| | | tagname: "", |
| | | tagcategoryid: "", |
| | | tagdescription: "", |
| | | tagid: "", |
| | | }; |
| | | }, |
| | | routerErr(row) { |
| | | console.log(row, "跳转å¼å¸¸"); |
| | | this.$router.push({ |
| | | path: "/followvisit/discharge", |
| | | query: { |
| | | errtype: 1, |
| | | leavehospitaldistrictcode: row.leavehospitaldistrictcode, |
| | | }, |
| | | }); |
| | | }, |
| | | |
| | | // 表åéç½® |
| | | reset() { |
| | | this.form = { |
| | | userId: undefined, |
| | | deptId: undefined, |
| | | userName: undefined, |
| | | nickName: undefined, |
| | | password: undefined, |
| | | phonenumber: undefined, |
| | | email: undefined, |
| | | sex: undefined, |
| | | status: "0", |
| | | remark: undefined, |
| | | postIds: [], |
| | | roleIds: [], |
| | | }; |
| | | this.resetForm("form"); |
| | | }, |
| | | // æ ç¾ç¶æä¿®æ¹ |
| | | handleStatusChange(row) { |
| | | console.log(row.isupload); |
| | | let text = row.isupload === "0" ? "å¯ç¨" : "åç¨"; |
| | | this.$modal |
| | | .confirm('确认è¦"' + text + '""' + row.tagname + '"æ ç¾åï¼') |
| | | .then(function () { |
| | | return changetagcategory(row.tagid, row.isupload); |
| | | }) |
| | | .then(() => { |
| | | this.$modal.msgSuccess(text + "æå"); |
| | | }) |
| | | .catch(function () { |
| | | row.isupload = row.isupload === "0" ? "1" : "0"; |
| | | }); |
| | | }, |
| | | /** æç´¢æé®æä½ - ä¿®æ¹ä¸ºæç´¢å½åæ¿æ´»çtabæ°æ® */ |
| | | handleQuery() { |
| | | this.queryParams.pageNum = 1; |
| | | if (!this.queryParams.dateRange) this.queryParams.dateRange = []; |
| | | if (this.queryParams.statisticaltype == 1) { |
| | | this.queryParams.deptcodes = []; |
| | | } else if (this.queryParams.statisticaltype == 2) { |
| | | this.queryParams.leavehospitaldistrictcodes = []; |
| | | } |
| | | |
| | | this.queryParams.startTime = this.parseTime( |
| | | this.queryParams.dateRange[0] |
| | | ); |
| | | this.queryParams.endTime = this.parseTime(this.queryParams.dateRange[1]); |
| | | |
| | | // æ ¹æ®å½åæ¿æ´»çtabå è½½å¯¹åºæ°æ® |
| | | if (this.activeTab === "first") { |
| | | this.getFirstFollowUpList(); |
| | | } else { |
| | | this.getSecondFollowUpList(); |
| | | } |
| | | }, |
| | | |
| | | /** éç½®æé®æä½ */ |
| | | resetQuery() { |
| | | this.queryParams.dateRange = []; |
| | | this.queryParams.leavehospitaldistrictcodes = []; |
| | | this.handleQuery(); |
| | | }, |
| | | // å¤éæ¡é䏿°æ® |
| | | handleSelectionChange(selection) { |
| | | this.ids = selection.map((item) => item.tagid); |
| | | this.single = selection.length != 1; |
| | | this.multiple = !selection.length; |
| | | }, |
| | | |
| | | /** å é¤æé®æä½ */ |
| | | handleDelete(row) { |
| | | console.log(row, "å é¤å¼¹çª"); |
| | | const tagids = row.tagid || this.ids; |
| | | console.log(tagids); |
| | | const tagname = row.tagname; |
| | | this.$modal |
| | | .confirm( |
| | | tagname |
| | | ? 'æ¯å¦ç¡®è®¤å 餿 ç¾å称为"' + tagname + '"çæ°æ®é¡¹ï¼' |
| | | : "æ¯å¦ç¡®è®¤å é¤éä¸çæ°æ®é¡¹ï¼" |
| | | ) |
| | | .then(function () { |
| | | return deletetag(tagids); |
| | | }) |
| | | .then(() => { |
| | | this.getList(); |
| | | this.$modal.msgSuccess("å 餿å"); |
| | | }) |
| | | .catch(() => { }); |
| | | }, |
| | | // å¯¼åºæ¹æ³ |
| | | |
| | | async exportTable() { |
| | | try { |
| | | // 1. è·åå¹¶æ ¼å¼åæ¥æèå´ |
| | | 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]; |
| | | const formatDateForDisplay = (dateTimeStr) => { |
| | | 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}æ`; |
| | | } |
| | | |
| | | // 2. æ ¹æ®å½åæ¿æ´»çtabç¡®å®å¯¼åºçæ°æ® |
| | | const isFirstFollowUp = this.activeTab === "first"; |
| | | let excelName, worksheetName, dataToExport; |
| | | |
| | | if (isFirstFollowUp) { |
| | | excelName = `馿¬¡åºé¢é访ç»è®¡è¡¨_${dateRangeString}.xlsx`; |
| | | worksheetName = `馿¬¡é访ç»è®¡_${sheetNameSuffix}`; |
| | | dataToExport = this.firstFollowUpList; |
| | | |
| | | if (!dataToExport || dataToExport.length === 0) { |
| | | this.$message.warning("ææ é¦æ¬¡éè®¿æ°æ®å¯å¯¼åº"); |
| | | return false; |
| | | } |
| | | } else { |
| | | excelName = `忬¡åºé¢é访ç»è®¡è¡¨_${dateRangeString}.xlsx`; |
| | | worksheetName = `忬¡é访ç»è®¡_${sheetNameSuffix}`; |
| | | dataToExport = this.secondFollowUpList; |
| | | |
| | | if (!dataToExport || dataToExport.length === 0) { |
| | | this.$message.warning("ææ åæ¬¡éè®¿æ°æ®å¯å¯¼åº"); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | // 3. å建工ä½ç°¿åå·¥ä½è¡¨ |
| | | const workbook = new ExcelJS.Workbook(); |
| | | const worksheet = workbook.addWorksheet(worksheetName); |
| | | |
| | | // 4. æå»ºè¡¨æ ¼ |
| | | if (isFirstFollowUp) { |
| | | this.buildFirstFollowUpExportSheet( |
| | | worksheet, |
| | | dataToExport, |
| | | sheetNameSuffix |
| | | ); |
| | | } else { |
| | | this.buildSecondFollowUpExportSheet( |
| | | worksheet, |
| | | dataToExport, |
| | | sheetNameSuffix |
| | | ); |
| | | } |
| | | |
| | | // 5. çæå¹¶ä¸è½½æä»¶ |
| | | 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; |
| | | } |
| | | }, |
| | | /** æå»ºé¦æ¬¡é访导åºè¡¨æ ¼ */ |
| | | buildFirstFollowUpExportSheet(worksheet, data, 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" } }, |
| | | }, |
| | | }; |
| | | |
| | | 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, 16); // åå¹¶A1å°P1 |
| | | const titleCell = worksheet.getCell(1, 1); |
| | | titleCell.value = `馿¬¡åºé¢é访ç»è®¡è¡¨_${sheetNameSuffix}`; |
| | | titleCell.style = titleStyle; |
| | | worksheet.getRow(1).height = 35; |
| | | |
| | | // 2. å建表头 |
| | | const secondRowHeaders = [ |
| | | "", // A2 å±å¼åå ä½ |
| | | "åºé¢ç
åº", |
| | | "ç§å®¤", |
| | | "åºé¢äººæ¬¡", |
| | | "æ éé访人次", |
| | | "åºé访人次", // B2 to F2 |
| | | // 馿¬¡åºé¢é访å表头 |
| | | "éé访", |
| | | "å¾
é访", |
| | | "é访æå", |
| | | "é访失败", |
| | | "é访ç", |
| | | "åæ¶ç", |
| | | "人工", |
| | | "çä¿¡", |
| | | "微信", |
| | | ]; |
| | | |
| | | // æ·»å 第äºè¡ |
| | | secondRowHeaders.forEach((header, index) => { |
| | | const cell = worksheet.getCell(3, index + 1); |
| | | cell.value = header; |
| | | cell.style = headerStyle; |
| | | }); |
| | | |
| | | // 3. åå¹¶åå
æ ¼ |
| | | // åå¹¶ A2:A3, B2:B3, C2:C3, D2:D3, E2:E3, F2:F3 |
| | | for (let i = 1; i <= 6; i++) { |
| | | 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 = "åºé访人次"; |
| | | |
| | | // 4. åå¹¶"馿¬¡åºé¢é访"æ é¢ |
| | | worksheet.mergeCells(2, 7, 2, 15); // G2:O2 |
| | | worksheet.getCell(2, 7).value = "馿¬¡åºé¢é访"; |
| | | worksheet.getCell(2, 7).style = headerStyle; |
| | | |
| | | // 5. 设置è¡é« |
| | | worksheet.getRow(2).height = 28; |
| | | worksheet.getRow(3).height = 25; |
| | | |
| | | // 6. æ·»å æ°æ®è¡ |
| | | data.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, |
| | | ], |
| | | rowIndex + 4 |
| | | ); |
| | | |
| | | // åºç¨æ°æ®è¡æ ·å¼ |
| | | dataRow.eachCell((cell) => { |
| | | cell.style = cellStyle; |
| | | }); |
| | | dataRow.height = 24; |
| | | }); |
| | | |
| | | // 7. æ·»å åè®¡è¡ |
| | | const summaries = this.getFirstFollowUpSummaries(data); |
| | | const summaryRow = worksheet.addRow(summaries); |
| | | summaryRow.eachCell((cell, colNumber) => { |
| | | cell.style = summaryStyle; |
| | | if (colNumber === 1) { |
| | | cell.value = "å计"; |
| | | } |
| | | }); |
| | | summaryRow.height = 28; |
| | | |
| | | // 8. 设置å宽 |
| | | 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 }, // 微信 |
| | | ]; |
| | | }, |
| | | |
| | | /** 馿¬¡éè®¿æ°æ®å计è¡è®¡ç® */ |
| | | getFirstFollowUpSummaries(data) { |
| | | const summaries = [ |
| | | "å计", |
| | | "/", |
| | | "/", |
| | | 0, |
| | | 0, |
| | | 0, |
| | | 0, |
| | | 0, |
| | | 0, |
| | | 0, |
| | | "0%", |
| | | "0%", |
| | | 0, |
| | | 0, |
| | | 0, |
| | | ]; |
| | | |
| | | data.forEach((item) => { |
| | | // æ°å¼å段æ±å |
| | | summaries[3] += Number(item.dischargeCount) || 0; |
| | | summaries[4] += Number(item.nonFollowUp) || 0; |
| | | summaries[5] += Number(item.followUpNeeded) || 0; |
| | | summaries[6] += Number(item.needFollowUp) || 0; |
| | | summaries[7] += Number(item.pendingFollowUp) || 0; |
| | | summaries[8] += Number(item.followUpSuccess) || 0; |
| | | summaries[9] += Number(item.followUpFail) || 0; |
| | | summaries[12] += Number(item.manual) || 0; |
| | | summaries[13] += Number(item.sms) || 0; |
| | | summaries[14] += Number(item.weChat) || 0; |
| | | }); |
| | | |
| | | // 计ç®ç¾åæ¯å段çå¹³åå¼ |
| | | const followUpRateValues = data |
| | | .map((item) => this.extractPercentageValue(item.followUpRate)) |
| | | .filter((value) => value !== null); |
| | | |
| | | const rateValues = data |
| | | .map((item) => this.extractPercentageValue(item.rate)) |
| | | .filter((value) => value !== null); |
| | | |
| | | if (followUpRateValues.length > 0) { |
| | | const avgFollowUpRate = |
| | | followUpRateValues.reduce((sum, val) => sum + val, 0) / |
| | | followUpRateValues.length; |
| | | summaries[10] = (avgFollowUpRate * 100).toFixed(2) + "%"; |
| | | } |
| | | |
| | | if (rateValues.length > 0) { |
| | | const avgRate = |
| | | rateValues.reduce((sum, val) => sum + val, 0) / rateValues.length; |
| | | summaries[11] = (avgRate * 100).toFixed(2) + "%"; |
| | | } |
| | | |
| | | // æ ¼å¼åæ°å |
| | | 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[12] = this.formatNumber(summaries[12]); |
| | | summaries[13] = this.formatNumber(summaries[13]); |
| | | summaries[14] = this.formatNumber(summaries[14]); |
| | | |
| | | return summaries; |
| | | }, |
| | | |
| | | /** æå»ºå次é访导åºè¡¨æ ¼ */ |
| | | buildSecondFollowUpExportSheet(worksheet, data, 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" } }, |
| | | }, |
| | | }; |
| | | |
| | | 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, 15); // åå¹¶A1å°O1 |
| | | const titleCell = worksheet.getCell(1, 1); |
| | | titleCell.value = `忬¡åºé¢é访ç»è®¡è¡¨_${sheetNameSuffix}`; |
| | | titleCell.style = titleStyle; |
| | | worksheet.getRow(1).height = 35; |
| | | |
| | | // 2. å建表头 |
| | | const secondRowHeaders = [ |
| | | "", // A2 å±å¼åå ä½ |
| | | "åºé¢ç
åº", |
| | | "ç§å®¤", |
| | | "åºé¢äººæ¬¡", |
| | | "æ éé访人次", |
| | | "åºé访人次", // B2 to F2 |
| | | // 忬¡åºé¢é访å表头 |
| | | "éé访", |
| | | "å¾
é访", |
| | | "é访æå", |
| | | "é访失败", |
| | | "é访ç", |
| | | "人工", |
| | | "çä¿¡", |
| | | "微信", |
| | | ]; |
| | | |
| | | // æ·»å 第äºè¡ |
| | | secondRowHeaders.forEach((header, index) => { |
| | | const cell = worksheet.getCell(3, index + 1); |
| | | cell.value = header; |
| | | cell.style = headerStyle; |
| | | }); |
| | | |
| | | // 3. åå¹¶åå
æ ¼ |
| | | // åå¹¶ A2:A3, B2:B3, C2:C3, D2:D3, E2:E3, F2:F3 |
| | | for (let i = 1; i <= 6; i++) { |
| | | 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 = "åºé访人次"; |
| | | |
| | | // 4. åå¹¶"忬¡åºé¢é访"æ é¢ |
| | | worksheet.mergeCells(2, 7, 2, 14); // G2:N2 |
| | | worksheet.getCell(2, 7).value = "忬¡åºé¢é访"; |
| | | worksheet.getCell(2, 7).style = headerStyle; |
| | | |
| | | // 5. 设置è¡é« |
| | | worksheet.getRow(2).height = 28; |
| | | worksheet.getRow(3).height = 25; |
| | | |
| | | // 6. æ·»å æ°æ®è¡ |
| | | data.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 |
| | | ); |
| | | |
| | | // åºç¨æ°æ®è¡æ ·å¼ |
| | | dataRow.eachCell((cell) => { |
| | | cell.style = cellStyle; |
| | | }); |
| | | dataRow.height = 24; |
| | | }); |
| | | |
| | | // 7. æ·»å åè®¡è¡ |
| | | const summaries = this.getSecondFollowUpSummaries(data); |
| | | const summaryRow = worksheet.addRow(summaries); |
| | | summaryRow.eachCell((cell, colNumber) => { |
| | | cell.style = summaryStyle; |
| | | if (colNumber === 1) { |
| | | cell.value = "å计"; |
| | | } |
| | | }); |
| | | summaryRow.height = 28; |
| | | |
| | | // 8. 设置å宽 |
| | | 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 }, // 微信 |
| | | ]; |
| | | }, |
| | | |
| | | /** 忬¡éè®¿æ°æ®å计è¡è®¡ç® */ |
| | | getSecondFollowUpSummaries(data) { |
| | | const summaries = ["å计", "/", "/", 0, 0, 0, 0, 0, 0, 0, "0%", 0, 0, 0]; |
| | | |
| | | data.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; |
| | | }); |
| | | |
| | | // 计ç®é访çç¾åæ¯å段çå¹³åå¼ |
| | | const followUpRateAgainValues = data |
| | | .map((item) => this.extractPercentageValue(item.followUpRateAgain)) |
| | | .filter((value) => value !== null); |
| | | |
| | | if (followUpRateAgainValues.length > 0) { |
| | | const avgFollowUpRateAgain = |
| | | followUpRateAgainValues.reduce((sum, val) => sum + val, 0) / |
| | | followUpRateAgainValues.length; |
| | | summaries[10] = (avgFollowUpRateAgain * 100).toFixed(2) + "%"; |
| | | } |
| | | |
| | | // æ ¼å¼åæ°å |
| | | 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]); |
| | | |
| | | return summaries; |
| | | }, |
| | | |
| | | /** 忬¡éè®¿è¡¨æ ¼çå计è¡è®¡ç®æ¹æ³ */ |
| | | getSummariesSecond(param) { |
| | | const { columns, data } = param; |
| | | const sums = []; |
| | | |
| | | columns.forEach((column, index) => { |
| | | if (index === 0) { |
| | | sums[index] = "å计"; |
| | | return; |
| | | } |
| | | if (index === 1 || index === 2) { |
| | | sums[index] = "/"; |
| | | return; |
| | | } |
| | | |
| | | if (column.property === "followUpRateAgain") { |
| | | const percentageValues = data |
| | | .map((item) => { |
| | | 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; |
| | | } else { |
| | | const numValue = parseFloat(value); |
| | | return isNaN(numValue) ? null : numValue; |
| | | } |
| | | }) |
| | | .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) + "%"; |
| | | } else { |
| | | 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; |
| | | }); |
| | | |
| | | if (!values.every((value) => isNaN(value))) { |
| | | sums[index] = values.reduce((prev, curr) => prev + curr, 0); |
| | | sums[index] = this.formatNumber(sums[index]); |
| | | } else { |
| | | sums[index] = "-"; |
| | | } |
| | | } |
| | | }); |
| | | |
| | | return sums; |
| | | }, |
| | | /** 忬¡é访å
é¨è¡¨æ ¼å计è¡è®¡ç®æ¹æ³ */ |
| | | getInnerSummariesSecond(param) { |
| | | const { columns, data } = param; |
| | | const sums = []; |
| | | |
| | | columns.forEach((column, index) => { |
| | | if (index === 0) { |
| | | sums[index] = "å°è®¡"; |
| | | return; |
| | | } |
| | | |
| | | if (column.property === "drname" || column.property === "deptname") { |
| | | sums[index] = "-"; |
| | | return; |
| | | } |
| | | |
| | | if (column.property === "followUpRateAgain") { |
| | | const percentageValues = data |
| | | .map((item) => { |
| | | 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; |
| | | } else { |
| | | const numValue = parseFloat(value); |
| | | return isNaN(numValue) ? null : numValue; |
| | | } |
| | | }) |
| | | .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) + "%"; |
| | | } else { |
| | | 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; |
| | | }); |
| | | |
| | | if (!values.every((value) => isNaN(value))) { |
| | | sums[index] = values.reduce((prev, curr) => prev + curr, 0); |
| | | sums[index] = this.formatNumber(sums[index]); |
| | | } else { |
| | | sums[index] = "-"; |
| | | } |
| | | } |
| | | }); |
| | | |
| | | return sums; |
| | | }, |
| | | /** 忬¡éè®¿è¡¨æ ¼çè¡ç¹å»å±å¼ */ |
| | | handleRowClickSecond(row) { |
| | | if (this.expandsSecond.includes(this.getRowKey(row))) { |
| | | this.expandsSecond = []; |
| | | return; |
| | | } |
| | | |
| | | const params = { |
| | | ...this.queryParams, |
| | | deptcodes: this.queryParams.deptcodes.includes("all") |
| | | ? this.allDeptCodes |
| | | : this.queryParams.deptcodes, |
| | | leavehospitaldistrictcodes: [row.leavehospitaldistrictcode], |
| | | drcode: "1", |
| | | visitCount: 2, // è®¾ç½®ä¸ºåæ¬¡é访 |
| | | }; |
| | | |
| | | delete params.leavehospitaldistrictcodes.all; |
| | | delete params.deptcodes.all; |
| | | |
| | | if (!row.doctorStats) { |
| | | this.loadingSecond = true; |
| | | getSfStatistics(params).then((res) => { |
| | | this.$set(row, "doctorStats", res.data); |
| | | this.expandsSecond = [this.getRowKey(row)]; |
| | | this.loadingSecond = false; |
| | | }); |
| | | } else { |
| | | this.expandsSecond = [this.getRowKey(row)]; |
| | | } |
| | | }, |
| | | |
| | | /** 忬¡éè®¿è¡¨æ ¼çå¤éæ¡é䏿°æ® */ |
| | | handleSelectionChangeSecond(selection) { |
| | | this.idsSecond = selection.map((item) => item.tagid); |
| | | this.single = selection.length != 1; |
| | | this.multiple = !selection.length; |
| | | }, |
| | | // æ¾ç¤ºå¾è¡¨å¼¹çª |
| | | |
| | | showChartDialog() { |
| | | this.chartDialogVisible = true; |
| | | this.$nextTick(() => { |
| | | this.initPieChart(); |
| | | this.initBarLineChart(); |
| | | }); |
| | | }, |
| | | // å¨methodsä¸ä¿®æ¹ç»è®¡æ¹æ³ |
| | | showChartDialog() { |
| | | this.chartDialogVisible = true; |
| | | this.$nextTick(() => { |
| | | console.log(this.userList, "this.userList"); |
| | | |
| | | this.initCharts(); |
| | | }); |
| | | }, |
| | | |
| | | // æ°å¢åå§åå¾è¡¨æ¹æ³ |
| | | initCharts() { |
| | | this.initPieChart(); |
| | | this.initBarLineChart(); |
| | | }, |
| | | |
| | | // åå§åé¥¼å¾ |
| | | initPieChart() { |
| | | const echarts = require("echarts"); |
| | | const pieDom = document.getElementById("pieChart"); |
| | | if (!pieDom) return; |
| | | |
| | | if (this.pieChart) { |
| | | this.pieChart.dispose(); |
| | | } |
| | | |
| | | this.pieChart = echarts.init(pieDom); |
| | | |
| | | // 计ç®é¥¼å¾æ°æ® |
| | | const followUpData = { |
| | | pending: 0, |
| | | success: 0, |
| | | fail: 0, |
| | | }; |
| | | |
| | | this.userList.forEach((item) => { |
| | | followUpData.pending += item.pendingFollowUp || 0; |
| | | followUpData.success += item.followUpSuccess || 0; |
| | | followUpData.fail += item.followUpFail || 0; |
| | | }); |
| | | |
| | | // ä½¿ç¨æ´ç¾è§çé¢è²æ¹æ¡ |
| | | const pieOption = { |
| | | title: { |
| | | text: "éè®¿ç¶æåå¸", |
| | | left: "center", |
| | | textStyle: { |
| | | color: "#333", |
| | | fontSize: 16, |
| | | }, |
| | | }, |
| | | tooltip: { |
| | | trigger: "item", |
| | | formatter: "{a} <br/>{b}: {c} ({d}%)", |
| | | }, |
| | | legend: { |
| | | orient: "vertical", |
| | | left: "left", |
| | | data: ["å¾
é访", "é访æå", "é访失败"], |
| | | textStyle: { |
| | | color: "#666", |
| | | }, |
| | | }, |
| | | color: ["#FF9D4D", "#36B37E", "#FF5C5C"], // æ°çé
è²æ¹æ¡ |
| | | series: [ |
| | | { |
| | | name: "éè®¿ç¶æ", |
| | | type: "pie", |
| | | radius: ["40%", "70%"], |
| | | avoidLabelOverlap: true, |
| | | itemStyle: { |
| | | borderRadius: 10, |
| | | borderColor: "#fff", |
| | | borderWidth: 2, |
| | | }, |
| | | label: { |
| | | show: true, |
| | | formatter: "{b}: {c} ({d}%)", |
| | | color: "#333", |
| | | }, |
| | | emphasis: { |
| | | label: { |
| | | show: true, |
| | | fontSize: "18", |
| | | fontWeight: "bold", |
| | | }, |
| | | itemStyle: { |
| | | shadowBlur: 10, |
| | | shadowOffsetX: 0, |
| | | shadowColor: "rgba(0, 0, 0, 0.5)", |
| | | }, |
| | | }, |
| | | data: [ |
| | | { |
| | | value: followUpData.pending, |
| | | name: "å¾
é访", |
| | | }, |
| | | { |
| | | value: followUpData.success, |
| | | name: "é访æå", |
| | | }, |
| | | { |
| | | value: followUpData.fail, |
| | | name: "é访失败", |
| | | }, |
| | | ], |
| | | }, |
| | | ], |
| | | }; |
| | | |
| | | this.pieChart.setOption(pieOption); |
| | | window.addEventListener("resize", this.resizePieChart); |
| | | }, |
| | | |
| | | // åå§åæ±ç¶æçº¿å¾ |
| | | initBarLineChart() { |
| | | const echarts = require("echarts"); |
| | | const barDom = document.getElementById("barLineChart"); |
| | | if (!barDom) return; |
| | | |
| | | if (this.barLineChart) { |
| | | this.barLineChart.dispose(); |
| | | } |
| | | |
| | | this.barLineChart = echarts.init(barDom); |
| | | |
| | | // å夿°æ® |
| | | const categories = this.userList.map( |
| | | (item) => item.leavehospitaldistrictname || item.deptname |
| | | ); |
| | | |
| | | const dischargeData = this.userList.map( |
| | | (item) => item.dischargeCount || 0 |
| | | ); |
| | | const followUpData = this.userList.map( |
| | | (item) => item.followUpNeeded || 0 |
| | | ); |
| | | |
| | | // æ°å¢ä¸¤æ¡æçº¿æ°æ® |
| | | const followUpRateData = this.userList.map((item) => { |
| | | if (!item.followUpRate) return 0; |
| | | // 廿ç¾åå·å¹¶è½¬ä¸ºæ°å |
| | | const rateStr = String(item.followUpRate).replace("%", ""); |
| | | return parseFloat(rateStr) || 0; |
| | | }); |
| | | |
| | | const timelyRateData = this.userList.map((item) => |
| | | item.rate ? (Number(item.rate) * 100).toFixed(2) : 0 |
| | | ); |
| | | |
| | | const option = { |
| | | title: { |
| | | text: "ç§å®¤/ç
åºé访è¶å¿", |
| | | left: "center", |
| | | textStyle: { |
| | | color: "#333", |
| | | fontSize: 16, |
| | | }, |
| | | }, |
| | | tooltip: { |
| | | trigger: "axis", |
| | | axisPointer: { |
| | | type: "cross", |
| | | crossStyle: { |
| | | color: "#999", |
| | | }, |
| | | }, |
| | | }, |
| | | legend: { |
| | | data: ["åºé¢äººæ¬¡", "åºé访人次", "é访ç(%)", "åæ¶ç(%)"], |
| | | top: "bottom", |
| | | textStyle: { |
| | | color: "#666", |
| | | }, |
| | | }, |
| | | color: ["#5470C6", "#91CC75", "#EE6666", "#9A60B4"], // æ°å¢ç´«è²ç¨äºåæ¶ç |
| | | xAxis: { |
| | | type: "category", |
| | | data: categories, |
| | | axisLabel: { |
| | | interval: 0, |
| | | rotate: 30, |
| | | color: "#666", |
| | | }, |
| | | axisLine: { |
| | | lineStyle: { |
| | | color: "#ddd", |
| | | }, |
| | | }, |
| | | }, |
| | | yAxis: [ |
| | | { |
| | | type: "value", |
| | | name: "人次", |
| | | min: 0, |
| | | axisLabel: { |
| | | color: "#666", |
| | | }, |
| | | axisLine: { |
| | | lineStyle: { |
| | | color: "#ddd", |
| | | }, |
| | | }, |
| | | splitLine: { |
| | | lineStyle: { |
| | | color: "#f0f0f0", |
| | | }, |
| | | }, |
| | | }, |
| | | { |
| | | type: "value", |
| | | name: "ç¾åæ¯(%)", |
| | | min: 0, |
| | | max: 100, |
| | | axisLabel: { |
| | | color: "#666", |
| | | formatter: "{value}%", |
| | | }, |
| | | axisLine: { |
| | | lineStyle: { |
| | | color: "#ddd", |
| | | }, |
| | | }, |
| | | splitLine: { |
| | | show: false, |
| | | }, |
| | | }, |
| | | ], |
| | | series: [ |
| | | { |
| | | name: "åºé¢äººæ¬¡", |
| | | type: "bar", |
| | | barWidth: "25%", |
| | | data: dischargeData, |
| | | itemStyle: { |
| | | borderRadius: [4, 4, 0, 0], |
| | | }, |
| | | }, |
| | | { |
| | | name: "åºé访人次", |
| | | type: "bar", |
| | | barWidth: "25%", |
| | | data: followUpData, |
| | | itemStyle: { |
| | | borderRadius: [4, 4, 0, 0], |
| | | }, |
| | | }, |
| | | { |
| | | name: "é访ç(%)", |
| | | type: "line", |
| | | yAxisIndex: 1, |
| | | data: followUpRateData, |
| | | symbolSize: 8, |
| | | lineStyle: { |
| | | width: 3, |
| | | }, |
| | | markLine: { |
| | | silent: true, |
| | | data: [ |
| | | { |
| | | yAxis: 80, |
| | | lineStyle: { |
| | | color: "#EE6666", |
| | | type: "dashed", |
| | | }, |
| | | // label: { |
| | | // position: 'end', |
| | | // formatter: 'ç®æ 80%' |
| | | // } |
| | | }, |
| | | ], |
| | | }, |
| | | }, |
| | | { |
| | | name: "åæ¶ç(%)", |
| | | type: "line", |
| | | yAxisIndex: 1, |
| | | data: timelyRateData, |
| | | symbolSize: 8, |
| | | lineStyle: { |
| | | width: 3, |
| | | type: "dotted", // 使ç¨è线åºå |
| | | }, |
| | | markLine: { |
| | | silent: true, |
| | | data: [ |
| | | { |
| | | yAxis: 90, |
| | | lineStyle: { |
| | | color: "#9A60B4", |
| | | type: "dashed", |
| | | }, |
| | | // label: { |
| | | // position: 'end', |
| | | // formatter: 'ç®æ 90%' |
| | | // } |
| | | }, |
| | | ], |
| | | }, |
| | | }, |
| | | ], |
| | | grid: { |
| | | top: "15%", |
| | | left: "3%", |
| | | right: "4%", |
| | | bottom: "15%", |
| | | containLabel: true, |
| | | }, |
| | | }; |
| | | |
| | | this.barLineChart.setOption(option); |
| | | window.addEventListener("resize", this.resizeBarLineChart); |
| | | }, |
| | | |
| | | // å¾è¡¨ååºå¼è°æ´æ¹æ³ |
| | | resizePieChart() { |
| | | if (this.pieChart) { |
| | | this.pieChart.resize(); |
| | | } |
| | | }, |
| | | |
| | | resizeBarLineChart() { |
| | | if (this.barLineChart) { |
| | | this.barLineChart.resize(); |
| | | } |
| | | }, |
| | | |
| | | // å¨ç»ä»¶éæ¯æ¶æ¸
ç |
| | | beforeDestroy() { |
| | | // ç§»é¤äºä»¶çå¬ |
| | | window.removeEventListener("resize", this.resizePieChart); |
| | | window.removeEventListener("resize", this.resizeBarLineChart); |
| | | |
| | | // 鿝å¾è¡¨å®ä¾ |
| | | if (this.pieChart) { |
| | | this.pieChart.dispose(); |
| | | this.pieChart = null; |
| | | } |
| | | if (this.barLineChart) { |
| | | this.barLineChart.dispose(); |
| | | this.barLineChart = null; |
| | | } |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | ::v-deep .el-tabs__header { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | ::v-deep .el-tabs__item { |
| | | font-size: 16px; |
| | | padding: 0 20px; |
| | | height: 40px; |
| | | line-height: 40px; |
| | | } |
| | | |
| | | ::v-deep .el-tabs__active-bar { |
| | | height: 3px; |
| | | } |
| | | |
| | | /* Tabå
容åºåæ ·å¼ */ |
| | | .el-tab-pane { |
| | | .your-table-container { |
| | | margin-top: 10px; |
| | | } |
| | | } |
| | | |
| | | .sidecolumn { |
| | | width: 180px; |
| | | min-height: 100vh; |
| | | text-align: center; |
| | | // display: flex; |
| | | margin-top: 20px; |
| | | margin: 20px; |
| | | padding: 30px; |
| | | background: #edf1f7; |
| | | border: 1px solid #dcdfe6; |
| | | -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), |
| | | 0 0 6px 0 rgba(0, 0, 0, 0.04); |
| | | |
| | | .sidecolumn-top { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | |
| | | .top-wj { |
| | | font-size: 20px; |
| | | } |
| | | |
| | | .top-tj { |
| | | font-size: 18px; |
| | | |
| | | color: rgb(0, 89, 255); |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | |
| | | .center-ss { |
| | | margin-top: 30px; |
| | | |
| | | .input-with-select { |
| | | height: 40px !important; |
| | | } |
| | | } |
| | | |
| | | .bottom-fl { |
| | | margin-top: 30px; |
| | | display: center !important; |
| | | } |
| | | } |
| | | |
| | | .qrcode-dialo { |
| | | text-align: center; |
| | | // display: flex; |
| | | margin: 20px; |
| | | padding: 30px; |
| | | background: #edf1f7; |
| | | border: 1px solid #dcdfe6; |
| | | -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), |
| | | 0 0 6px 0 rgba(0, 0, 0, 0.04); |
| | | |
| | | .qrcode-text { |
| | | font-size: 20px; |
| | | |
| | | span { |
| | | margin-left: 20px; |
| | | } |
| | | } |
| | | |
| | | .qrcode-img { |
| | | width: 300px; |
| | | height: 400px; |
| | | } |
| | | } |
| | | |
| | | ::v-deep.el-tabs--left, |
| | | .el-tabs--right { |
| | | overflow: hidden; |
| | | align-items: center; |
| | | display: flex; |
| | | } |
| | | |
| | | ::v-deep.el-input--medium .el-input__inner { |
| | | height: 40px !important; |
| | | } |
| | | |
| | | ::v-deep.el-tabs--right .el-tabs__active-bar.is-right { |
| | | height: 40px; |
| | | width: 5px; |
| | | left: 0; |
| | | } |
| | | |
| | | ::v-deep.el-tabs--right .el-tabs__item.is-right { |
| | | display: block; |
| | | text-align: left; |
| | | font-size: 20px; |
| | | } |
| | | |
| | | // ç¾ååè®¡è¡æ ·å¼ |
| | | ::v-deep .el-table__footer { |
| | | .el-table__cell { |
| | | background-color: #f5f7fa; |
| | | font-weight: 600; |
| | | color: #409eff; |
| | | |
| | | .cell { |
| | | font-weight: 600; |
| | | color: #409eff; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // å
é¨è¡¨æ ¼åè®¡è¡æ ·å¼ |
| | | ::v-deep .inner-table .el-table__footer { |
| | | .el-table__cell { |
| | | background-color: #ecf5ff; |
| | | font-weight: 500; |
| | | color: #67c23a; |
| | | |
| | | .cell { |
| | | font-weight: 500; |
| | | color: #67c23a; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // ç¾åæ¯åæ®µç¹æ®æ ·å¼ |
| | | .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; |
| | | } |
| | | |
| | | .leftvlue { |
| | | // display: flex; |
| | | // flex: 1; |
| | | // width: 80%; |
| | | // margin-top: 20px; |
| | | margin: 20px; |
| | | padding: 30px; |
| | | background: #ffff; |
| | | border: 1px solid #dcdfe6; |
| | | -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), |
| | | 0 0 6px 0 rgba(0, 0, 0, 0.04); |
| | | |
| | | .mulsz { |
| | | font-size: 20px; |
| | | } |
| | | } |
| | | |
| | | /* ä½¿è¡ææåæé */ |
| | | .el-table__row { |
| | | cursor: pointer; |
| | | } |
| | | |
| | | /* å
å±å»çè¡¨æ ¼æ ·å¼ */ |
| | | .inner-table { |
| | | |
| | | // è¡¨å¤´èæ¯è² |
| | | ::v-deep .el-table__header-wrapper { |
| | | background-color: #f0f7ff !important; |
| | | |
| | | th { |
| | | background-color: #f0f7ff !important; |
| | | } |
| | | } |
| | | |
| | | // è¡¨æ ¼è¡èæ¯è² |
| | | ::v-deep .el-table__body-wrapper { |
| | | tr { |
| | | background-color: #f9fbfe !important; |
| | | |
| | | &:hover { |
| | | background-color: #e6f1ff !important; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // è¾¹æ¡é¢è² |
| | | ::v-deep .el-table--border { |
| | | border-color: #d9e8ff !important; |
| | | |
| | | td, |
| | | th { |
| | | border-color: #d9e8ff !important; |
| | | } |
| | | } |
| | | |
| | | // æé©¬çº¹ææ |
| | | ::v-deep .el-table--striped .el-table__body tr.el-table__row--striped td { |
| | | background-color: #f5f9ff !important; |
| | | } |
| | | } |
| | | |
| | | /* å±å¼è¡æ ·å¼ */ |
| | | .el-table__expanded-cell { |
| | | padding: 10px 0 !important; |
| | | background: #f8f8f8; |
| | | } |
| | | |
| | | .document { |
| | | width: 100px; |
| | | height: 50px; |
| | | } |
| | | |
| | | .data-list { |
| | | max-height: 800px; |
| | | overflow-y: auto; |
| | | } |
| | | |
| | | .documentf { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | } |
| | | |
| | | .button-text { |
| | | color: rgb(70, 204, 238); |
| | | } |
| | | |
| | | .button-textck { |
| | | color: rgb(39, 167, 67); |
| | | } |
| | | |
| | | .button-textxg { |
| | | color: rgb(35, 81, 233); |
| | | } |
| | | |
| | | .button-textsc { |
| | | color: rgb(235, 23, 23); |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div class="Questionnairemanagement"> |
| | | <div class="leftvlue"> |
| | | <div class="leftvlue-bg"> |
| | | <el-row :gutter="20"> |
| | | <!--æ ç¾æ°æ®--> |
| | | <el-col :span="24" :xs="24"> |
| | | <el-form |
| | | :model="queryParams" |
| | | ref="queryForm" |
| | | size="small" |
| | | :inline="true" |
| | | v-show="showSearch" |
| | | label-width="98px" |
| | | > |
| | | <el-form-item label="ç»è®¡ç±»å" prop="userName"> |
| | | <el-select |
| | | v-model="queryParams.statisticaltype" |
| | | placeholder="è¯·éæ©ç»è®¡ç±»å" |
| | | > |
| | | <el-option |
| | | v-for="item in Statisticallist" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | > |
| | | </el-option> |
| | | </el-select> |
| | | <el-select |
| | | style="margin-left: 10px" |
| | | v-if="queryParams.statisticaltype == 1" |
| | | v-model="queryParams.leavehospitaldistrictcodes" |
| | | size="medium" |
| | | multiple |
| | | filterable |
| | | placeholder="è¯·éæ©ç
åº" |
| | | > |
| | | <el-option |
| | | v-for="item in flatArrayhospit" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | > |
| | | </el-option> |
| | | </el-select> |
| | | <el-select |
| | | v-else-if="queryParams.statisticaltype == 2" |
| | | v-model="queryParams.deptcodes" |
| | | size="medium" |
| | | multiple |
| | | filterable |
| | | placeholder="è¯·éæ©ç§å®¤" |
| | | > |
| | | <el-option |
| | | v-for="item in flatArraydept" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | > |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <div class="follow-up-statistics"> |
| | | <!-- æç´¢è¡¨ååºå --> |
| | | <div class="search-section"> |
| | | <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="98px"> |
| | | <el-form-item label="ç»è®¡ç±»å" prop="userName"> |
| | | <el-select v-model="queryParams.statisticaltype" placeholder="è¯·éæ©ç»è®¡ç±»å"> |
| | | <el-option v-for="item in Statisticallist" :key="item.value" :label="item.label" :value="item.value" /> |
| | | </el-select> |
| | | <el-select |
| | | style="margin-left: 10px" |
| | | v-if="queryParams.statisticaltype == 1" |
| | | v-model="queryParams.leavehospitaldistrictcodes" |
| | | size="medium" |
| | | multiple |
| | | filterable |
| | | placeholder="è¯·éæ©ç
åº" |
| | | > |
| | | <el-option v-for="item in flatArrayhospit" :key="item.value" :label="item.label" :value="item.value" /> |
| | | </el-select> |
| | | <el-select |
| | | v-else-if="queryParams.statisticaltype == 2" |
| | | v-model="queryParams.deptcodes" |
| | | size="medium" |
| | | multiple |
| | | filterable |
| | | placeholder="è¯·éæ©ç§å®¤" |
| | | > |
| | | <el-option v-for="item in flatArraydept" :key="item.value" :label="item.label" :value="item.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="æå¡ç±»å" prop="userName"> |
| | | <el-select |
| | | v-model="queryParams.serviceType" |
| | | multiple |
| | | placeholder="è¯·éæ©" |
| | | > |
| | | <el-option |
| | | v-for="item in options" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | > |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item |
| | | label-width="200" |
| | | label="åºé访æ¶é´èå´" |
| | | prop="userName" |
| | | > |
| | | <el-date-picker |
| | | v-model="queryParams.dateRange" |
| | | 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> |
| | | <el-form-item label="æå¡ç±»å" prop="userName"> |
| | | <el-select v-model="queryParams.serviceType" multiple placeholder="è¯·éæ©"> |
| | | <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | | icon="el-icon-search" |
| | | size="medium" |
| | | @click="handleQuery" |
| | | >æç´¢</el-button |
| | | > |
| | | <el-button |
| | | icon="el-icon-refresh" |
| | | size="medium" |
| | | @click="resetQuery" |
| | | >éç½®</el-button |
| | | > |
| | | </el-form-item> |
| | | <el-button |
| | | type="warning" |
| | | plain |
| | | icon="el-icon-download" |
| | | size="medium" |
| | | @click="exportTable" |
| | | >导åº</el-button |
| | | > |
| | | <el-button |
| | | type="primary" |
| | | plain |
| | | icon="el-icon-data-line" |
| | | size="medium" |
| | | @click="showChartDialog" |
| | | >ç»è®¡è¶å¿å¾</el-button |
| | | > |
| | | </el-form> |
| | | |
| | | <!-- æ°å¢ï¼Tabæ ç¾é¡µ --> |
| | | <el-tabs v-model="activeTab" @tab-click="handleTabClick"> |
| | | <el-tab-pane label="馿¬¡é访" name="first"> |
| | | <div class="your-table-container"> |
| | | <el-table |
| | | ref="exportTable" |
| | | id="exportTableid" |
| | | v-loading="loading" |
| | | :data="firstFollowUpList" |
| | | :border="true" |
| | | @selection-change="handleSelectionChange" |
| | | @expand-change="handleRowClick" |
| | | :row-key="getRowKey" |
| | | show-summary |
| | | :summary-method="getSummaries" |
| | | :expand-row-keys="expands" |
| | | > |
| | | <!-- å±å¼è¡ç®å¤´å --> |
| | | <el-table-column type="expand"> |
| | | <template slot-scope="props"> |
| | | <el-table |
| | | :data="props.row.doctorStats" |
| | | border |
| | | style="width: 95%; margin: 0 auto" |
| | | class="inner-table" |
| | | show-summary |
| | | :summary-method="getInnerSummaries" |
| | | > |
| | | <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" |
| | | key="dischargeCount" |
| | | prop="dischargeCount" |
| | | > |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="æ éé访人次" |
| | | align="center" |
| | | width="100" |
| | | key="nonFollowUp" |
| | | prop="nonFollowUp" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="åºé访人次" |
| | | align="center" |
| | | width="100" |
| | | key="followUpNeeded" |
| | | prop="followUpNeeded" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column align="center" label="馿¬¡åºé¢é访"> |
| | | <el-table-column |
| | | label="éé访" |
| | | align="center" |
| | | key="needFollowUp" |
| | | prop="needFollowUp" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="å¾
é访" |
| | | align="center" |
| | | key="pendingFollowUp" |
| | | prop="pendingFollowUp" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="é访æå" |
| | | align="center" |
| | | key="followUpSuccess" |
| | | prop="followUpSuccess" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="é访失败" |
| | | align="center" |
| | | key="followUpFail" |
| | | prop="followUpFail" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="é访ç" |
| | | align="center" |
| | | width="120" |
| | | key="followUpRate" |
| | | prop="followUpRate" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | v-if="orgname != '丽水å¸ä¸å»é¢'" |
| | | label="åæ¶ç" |
| | | align="center" |
| | | width="120" |
| | | key="rate" |
| | | prop="rate" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="medium" |
| | | type="text" |
| | | @click="Seedetails(scope.row)" |
| | | ><span class="button-zx" |
| | | >{{ |
| | | (Number(scope.row.rate) * 100).toFixed(2) |
| | | }}%</span |
| | | ></el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="人工" |
| | | align="center" |
| | | key="manual" |
| | | prop="manual" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="çä¿¡" |
| | | align="center" |
| | | key="sms" |
| | | prop="sms" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="微信" |
| | | align="center" |
| | | key="weChat" |
| | | prop="weChat" |
| | | > |
| | | </el-table-column> |
| | | </el-table-column> |
| | | </el-table> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="åºé¢ç
åº" |
| | | align="center" |
| | | sortable |
| | | key="leavehospitaldistrictname" |
| | | prop="leavehospitaldistrictname" |
| | | width="150" |
| | | :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> |
| | | |
| | | <el-table-column |
| | | label="æ éé访人次" |
| | | align="center" |
| | | width="100" |
| | | key="nonFollowUp" |
| | | prop="nonFollowUp" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="åºé访人次" |
| | | align="center" |
| | | width="100" |
| | | key="followUpNeeded" |
| | | prop="followUpNeeded" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column align="center" label="馿¬¡åºé¢é访"> |
| | | <el-table-column |
| | | label="éé访" |
| | | align="center" |
| | | key="needFollowUp" |
| | | prop="needFollowUp" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="medium" |
| | | type="text" |
| | | @click=" |
| | | viewDetails( |
| | | scope.row.needFollowUpInfo, |
| | | scope.row.leavehospitaldistrictname + |
| | | 'éé访å表' |
| | | ) |
| | | " |
| | | ><span class="button-zx">{{ |
| | | scope.row.needFollowUp |
| | | }}</span></el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="å¾
é访" |
| | | align="center" |
| | | 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="é访æå" |
| | | align="center" |
| | | key="followUpSuccess" |
| | | prop="followUpSuccess" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="medium" |
| | | type="text" |
| | | @click=" |
| | | viewDetails( |
| | | scope.row.followUpSuccessInfo, |
| | | scope.row.leavehospitaldistrictname + |
| | | 'é访æåå表' |
| | | ) |
| | | " |
| | | ><span class="button-zx">{{ |
| | | scope.row.followUpSuccess |
| | | }}</span></el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="é访失败" |
| | | align="center" |
| | | 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="é访ç" |
| | | align="center" |
| | | width="120" |
| | | key="followUpRate" |
| | | prop="followUpRate" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | v-if="orgname != '丽水å¸ä¸å»é¢'" |
| | | label="åæ¶ç" |
| | | align="center" |
| | | width="120" |
| | | key="rate" |
| | | prop="rate" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="medium" |
| | | type="text" |
| | | @click="Seedetails(scope.row)" |
| | | ><span class="button-zx" |
| | | >{{ |
| | | (Number(scope.row.rate) * 100).toFixed(2) |
| | | }}%</span |
| | | ></el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="人工" |
| | | align="center" |
| | | key="manual" |
| | | prop="manual" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="medium" |
| | | type="text" |
| | | @click=" |
| | | viewDetails( |
| | | scope.row.manualInfo, |
| | | scope.row.leavehospitaldistrictname + |
| | | '人工é访å表' |
| | | ) |
| | | " |
| | | ><span class="button-zx">{{ |
| | | scope.row.manual |
| | | }}</span></el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="çä¿¡" |
| | | align="center" |
| | | key="sms" |
| | | prop="sms" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="medium" |
| | | type="text" |
| | | @click=" |
| | | viewDetails( |
| | | scope.row.smsInfo, |
| | | scope.row.leavehospitaldistrictname + |
| | | 'çä¿¡é访å表' |
| | | ) |
| | | " |
| | | ><span class="button-zx">{{ |
| | | scope.row.sms |
| | | }}</span></el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="微信" |
| | | align="center" |
| | | key="weChat" |
| | | prop="weChat" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="medium" |
| | | type="text" |
| | | @click=" |
| | | viewDetails( |
| | | scope.row.weChatInfo, |
| | | scope.row.leavehospitaldistrictname + |
| | | '微信é访å表' |
| | | ) |
| | | " |
| | | ><span class="button-zx">{{ |
| | | scope.row.weChat |
| | | }}</span></el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | </el-table-column> |
| | | |
| | | <!-- é访æ
åµåï¼ä»
丽水å¸ä¸å»é¢æ¾ç¤ºï¼ --> |
| | | <el-table-column |
| | | v-if="orgname == '丽水å¸ä¸å»é¢'" |
| | | align="center" |
| | | label="é访æ
åµ" |
| | | > |
| | | <el-table-column |
| | | label="æ£å¸¸è¯é³" |
| | | align="center" |
| | | width="100" |
| | | key="taskSituation1" |
| | | prop="taskSituation1" |
| | | > |
| | | </el-table-column |
| | | ><el-table-column |
| | | label="æ£è
ææ¥ææè®¿" |
| | | align="center" |
| | | width="100" |
| | | key="taskSituation2" |
| | | prop="taskSituation2" |
| | | > |
| | | </el-table-column |
| | | ><el-table-column |
| | | label="é¢è®¿æè
æ¥è¯" |
| | | align="center" |
| | | width="100" |
| | | key="taskSituation3" |
| | | prop="taskSituation3" |
| | | > |
| | | </el-table-column |
| | | ><el-table-column |
| | | label="微信é访" |
| | | align="center" |
| | | width="100" |
| | | key="taskSituation4" |
| | | prop="taskSituation4" |
| | | > |
| | | </el-table-column |
| | | ><el-table-column |
| | | label="é访çµè¯ä¸æ£ç¡®" |
| | | align="center" |
| | | width="100" |
| | | key="taskSituation5" |
| | | prop="taskSituation5" |
| | | > |
| | | </el-table-column |
| | | ><el-table-column |
| | | label="å
¶ä»æ
åµä¸å®é访" |
| | | align="center" |
| | | width="100" |
| | | key="taskSituation6" |
| | | prop="taskSituation6" |
| | | > |
| | | </el-table-column> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </el-tab-pane> |
| | | |
| | | <el-tab-pane label="忬¡é访" name="second"> |
| | | <div class="your-table-container"> |
| | | <el-table |
| | | ref="exportTableSecond" |
| | | id="exportTableidSecond" |
| | | v-loading="loadingSecond" |
| | | :data="secondFollowUpList" |
| | | :border="true" |
| | | @selection-change="handleSelectionChangeSecond" |
| | | @expand-change="handleRowClickSecond" |
| | | :row-key="getRowKey" |
| | | show-summary |
| | | :summary-method="getSummariesSecond" |
| | | :expand-row-keys="expandsSecond" |
| | | > |
| | | <!-- å±å¼è¡ç®å¤´å --> |
| | | <el-table-column type="expand"> |
| | | <template slot-scope="props"> |
| | | <el-table |
| | | :data="props.row.doctorStats" |
| | | border |
| | | style="width: 95%; margin: 0 auto" |
| | | class="inner-table" |
| | | show-summary |
| | | :summary-method="getInnerSummariesSecond" |
| | | > |
| | | <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" |
| | | key="dischargeCount" |
| | | prop="dischargeCount" |
| | | > |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="æ éé访人次" |
| | | align="center" |
| | | width="100" |
| | | key="nonFollowUp" |
| | | prop="nonFollowUp" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="åºé访人次" |
| | | align="center" |
| | | width="100" |
| | | key="followUpNeeded" |
| | | prop="followUpNeeded" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column align="center" label="忬¡åºé¢é访"> |
| | | <el-table-column |
| | | label="éé访" |
| | | align="center" |
| | | key="needFollowUpAgain" |
| | | prop="needFollowUpAgain" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="å¾
é访" |
| | | align="center" |
| | | key="pendingFollowUpAgain" |
| | | prop="pendingFollowUpAgain" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="é访æå" |
| | | align="center" |
| | | key="followUpSuccessAgain" |
| | | prop="followUpSuccessAgain" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="é访失败" |
| | | align="center" |
| | | key="followUpFailAgain" |
| | | prop="followUpFailAgain" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="é访ç" |
| | | align="center" |
| | | width="120" |
| | | key="followUpRateAgain" |
| | | prop="followUpRateAgain" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="人工" |
| | | align="center" |
| | | key="manualAgain" |
| | | prop="manualAgain" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="çä¿¡" |
| | | align="center" |
| | | key="smsAgain" |
| | | prop="smsAgain" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="微信" |
| | | align="center" |
| | | key="weChatAgain" |
| | | prop="weChatAgain" |
| | | > |
| | | </el-table-column> |
| | | </el-table-column> |
| | | </el-table> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="åºé¢ç
åº" |
| | | align="center" |
| | | sortable |
| | | key="leavehospitaldistrictname" |
| | | prop="leavehospitaldistrictname" |
| | | width="150" |
| | | :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> |
| | | |
| | | <el-table-column |
| | | label="æ éé访人次" |
| | | align="center" |
| | | width="100" |
| | | key="nonFollowUp" |
| | | prop="nonFollowUp" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="åºé访人次" |
| | | align="center" |
| | | width="100" |
| | | key="followUpNeeded" |
| | | prop="followUpNeeded" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column align="center" label="忬¡åºé¢é访"> |
| | | <el-table-column |
| | | label="éé访" |
| | | align="center" |
| | | key="needFollowUpAgain" |
| | | prop="needFollowUpAgain" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="medium" |
| | | type="text" |
| | | @click=" |
| | | viewDetails( |
| | | scope.row.needFollowUpAgainInfo, |
| | | scope.row.leavehospitaldistrictname + |
| | | '忬¡é访éé访å表' |
| | | ) |
| | | " |
| | | ><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=" |
| | | viewDetails( |
| | | scope.row.pendingFollowUpAgainInfo, |
| | | scope.row.leavehospitaldistrictname + |
| | | '忬¡é访å¾
é访å表' |
| | | ) |
| | | " |
| | | ><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=" |
| | | viewDetails( |
| | | scope.row.followUpSuccessAgainInfo, |
| | | scope.row.leavehospitaldistrictname + |
| | | '忬¡é访é访æåå表' |
| | | ) |
| | | " |
| | | ><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=" |
| | | viewDetails( |
| | | scope.row.followUpFailAgainInfo, |
| | | scope.row.leavehospitaldistrictname + |
| | | '忬¡é访é访失败å表' |
| | | ) |
| | | " |
| | | ><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> |
| | | <el-table-column |
| | | label="人工" |
| | | align="center" |
| | | key="manualAgain" |
| | | prop="manualAgain" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="medium" |
| | | type="text" |
| | | @click=" |
| | | viewDetails( |
| | | scope.row.manualAgainInfo, |
| | | scope.row.leavehospitaldistrictname + |
| | | '忬¡é访人工é访å表' |
| | | ) |
| | | " |
| | | ><span class="button-zx">{{ |
| | | scope.row.manualAgain |
| | | }}</span></el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="çä¿¡" |
| | | align="center" |
| | | key="smsAgain" |
| | | prop="smsAgain" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="medium" |
| | | type="text" |
| | | @click=" |
| | | viewDetails( |
| | | scope.row.smsAgainInfo, |
| | | scope.row.leavehospitaldistrictname + |
| | | '忬¡é访çä¿¡é访å表' |
| | | ) |
| | | " |
| | | ><span class="button-zx">{{ |
| | | scope.row.smsAgain |
| | | }}</span></el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="微信" |
| | | align="center" |
| | | key="weChatAgain" |
| | | prop="weChatAgain" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="medium" |
| | | type="text" |
| | | @click=" |
| | | viewDetails( |
| | | scope.row.weChatAgainInfo, |
| | | scope.row.leavehospitaldistrictname + |
| | | '忬¡é访微信é访å表' |
| | | ) |
| | | " |
| | | ><span class="button-zx">{{ |
| | | scope.row.weChatAgain |
| | | }}</span></el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | |
| | | <!-- 忥çå页ç»ä»¶ä¿çï¼å¦æéè¦ï¼ --> |
| | | <!-- <pagination |
| | | v-show="total > 0" |
| | | :total="total" |
| | | :page.sync="queryParams.pageNum" |
| | | :limit.sync="queryParams.pageSize" |
| | | @pagination="getList" |
| | | /> --> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | </div> |
| | | <!-- ç»è®¡è¶å¿å¾å¼¹çª --> |
| | | <el-dialog |
| | | title="é访ç»è®¡è¶å¿å¾" |
| | | :visible.sync="chartDialogVisible" |
| | | width="80%" |
| | | :close-on-click-modal="false" |
| | | > |
| | | <div class="chart-container"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <div class="chart-title">éè®¿ç¶æåå¸</div> |
| | | <div id="pieChart" style="width: 100%; height: 400px"></div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="chart-title">é访è¶å¿åæ</div> |
| | | <div id="barLineChart" style="width: 100%; height: 400px"></div> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | </el-dialog> |
| | | <el-dialog |
| | | title="æªåæ¶é访æ£è
æå¡" |
| | | :visible.sync="SeedetailsVisible" |
| | | v-loading="Seedloading" |
| | | width="70%" |
| | | :close-on-click-modal="false" |
| | | > |
| | | <div class="examine-jic"> |
| | | <div class="jic-value"> |
| | | <el-row :gutter="20"> |
| | | <!--ç¨æ·æ°æ®--> |
| | | <el-form |
| | | :model="patientqueryParams" |
| | | ref="queryForm" |
| | | size="small" |
| | | :inline="true" |
| | | label-width="98px" |
| | | > |
| | | <el-form-item label="æ£è
ï¼"> |
| | | <el-input |
| | | v-model="patientqueryParams.name" |
| | | @keyup.enter.native="handleQuery" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="æ£è
è¯æï¼"> |
| | | <el-input |
| | | v-model="patientqueryParams.leavediagname" |
| | | @keyup.enter.native="handleQuery" |
| | | ></el-input> |
| | | </el-form-item> |
| | | |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | | icon="el-icon-search" |
| | | size="medium" |
| | | @click="handleQuery" |
| | | >æç´¢</el-button |
| | | > |
| | | <el-button |
| | | icon="el-icon-refresh" |
| | | size="medium" |
| | | @click="resetQuery" |
| | | >åæ¶å建</el-button |
| | | > |
| | | </el-form-item> |
| | | </el-form> |
| | | <!-- éæ©æ£è
å表 --> |
| | | <el-table :data="logsheetlist" 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="Seedetailstion" |
| | | <el-form-item label-width="200" label="åºé访æ¶é´èå´" prop="userName"> |
| | | <el-date-picker |
| | | v-model="queryParams.dateRange" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | type="daterange" |
| | | range-separator="è³" |
| | | start-placeholder="å¼å§æ¥æ" |
| | | end-placeholder="ç»ææ¥æ" |
| | | :default-time="['00:00:00', '23:59:59']" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | <!-- å类详æ
--> |
| | | <el-dialog |
| | | </el-form-item> |
| | | |
| | | <el-form-item> |
| | | <el-button type="primary" icon="el-icon-search" size="medium" @click="handleQuery">æç´¢</el-button> |
| | | <el-button icon="el-icon-refresh" size="medium" @click="resetQuery">éç½®</el-button> |
| | | </el-form-item> |
| | | |
| | | <el-button type="warning" plain icon="el-icon-download" size="medium" @click="handleExport">导åº</el-button> |
| | | <el-button type="primary" plain icon="el-icon-data-line" size="medium" @click="showChartDialog">ç»è®¡è¶å¿å¾</el-button> |
| | | </el-form> |
| | | </div> |
| | | |
| | | <!-- Tab忢åºå --> |
| | | <div class="tab-section"> |
| | | <el-tabs v-model="activeTab" @tab-click="handleTabClick"> |
| | | <el-tab-pane label="馿¬¡é访" name="first"> |
| | | <FirstFollowUp |
| | | ref="firstFollowUp" |
| | | :query-params="queryParams" |
| | | :flat-array-hospit="flatArrayhospit" |
| | | :flat-array-dept="flatArraydept" |
| | | :options="options" |
| | | :orgname="orgname" |
| | | @view-details="viewDetails" |
| | | @see-details="Seedetails" |
| | | /> |
| | | </el-tab-pane> |
| | | |
| | | <el-tab-pane label="忬¡é访" name="second"> |
| | | <SecondFollowUp |
| | | ref="secondFollowUp" |
| | | :query-params="queryParams" |
| | | :flat-array-hospit="flatArrayhospit" |
| | | :flat-array-dept="flatArraydept" |
| | | :options="options" |
| | | :orgname="orgname" |
| | | @view-details="viewDetails" |
| | | /> |
| | | </el-tab-pane> |
| | | |
| | | <el-tab-pane label="å»¶ç»æ¤çç»è®¡" name="continued" v-if="orgname == 'çç«åå¾·ç¿ èé¢åº'"> |
| | | <ContinuedCare |
| | | ref="continuedCare" |
| | | :query-params="queryParams" |
| | | :flat-array-hospit="flatArrayhospit" |
| | | :flat-array-dept="flatArraydept" |
| | | :options="options" |
| | | :orgname="orgname" |
| | | @view-details="viewDetails" |
| | | /> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | </div> |
| | | |
| | | <!-- å¼¹çªåºå --> |
| | | <ChartDialog |
| | | :visible="chartDialogVisible" |
| | | :data="chartData" |
| | | :active-tab="activeTab" |
| | | @close="chartDialogVisible = false" |
| | | /> |
| | | |
| | | <DetailDialog |
| | | :visible="infotitleVisible" |
| | | :title="infotitle" |
| | | :visible.sync="infotitleVisible" |
| | | v-loading="infotitloading" |
| | | width="70%" |
| | | :close-on-click-modal="false" |
| | | > |
| | | <div style="margin-bottom: 16px; display: flex; align-items: center"> |
| | | <span style="margin-right: 10px; font-weight: bold">æ£è
å§åæ¥è¯¢:</span> |
| | | <el-input |
| | | v-model="searchName" |
| | | placeholder="请è¾å
¥æ£è
å§åè¿è¡çé" |
| | | clearable |
| | | style="width: 300px" |
| | | @input="handleSearch" |
| | | @clear="handleSearch" |
| | | > |
| | | </el-input> |
| | | <span |
| | | style="margin-left: 10px; color: rgb(35, 81, 233); font-size: 16px" |
| | | > |
| | | å
± {{ infotitlelist.length }} æ¡è®°å½ |
| | | </span> |
| | | </div> |
| | | <div class="examine-jic"> |
| | | <div class="jic-value"> |
| | | <el-row :gutter="20"> |
| | | <!-- éæ©æ£è
å表 --> |
| | | <div |
| | | class="data-list" |
| | | ref="dataList" |
| | | @scroll="handleScroll" |
| | | v-loading="infotitloading" |
| | | > |
| | | <el-table |
| | | :data="currentDisplayList" |
| | | 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 |
| | | label="任塿§è¡æ¹å¼" |
| | | align="center" |
| | | key="preachform" |
| | | prop="preachform" |
| | | width="160" |
| | | :show-overflow-tooltip="true" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span v-for="item in scope.row.preachform" |
| | | >{{ item }}ã |
| | | </span> |
| | | </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" |
| | | /> |
| | | :data="infotitlelist" |
| | | :search-name="searchName" |
| | | @close="infotitleVisible = false" |
| | | @search="handleSearch" |
| | | @details-go="SeedetailsgGo" |
| | | /> |
| | | |
| | | <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> |
| | | </div> |
| | | </el-row> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | <TimelyRateDialog |
| | | :visible="SeedetailsVisible" |
| | | :loading="Seedloading" |
| | | :data="logsheetlist" |
| | | :total="patienttotal" |
| | | :query-params="patientqueryParams" |
| | | @close="SeedetailsVisible = false" |
| | | @search="Seedetailstion" |
| | | @details-go="SeedetailsgGo" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { |
| | | toamendtag, |
| | | addapitag, |
| | | deletetag, |
| | | changetagcategory, |
| | | } 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"; |
| | | import FirstFollowUp from './components/FirstFollowUp.vue' |
| | | import SecondFollowUp from './components/SecondFollowUp.vue' |
| | | import ContinuedCare from './components/ContinuedCare.vue' |
| | | import ChartDialog from './components/ChartDialog.vue' |
| | | import DetailDialog from './components/DetailDialog.vue' |
| | | import TimelyRateDialog from './components/TimelyRateDialog.vue' |
| | | |
| | | const shortcuts = [ |
| | | { |
| | | text: "ä»å¤©", |
| | | onClick(picker) { |
| | | picker.$emit("pick", new Date()); |
| | | }, |
| | | }, |
| | | { |
| | | text: "æ¨å¤©", |
| | | onClick(picker) { |
| | | const date = new Date(); |
| | | date.setTime(date.getTime() - 3600 * 1000 * 24); |
| | | picker.$emit("pick", date); |
| | | }, |
| | | }, |
| | | { |
| | | text: "ä¸å¨å", |
| | | onClick(picker) { |
| | | const date = new Date(); |
| | | date.setTime(date.getTime() - 3600 * 1000 * 24 * 7); |
| | | picker.$emit("pick", date); |
| | | }, |
| | | }, |
| | | ]; |
| | | |
| | | export default { |
| | | name: "Percentage", |
| | | dicts: ["sys_normal_disable", "sys_user_sex"], |
| | | components: { Treeselect }, |
| | | name: 'FollowUpStatistics', |
| | | components: { |
| | | FirstFollowUp, |
| | | SecondFollowUp, |
| | | ContinuedCare, |
| | | ChartDialog, |
| | | DetailDialog, |
| | | TimelyRateDialog |
| | | }, |
| | | data() { |
| | | return { |
| | | // æ°å¢ï¼Tabæ ç¾é¡µæ§å¶ |
| | | activeTab: "first", // å½åæ¿æ´»çtabï¼first-馿¬¡é访ï¼second-忬¡é访 |
| | | |
| | | // åç¦»çæ°æ®å表 |
| | | firstFollowUpList: [], // 馿¬¡éè®¿æ°æ® |
| | | secondFollowUpList: [], // 忬¡éè®¿æ°æ® |
| | | |
| | | // å离çå è½½ç¶æ |
| | | loading: false, // 馿¬¡éè®¿è¡¨æ ¼å è½½ç¶æ |
| | | loadingSecond: false, // 忬¡éè®¿è¡¨æ ¼å è½½ç¶æ |
| | | |
| | | // å离çå±å¼ç¶æ |
| | | expands: [], // 馿¬¡éè®¿è¡¨æ ¼å±å¼è¡ |
| | | expandsSecond: [], // 忬¡éè®¿è¡¨æ ¼å±å¼è¡ |
| | | |
| | | // å离çéæ©ç¶æ |
| | | ids: [], // 馿¬¡é访éä¸é¡¹ |
| | | idsSecond: [], // 忬¡é访éä¸é¡¹ |
| | | |
| | | orgname: "", |
| | | infotitlelist: [], |
| | | currentDisplayList: [], |
| | | loadIndex: 0, |
| | | pageSize: 100, |
| | | isLoading: false, |
| | | |
| | | Seedloading: false, |
| | | chartDialogVisible: false, |
| | | infotitleVisible: false, |
| | | searchName: "", |
| | | infotitloading: false, |
| | | infotitle: "", |
| | | pieChart: null, |
| | | barLineChart: null, |
| | | |
| | | single: true, |
| | | multiple: true, |
| | | showSearch: true, |
| | | idds: "", |
| | | total: 0, |
| | | flatArrayhospit: [], |
| | | flatArraydept: [], |
| | | patienttotal: 0, |
| | | logsheetlist: [], |
| | | activeTab: 'first', |
| | | orgname: localStorage.getItem('orgname') || '', |
| | | Statisticallist: [ |
| | | { |
| | | label: "ç
åºç»è®¡", |
| | | value: 1, |
| | | }, |
| | | { |
| | | label: "ç§å®¤ç»è®¡", |
| | | value: 2, |
| | | }, |
| | | { label: 'ç
åºç»è®¡', value: 1 }, |
| | | { label: 'ç§å®¤ç»è®¡', value: 2 } |
| | | ], |
| | | patientqueryParams: { |
| | | pn: 1, |
| | | ps: 10, |
| | | }, |
| | | amendtag: false, |
| | | lstamendtag: false, |
| | | scavisible: false, |
| | | deleteVisible: false, |
| | | deletefenl: "é«è¡å", |
| | | tagform: { |
| | | isupload: "", |
| | | tagname: "", |
| | | tagcategoryid: "", |
| | | tagdescription: "", |
| | | }, |
| | | classifyform: { |
| | | categoryname: "", |
| | | }, |
| | | title: "", |
| | | open: false, |
| | | dateRange: [], |
| | | postOptions: [], |
| | | roleOptions: [], |
| | | allDeptCodes: [], |
| | | allWardCodes: [], |
| | | checkboxlist: [], |
| | | form: {}, |
| | | forms: { |
| | | name: "", |
| | | }, |
| | | numberlb: 22, |
| | | dialogFormVisible: false, |
| | | lstamendtagVisible: false, |
| | | goQRCodeVisible: false, |
| | | sidecolumnval: "", |
| | | propss: { multiple: true }, |
| | | SeedetailsVisible: false, |
| | | options: store.getters.tasktypes, |
| | | pickerOptions: { |
| | | disabledDate(time) { |
| | | return time.getTime() < Date.now() - 3600 * 1000 * 24; |
| | | }, |
| | | shortcuts: shortcuts, |
| | | }, |
| | | pickerOptionsa: { |
| | | disabledDate(time) { |
| | | return time.getTime() > Date.now(); |
| | | }, |
| | | shortcuts: shortcuts, |
| | | }, |
| | | options: this.$store.getters.tasktypes, |
| | | queryParams: { |
| | | serviceType: [2], |
| | | dateRange: [], |
| | | statisticaltype: 1, |
| | | leavehospitaldistrictcodes: ["all"], |
| | | deptcodes: [], |
| | | visitCount: 1, // æ°å¢ï¼é访次æ°åæ°ï¼1-馿¬¡ï¼2-忬¡ |
| | | leavehospitaldistrictcodes: ['all'], |
| | | deptcodes: [] |
| | | }, |
| | | columns: [ |
| | | { key: 0, label: `æ ç¾ç¼å·`, visible: true }, |
| | | { key: 1, label: `æ ç¾åç§°`, visible: true }, |
| | | { key: 2, label: `æ ç¾æµç§°`, visible: true }, |
| | | { key: 3, label: `é¨é¨`, visible: true }, |
| | | { key: 4, label: `ææºå·ç `, visible: true }, |
| | | { key: 5, label: `ç¶æ`, visible: true }, |
| | | { key: 6, label: `å建æ¶é´`, visible: true }, |
| | | ], |
| | | }; |
| | | flatArrayhospit: [], |
| | | flatArraydept: [], |
| | | allDeptCodes: [], |
| | | allWardCodes: [], |
| | | showSearch: true, |
| | | |
| | | // å¼¹çªç¸å
³ç¶æ |
| | | chartDialogVisible: false, |
| | | chartData: [], |
| | | infotitleVisible: false, |
| | | SeedetailsVisible: false, |
| | | searchName: '', |
| | | infotitle: '', |
| | | infotitlelist: [], |
| | | patienttotal: 0, |
| | | logsheetlist: [], |
| | | Seedloading: false, |
| | | patientqueryParams: { |
| | | pn: 1, |
| | | ps: 10 |
| | | } |
| | | } |
| | | }, |
| | | watch: {}, |
| | | created() { |
| | | this.getDeptTree(); |
| | | this.getFirstFollowUpList(); // é»è®¤å è½½é¦æ¬¡éè®¿æ°æ® |
| | | this.checkboxlist = store.getters.checkboxlist; |
| | | this.orgname = localStorage.getItem("orgname"); |
| | | this.getDeptTree() |
| | | }, |
| | | |
| | | methods: { |
| | | /** æ¥è¯¢é¦æ¬¡é访å表 */ |
| | | async getFirstFollowUpList() { |
| | | this.loading = true; |
| | | this.queryParams.visitCount = 1; // 设置é访次æ°ä¸ºé¦æ¬¡ |
| | | |
| | | 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; |
| | | |
| | | try { |
| | | const response = await getSfStatistics(params); |
| | | this.firstFollowUpList = this.customSort(response.data); |
| | | this.total = response.total; |
| | | } catch (error) { |
| | | console.error("è·å馿¬¡éè®¿æ°æ®å¤±è´¥:", error); |
| | | this.$message.error("è·å馿¬¡éè®¿æ°æ®å¤±è´¥"); |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | |
| | | /** æ¥è¯¢å次é访å表 */ |
| | | async getSecondFollowUpList() { |
| | | this.loadingSecond = true; |
| | | this.queryParams.visitCount = 2; // 设置é访次æ°ä¸ºå次 |
| | | |
| | | 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; |
| | | |
| | | try { |
| | | const response = await getSfStatistics(params); |
| | | this.secondFollowUpList = this.customSort(response.data); |
| | | this.total = response.total; |
| | | } catch (error) { |
| | | console.error("è·å忬¡éè®¿æ°æ®å¤±è´¥:", error); |
| | | this.$message.error("è·å忬¡éè®¿æ°æ®å¤±è´¥"); |
| | | } finally { |
| | | this.loadingSecond = false; |
| | | } |
| | | }, |
| | | |
| | | /** Tab忢äºä»¶ */ |
| | | handleTabClick(tab) { |
| | | if (tab.name === "first") { |
| | | if (this.firstFollowUpList.length === 0) { |
| | | this.getFirstFollowUpList(); |
| | | } |
| | | } else if (tab.name === "second") { |
| | | if (this.secondFollowUpList.length === 0) { |
| | | this.getSecondFollowUpList(); |
| | | } |
| | | } |
| | | }, |
| | | sortChineseNumber(aRow, bRow) { |
| | | const a = aRow.leavehospitaldistrictname; |
| | | const b = bRow.leavehospitaldistrictname; |
| | | |
| | | // 䏿æ°åå°é¿æä¼¯æ°åçæ å°ï¼æ©å±å°45ï¼ |
| | | 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, |
| | | }; |
| | | |
| | | // æå䏿æ°å |
| | | 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; |
| | | } |
| | | |
| | | // å¦ææ²¡æå¹é
å°ä¸ææ°åï¼å°è¯å¹é
é¿æä¼¯æ°å |
| | | const arabicMatch = text.match(/^(\d+)/); |
| | | if (arabicMatch && arabicMatch[1]) { |
| | | const num = parseInt(arabicMatch[1], 10); |
| | | return num >= 1 && num <= 45 ? num : -1; |
| | | } |
| | | |
| | | return -1; |
| | | }; |
| | | |
| | | const numA = getNumberFromText(a); |
| | | const numB = getNumberFromText(b); |
| | | |
| | | // å¤çæ æ³è§£æçæ
åµ |
| | | if (numA === -1 && numB === -1) { |
| | | return (a || "").localeCompare(b || ""); |
| | | } |
| | | if (numA === -1) return 1; |
| | | if (numB === -1) return -1; |
| | | |
| | | return numA - numB; |
| | | }, |
| | | // æç´¢å¤ç彿° |
| | | handleSearch() { |
| | | if (!this.searchName.trim()) { |
| | | // 妿æç´¢æ¡ä¸ºç©ºï¼æ¾ç¤ºæææ°æ® |
| | | this.currentDisplayList = [...this.infotitlelist]; |
| | | } else { |
| | | // æ ¹æ®æ£è
å§åè¿è¡çéï¼ä¸åºå大å°åï¼ |
| | | const keyword = this.searchName.toLowerCase(); |
| | | this.currentDisplayList = this.infotitlelist.filter((item) => { |
| | | return item.sendname && item.sendname.toLowerCase().includes(keyword); |
| | | }); |
| | | } |
| | | }, |
| | | customSort(data) { |
| | | // å®ä¹æ¨ææçç
åºé¡ºåºï¼æ©å±å°ååäºï¼ |
| | | const order = [ |
| | | "ä¸", |
| | | "äº", |
| | | "ä¸", |
| | | "å", |
| | | "äº", |
| | | "å
", |
| | | "ä¸", |
| | | "å
«", |
| | | "ä¹", |
| | | "å", |
| | | "åä¸", |
| | | "åäº", |
| | | "åä¸", |
| | | "åå", |
| | | "åäº", |
| | | "åå
", |
| | | "åä¸", |
| | | "åå
«", |
| | | "åä¹", |
| | | "äºå", |
| | | "äºåä¸", |
| | | "äºåäº", |
| | | "äºåä¸", |
| | | "äºåå", |
| | | "äºåäº", |
| | | "äºåå
", |
| | | "äºåä¸", |
| | | "äºåå
«", |
| | | "äºåä¹", |
| | | "ä¸å", |
| | | "ä¸åä¸", |
| | | "ä¸åäº", |
| | | "ä¸åä¸", |
| | | "ä¸åå", |
| | | "ä¸åäº", |
| | | "ä¸åå
", |
| | | "ä¸åä¸", |
| | | "ä¸åå
«", |
| | | "ä¸åä¹", |
| | | "åå", |
| | | "ååä¸", |
| | | "ååäº", |
| | | "ååä¸", |
| | | "ååå", |
| | | "ååäº", |
| | | ]; |
| | | |
| | | return data.sort((a, b) => { |
| | | // æåç
åºåç§°ä¸ç䏿æ°åé¨å |
| | | const getIndex = (name) => { |
| | | if (!name || typeof name !== "string") return -1; |
| | | |
| | | // å¹é
䏿æ°å |
| | | const chineseMatch = name.match(/^([ä¸äºä¸åäºå
ä¸å
«ä¹å]+)/); |
| | | if (chineseMatch && chineseMatch[1]) { |
| | | return order.indexOf(chineseMatch[1]); |
| | | } |
| | | |
| | | // å¹é
é¿æä¼¯æ°å |
| | | const arabicMatch = name.match(/^(\d+)/); |
| | | if (arabicMatch && arabicMatch[1]) { |
| | | const num = parseInt(arabicMatch[1], 10); |
| | | if (num >= 1 && num <= 45) { |
| | | return num - 1; // å 为æ°ç»ç´¢å¼ä»0å¼å§ |
| | | } |
| | | } |
| | | |
| | | return -1; |
| | | }; |
| | | |
| | | const indexA = getIndex(a.leavehospitaldistrictname); |
| | | const indexB = getIndex(b.leavehospitaldistrictname); |
| | | |
| | | // æåºé»è¾ |
| | | if (indexA === -1 && indexB === -1) { |
| | | return (a.leavehospitaldistrictname || "").localeCompare( |
| | | b.leavehospitaldistrictname || "" |
| | | ); |
| | | } |
| | | if (indexA === -1) return 1; |
| | | if (indexB === -1) return -1; |
| | | return indexA - indexB; |
| | | }); |
| | | }, |
| | | getRowKey(row) { |
| | | return row.statisticaltype === 1 |
| | | ? row.leavehospitaldistrictcode |
| | | : row.deptcode; |
| | | }, |
| | | |
| | | // å¤çè¡ç¹å»å±å¼ |
| | | handleRowClick(row) { |
| | | console.log(row, "row"); |
| | | |
| | | // 妿已ç»å±å¼åæ¶èµ· |
| | | if (this.expands.includes(this.getRowKey(row))) { |
| | | this.expands = []; |
| | | return; |
| | | } |
| | | // å¤çæ¥è¯¢åæ° |
| | | const params = { |
| | | ...this.queryParams, |
| | | // 妿鿩äº"å
¨é¨"ï¼åä¼ ææç
åº/ç§å®¤ä»£ç |
| | | deptcodes: this.queryParams.deptcodes.includes("all") |
| | | ? this.allDeptCodes |
| | | : this.queryParams.deptcodes, |
| | | leavehospitaldistrictcodes: [row.leavehospitaldistrictcode], |
| | | drcode: "1", |
| | | visitCount: 1, // è®¾ç½®ä¸ºé¦æ¬¡é访 |
| | | }; |
| | | |
| | | // ç§»é¤å¯è½åå¨ç"all"å¼ |
| | | delete params.leavehospitaldistrictcodes.all; |
| | | delete params.deptcodes.all; |
| | | // å¦æè¯¥è¡è¿æ²¡æå è½½å»çæ°æ®ï¼åå è½½ |
| | | if (!row.doctorStats) { |
| | | this.loading = true; |
| | | getSfStatistics(params).then((res) => { |
| | | this.$set(row, "doctorStats", res.data); |
| | | this.expands = [this.getRowKey(row)]; |
| | | this.loading = false; |
| | | }); |
| | | } else { |
| | | this.expands = [this.getRowKey(row)]; |
| | | } |
| | | }, |
| | | getSummaries(param) { |
| | | const { columns, data } = param; |
| | | const sums = []; |
| | | |
| | | columns.forEach((column, index) => { |
| | | if (index === 0) { |
| | | sums[index] = "å计"; |
| | | return; |
| | | } |
| | | if (index === 1 || index === 2) { |
| | | sums[index] = "/"; |
| | | return; |
| | | } |
| | | |
| | | // 对ç¾åæ¯åæ®µç¹æ®å¤ç - åå¹³åå¼ |
| | | if ( |
| | | column.property === "followUpRate" || |
| | | column.property === "rate" || |
| | | column.property === "followUpRateAgain" |
| | | ) { |
| | | // æåææææç¾åæ¯å¼å¹¶è½¬æ¢ä¸ºå°æ° |
| | | const percentageValues = data |
| | | .map((item) => { |
| | | 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; |
| | | } else { |
| | | // å¤çå·²ç»æ¯å°æ°çæ°æ® |
| | | const numValue = parseFloat(value); |
| | | return isNaN(numValue) ? null : numValue; |
| | | } |
| | | }) |
| | | .filter((value) => value !== null && value !== 0); // è¿æ»¤ænullå0å¼ |
| | | |
| | | if (percentageValues.length > 0) { |
| | | const average = |
| | | percentageValues.reduce((sum, value) => sum + value, 0) / |
| | | percentageValues.length; |
| | | sums[index] = (average * 100).toFixed(2) + "%"; |
| | | } else { |
| | | 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; |
| | | }); |
| | | |
| | | if (!values.every((value) => isNaN(value))) { |
| | | sums[index] = values.reduce((prev, curr) => prev + curr, 0); |
| | | sums[index] = this.formatNumber(sums[index]); |
| | | } else { |
| | | sums[index] = "-"; |
| | | } |
| | | } |
| | | }); |
| | | |
| | | return sums; |
| | | }, |
| | | |
| | | // å
é¨è¡¨æ ¼å计è¡è®¡ç®æ¹æ³ |
| | | getInnerSummaries(param) { |
| | | const { columns, data } = param; |
| | | const sums = []; |
| | | |
| | | columns.forEach((column, index) => { |
| | | if (index === 0) { |
| | | sums[index] = "å°è®¡"; |
| | | return; |
| | | } |
| | | |
| | | if (column.property === "drname" || column.property === "deptname") { |
| | | sums[index] = "-"; |
| | | return; |
| | | } |
| | | |
| | | // 对ç¾åæ¯åæ®µç¹æ®å¤ç - åå¹³åå¼ |
| | | if (column.property === "followUpRate" || column.property === "rate") { |
| | | // æåææææç¾åæ¯å¼å¹¶è½¬æ¢ä¸ºå°æ° |
| | | const percentageValues = data |
| | | .map((item) => { |
| | | 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; |
| | | } else { |
| | | // å¤çå·²ç»æ¯å°æ°çæ°æ® |
| | | const numValue = parseFloat(value); |
| | | return isNaN(numValue) ? null : numValue; |
| | | } |
| | | }) |
| | | .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) + "%"; |
| | | } else { |
| | | 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; |
| | | }); |
| | | |
| | | if (!values.every((value) => isNaN(value))) { |
| | | sums[index] = values.reduce((prev, curr) => prev + curr, 0); |
| | | sums[index] = this.formatNumber(sums[index]); |
| | | } else { |
| | | sums[index] = "-"; |
| | | } |
| | | } |
| | | }); |
| | | |
| | | return sums; |
| | | }, |
| | | |
| | | // è¾
婿¹æ³ï¼æåç¾åæ¯æ°å¼ |
| | | extractPercentageValue(value) { |
| | | if (!value) return null; |
| | | |
| | | if (typeof value === "string") { |
| | | // å¤ç带ç¾åå·çå符串 |
| | | if (value.includes("%")) { |
| | | const num = parseFloat(value.replace("%", "")); |
| | | return isNaN(num) ? null : num / 100; |
| | | } |
| | | // å¤ç纯æ°åå符串 |
| | | const num = parseFloat(value); |
| | | return isNaN(num) ? null : num; |
| | | } |
| | | |
| | | // å¤çæ°åç±»å |
| | | return typeof value === "number" ? value : null; |
| | | }, |
| | | |
| | | // æ°åæ ¼å¼åæ¹æ³ |
| | | formatNumber(num) { |
| | | if (isNaN(num)) return "-"; |
| | | return Number.isInteger(num) ? num.toString() : num.toFixed(0); |
| | | }, |
| | | /** ä¿®æ¹æ ç¾ */ |
| | | handleUpdate(row) { |
| | | console.log(row, "ä¿®æ¹æ ç¾"); |
| | | this.lstamendtagVisible = true; |
| | | this.lstamendtag = true; |
| | | this.tagform = { |
| | | isupload: row.isupload, |
| | | tagname: row.tagname, |
| | | tagcategoryid: row.tagcategoryid, |
| | | tagdescription: row.tagdescription, |
| | | tagid: row.tagid, |
| | | }; |
| | | }, |
| | | // è·åç§å®¤æ |
| | | getDeptTree() { |
| | | // ç§å®¤å表 |
| | | this.flatArraydept = store.getters.belongDepts.map((dept) => { |
| | | this.flatArraydept = this.$store.getters.belongDepts.map((dept) => { |
| | | return { |
| | | label: dept.deptName, |
| | | value: dept.deptCode, |
| | | }; |
| | | }); |
| | | // å卿æç§å®¤ä»£ç |
| | | this.allDeptCodes = store.getters.belongDepts.map( |
| | | (dept) => dept.deptCode |
| | | ); |
| | | value: dept.deptCode |
| | | } |
| | | }) |
| | | this.allDeptCodes = this.$store.getters.belongDepts.map((dept) => dept.deptCode) |
| | | |
| | | // ç
åºå表 |
| | | this.flatArrayhospit = store.getters.belongWards.map((ward) => { |
| | | this.flatArrayhospit = this.$store.getters.belongWards.map((ward) => { |
| | | return { |
| | | label: ward.districtName, |
| | | value: ward.districtCode, |
| | | }; |
| | | }); |
| | | |
| | | // å卿æç
åºä»£ç |
| | | this.allWardCodes = store.getters.belongWards.map( |
| | | (ward) => ward.districtCode |
| | | ); |
| | | this.flatArraydept.push({ label: "å
¨é¨", value: "all" }); |
| | | this.flatArrayhospit.push({ label: "å
¨é¨", value: "all" }); |
| | | }, |
| | | flattenArray(multiArray) { |
| | | let result = []; |
| | | |
| | | // éå½å½æ°ï¼ç¨äºå°å¤çº§æ°ç»è½¬æ¢ä¸ºä¸ç»´æ°ç»ï¼åªå
嫿åºå±çå
ç´ |
| | | function flatten(element) { |
| | | // 妿å½åå
ç´ æåå
ç´ ï¼ç»§ç»éå½ |
| | | if (element.children && element.children.length > 0) { |
| | | element.children.forEach((child) => flatten(child)); |
| | | } else { |
| | | // å
éå
ç´ ä»¥é¿å
ä¿®æ¹åå§æ°æ® |
| | | let item = JSON.parse(JSON.stringify(element)); |
| | | result.push(item); // å°æåºå±çå
ç´ æ·»å å°ç»ææ°ç» |
| | | value: ward.districtCode |
| | | } |
| | | }) |
| | | this.allWardCodes = this.$store.getters.belongWards.map((ward) => ward.districtCode) |
| | | |
| | | this.flatArraydept.push({ label: 'å
¨é¨', value: 'all' }) |
| | | this.flatArrayhospit.push({ label: 'å
¨é¨', value: 'all' }) |
| | | }, |
| | | |
| | | handleTabClick(tab) { |
| | | this.activeTab = tab.name |
| | | this.loadCurrentTabData() |
| | | }, |
| | | |
| | | loadCurrentTabData() { |
| | | switch (this.activeTab) { |
| | | case 'first': |
| | | this.$refs.firstFollowUp.loadData() |
| | | break |
| | | case 'second': |
| | | this.$refs.secondFollowUp.loadData() |
| | | break |
| | | case 'continued': |
| | | this.$refs.continuedCare.loadData() |
| | | break |
| | | } |
| | | }, |
| | | |
| | | handleQuery() { |
| | | this.queryParams.startTime = this.parseTime(this.queryParams.dateRange[0]) |
| | | this.queryParams.endTime = this.parseTime(this.queryParams.dateRange[1]) |
| | | |
| | | if (this.queryParams.statisticaltype == 1) { |
| | | this.queryParams.deptcodes = [] |
| | | } else if (this.queryParams.statisticaltype == 2) { |
| | | this.queryParams.leavehospitaldistrictcodes = [] |
| | | } |
| | | |
| | | // ä»é¡¶å±å
ç´ å¼å§éå½ |
| | | multiArray.forEach((element) => flatten(element)); |
| | | return result; // è¿ååªå
嫿åºå±å
ç´ çä¸ç»´æ°ç» |
| | | this.loadCurrentTabData() |
| | | }, |
| | | addladeltag() { |
| | | this.lstamendtagVisible = true; |
| | | this.lstamendtag = false; |
| | | this.tagform = { |
| | | isupload: "", |
| | | tagname: "", |
| | | tagcategoryid: "", |
| | | tagdescription: "", |
| | | tagid: "", |
| | | }; |
| | | |
| | | resetQuery() { |
| | | this.queryParams.dateRange = [] |
| | | this.queryParams.leavehospitaldistrictcodes = [] |
| | | this.handleQuery() |
| | | }, |
| | | Seedetails(row) { |
| | | this.SeedetailsVisible = true; |
| | | this.Seedloading = true; |
| | | this.patientqueryParams.starttime = this.parseTime( |
| | | this.queryParams.dateRange[0] |
| | | ); |
| | | this.patientqueryParams.endtime = this.parseTime( |
| | | this.queryParams.dateRange[1] |
| | | ); |
| | | this.patientqueryParams.deptcode = row.deptcode; |
| | | selectTimelyRate(this.patientqueryParams).then((response) => { |
| | | this.logsheetlist = response.data.detail; |
| | | this.patienttotal = response.data.total; |
| | | this.Seedloading = false; |
| | | }); |
| | | |
| | | async handleExport() { |
| | | switch (this.activeTab) { |
| | | case 'first': |
| | | await this.$refs.firstFollowUp.exportTable() |
| | | break |
| | | case 'second': |
| | | await this.$refs.secondFollowUp.exportTable() |
| | | break |
| | | case 'continued': |
| | | await this.$refs.continuedCare.exportTable() |
| | | break |
| | | } |
| | | }, |
| | | Seedetailstion() { |
| | | selectTimelyRate(this.patientqueryParams).then((response) => { |
| | | this.logsheetlist = response.data.detail; |
| | | this.patienttotal = response.data.total; |
| | | this.Seedloading = false; |
| | | }); |
| | | |
| | | showChartDialog() { |
| | | this.chartData = this.getCurrentTabData() |
| | | this.chartDialogVisible = true |
| | | }, |
| | | |
| | | getCurrentTabData() { |
| | | switch (this.activeTab) { |
| | | case 'first': |
| | | return this.$refs.firstFollowUp.tableData |
| | | case 'second': |
| | | return this.$refs.secondFollowUp.tableData |
| | | case 'continued': |
| | | return this.$refs.continuedCare.tableData |
| | | default: |
| | | return [] |
| | | } |
| | | }, |
| | | |
| | | viewDetails(row, title) { |
| | | this.infotitleVisible = true; |
| | | this.infotitle = title; |
| | | this.infotitlelist = row; // å设rowå°±æ¯éè¦å±ç¤ºçè¯¦ç»æ°ç» |
| | | console.log(this.infotitlelist, "this.infotitlelist"); |
| | | |
| | | this.infotitlelist.forEach((item) => { |
| | | let idArray = null; |
| | | |
| | | if (item.preachform) { |
| | | if (item.endtime) { |
| | | item.preachformson = item.preachform; |
| | | idArray = item.preachform.split(","); |
| | | } |
| | | |
| | | item.preachform = idArray.map((value) => { |
| | | // æ¥æ¾id对åºç对象 |
| | | const item = this.checkboxlist.find((item) => item.value == value); |
| | | // 妿æ¾å°å¯¹åºçidï¼è¿ålabelå¼ï¼å¦åè¿ånull |
| | | return item ? item.label : null; |
| | | }); |
| | | } |
| | | }); |
| | | // åå§åå è½½ |
| | | this.loadIndex = 0; |
| | | this.currentDisplayList = []; |
| | | this.$nextTick(() => { |
| | | this.loadMoreData(); |
| | | }); |
| | | this.infotitle = title |
| | | this.infotitlelist = row |
| | | this.infotitleVisible = true |
| | | }, |
| | | loadMoreData() { |
| | | if (this.isLoading) return; |
| | | this.isLoading = true; |
| | | |
| | | // 模æå¼æ¥å è½½ï¼å®é
å¯è½æ¯ç´æ¥åçæ¬å°æ°æ® |
| | | setTimeout(() => { |
| | | console.log(this.infotitlelist, "this.infotitlelist"); |
| | | Seedetails(row) { |
| | | this.SeedetailsVisible = true |
| | | this.Seedloading = true |
| | | |
| | | const nextChunk = this.infotitlelist.slice( |
| | | this.loadIndex, |
| | | this.loadIndex + this.pageSize |
| | | ); |
| | | this.currentDisplayList = this.currentDisplayList.concat(nextChunk); |
| | | this.loadIndex += this.pageSize; |
| | | this.isLoading = false; |
| | | }, 200); |
| | | this.$refs.firstFollowUp.selectTimelyRate(row, this.queryParams.dateRange) |
| | | .then(response => { |
| | | this.logsheetlist = response.data.detail |
| | | this.patienttotal = response.data.total |
| | | this.Seedloading = false |
| | | }) |
| | | }, |
| | | handleScroll(event) { |
| | | const scrollContainer = event.target; |
| | | // 夿æ¯å¦æ»å¨å°åºé¨ |
| | | const isAtBottom = |
| | | scrollContainer.scrollTop + scrollContainer.clientHeight >= |
| | | scrollContainer.scrollHeight - 10; |
| | | |
| | | if ( |
| | | isAtBottom && |
| | | !this.isLoading && |
| | | this.loadIndex < this.infotitlelist.length |
| | | ) { |
| | | this.loadMoreData(); |
| | | } |
| | | Seedetailstion() { |
| | | this.$refs.firstFollowUp.selectTimelyRate(this.patientqueryParams) |
| | | .then(response => { |
| | | this.logsheetlist = response.data.detail |
| | | this.patienttotal = response.data.total |
| | | }) |
| | | }, |
| | | |
| | | SeedetailsgGo(row) { |
| | | this.SeedetailsVisible = false; |
| | | let type = ""; |
| | | if (row.preachformson && row.preachformson.includes("3")) { |
| | | type = 1; |
| | | this.SeedetailsVisible = false |
| | | let type = '' |
| | | if (row.preachformson && row.preachformson.includes('3')) { |
| | | type = 1 |
| | | } |
| | | setTimeout(() => { |
| | | this.$router.push({ |
| | | path: "/followvisit/record/detailpage/", |
| | | path: '/followvisit/record/detailpage/', |
| | | query: { |
| | | taskid: row.taskid, |
| | | patid: row.patid, |
| | | id: row.id, |
| | | Voicetype: type, |
| | | // visitCount: this.topqueryParams.visitCount, |
| | | }, |
| | | }); |
| | | }, 300); |
| | | }, |
| | | // æ·»å /ä¿®æ¹æ ç¾ |
| | | Maintenancetag() { |
| | | if (this.lstamendtag) { |
| | | toamendtag(this.addDateRange(this.tagform)).then((response) => { |
| | | console.log(response); |
| | | this.getList(); |
| | | }); |
| | | } else { |
| | | addapitag(this.addDateRange(this.tagform)).then((response) => { |
| | | console.log(response); |
| | | this.getList(); |
| | | }); |
| | | } |
| | | this.tagform = { |
| | | isupload: "", |
| | | tagname: "", |
| | | tagcategoryid: "", |
| | | tagdescription: "", |
| | | tagid: "", |
| | | }; |
| | | }, |
| | | routerErr(row) { |
| | | console.log(row, "跳转å¼å¸¸"); |
| | | this.$router.push({ |
| | | path: "/followvisit/discharge", |
| | | query: { |
| | | errtype: 1, |
| | | leavehospitaldistrictcode: row.leavehospitaldistrictcode, |
| | | }, |
| | | }); |
| | | }, |
| | | |
| | | // 表åéç½® |
| | | reset() { |
| | | this.form = { |
| | | userId: undefined, |
| | | deptId: undefined, |
| | | userName: undefined, |
| | | nickName: undefined, |
| | | password: undefined, |
| | | phonenumber: undefined, |
| | | email: undefined, |
| | | sex: undefined, |
| | | status: "0", |
| | | remark: undefined, |
| | | postIds: [], |
| | | roleIds: [], |
| | | }; |
| | | this.resetForm("form"); |
| | | }, |
| | | // æ ç¾ç¶æä¿®æ¹ |
| | | handleStatusChange(row) { |
| | | console.log(row.isupload); |
| | | let text = row.isupload === "0" ? "å¯ç¨" : "åç¨"; |
| | | this.$modal |
| | | .confirm('确认è¦"' + text + '""' + row.tagname + '"æ ç¾åï¼') |
| | | .then(function () { |
| | | return changetagcategory(row.tagid, row.isupload); |
| | | Voicetype: type |
| | | } |
| | | }) |
| | | .then(() => { |
| | | this.$modal.msgSuccess(text + "æå"); |
| | | }) |
| | | .catch(function () { |
| | | row.isupload = row.isupload === "0" ? "1" : "0"; |
| | | }); |
| | | }, |
| | | /** æç´¢æé®æä½ - ä¿®æ¹ä¸ºæç´¢å½åæ¿æ´»çtabæ°æ® */ |
| | | handleQuery() { |
| | | this.queryParams.pageNum = 1; |
| | | if (!this.queryParams.dateRange) this.queryParams.dateRange = []; |
| | | if (this.queryParams.statisticaltype == 1) { |
| | | this.queryParams.deptcodes = []; |
| | | } else if (this.queryParams.statisticaltype == 2) { |
| | | this.queryParams.leavehospitaldistrictcodes = []; |
| | | } |
| | | |
| | | this.queryParams.startTime = this.parseTime( |
| | | this.queryParams.dateRange[0] |
| | | ); |
| | | this.queryParams.endTime = this.parseTime(this.queryParams.dateRange[1]); |
| | | |
| | | // æ ¹æ®å½åæ¿æ´»çtabå è½½å¯¹åºæ°æ® |
| | | if (this.activeTab === "first") { |
| | | this.getFirstFollowUpList(); |
| | | } else { |
| | | this.getSecondFollowUpList(); |
| | | } |
| | | }, 300) |
| | | }, |
| | | |
| | | /** éç½®æé®æä½ */ |
| | | resetQuery() { |
| | | this.queryParams.dateRange = []; |
| | | this.queryParams.leavehospitaldistrictcodes = []; |
| | | this.handleQuery(); |
| | | }, |
| | | // å¤éæ¡é䏿°æ® |
| | | handleSelectionChange(selection) { |
| | | this.ids = selection.map((item) => item.tagid); |
| | | this.single = selection.length != 1; |
| | | this.multiple = !selection.length; |
| | | }, |
| | | |
| | | /** å é¤æé®æä½ */ |
| | | handleDelete(row) { |
| | | console.log(row, "å é¤å¼¹çª"); |
| | | const tagids = row.tagid || this.ids; |
| | | console.log(tagids); |
| | | const tagname = row.tagname; |
| | | this.$modal |
| | | .confirm( |
| | | tagname |
| | | ? 'æ¯å¦ç¡®è®¤å 餿 ç¾å称为"' + tagname + '"çæ°æ®é¡¹ï¼' |
| | | : "æ¯å¦ç¡®è®¤å é¤éä¸çæ°æ®é¡¹ï¼" |
| | | ) |
| | | .then(function () { |
| | | return deletetag(tagids); |
| | | }) |
| | | .then(() => { |
| | | this.getList(); |
| | | this.$modal.msgSuccess("å 餿å"); |
| | | }) |
| | | .catch(() => {}); |
| | | }, |
| | | // å¯¼åºæ¹æ³ |
| | | |
| | | async exportTable() { |
| | | try { |
| | | // 1. è·åå¹¶æ ¼å¼åæ¥æèå´ |
| | | 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]; |
| | | const formatDateForDisplay = (dateTimeStr) => { |
| | | 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}æ`; |
| | | } |
| | | |
| | | // 2. æ ¹æ®å½åæ¿æ´»çtabç¡®å®å¯¼åºçæ°æ® |
| | | const isFirstFollowUp = this.activeTab === "first"; |
| | | let excelName, worksheetName, dataToExport; |
| | | |
| | | if (isFirstFollowUp) { |
| | | excelName = `馿¬¡åºé¢é访ç»è®¡è¡¨_${dateRangeString}.xlsx`; |
| | | worksheetName = `馿¬¡é访ç»è®¡_${sheetNameSuffix}`; |
| | | dataToExport = this.firstFollowUpList; |
| | | |
| | | if (!dataToExport || dataToExport.length === 0) { |
| | | this.$message.warning("ææ é¦æ¬¡éè®¿æ°æ®å¯å¯¼åº"); |
| | | return false; |
| | | } |
| | | } else { |
| | | excelName = `忬¡åºé¢é访ç»è®¡è¡¨_${dateRangeString}.xlsx`; |
| | | worksheetName = `忬¡é访ç»è®¡_${sheetNameSuffix}`; |
| | | dataToExport = this.secondFollowUpList; |
| | | |
| | | if (!dataToExport || dataToExport.length === 0) { |
| | | this.$message.warning("ææ åæ¬¡éè®¿æ°æ®å¯å¯¼åº"); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | // 3. å建工ä½ç°¿åå·¥ä½è¡¨ |
| | | const workbook = new ExcelJS.Workbook(); |
| | | const worksheet = workbook.addWorksheet(worksheetName); |
| | | |
| | | // 4. æå»ºè¡¨æ ¼ |
| | | if (isFirstFollowUp) { |
| | | this.buildFirstFollowUpExportSheet( |
| | | worksheet, |
| | | dataToExport, |
| | | sheetNameSuffix |
| | | ); |
| | | } else { |
| | | this.buildSecondFollowUpExportSheet( |
| | | worksheet, |
| | | dataToExport, |
| | | sheetNameSuffix |
| | | ); |
| | | } |
| | | |
| | | // 5. çæå¹¶ä¸è½½æä»¶ |
| | | 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; |
| | | } |
| | | }, |
| | | /** æå»ºé¦æ¬¡é访导åºè¡¨æ ¼ */ |
| | | buildFirstFollowUpExportSheet(worksheet, data, 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" } }, |
| | | }, |
| | | }; |
| | | |
| | | 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, 16); // åå¹¶A1å°P1 |
| | | const titleCell = worksheet.getCell(1, 1); |
| | | titleCell.value = `馿¬¡åºé¢é访ç»è®¡è¡¨_${sheetNameSuffix}`; |
| | | titleCell.style = titleStyle; |
| | | worksheet.getRow(1).height = 35; |
| | | |
| | | // 2. å建表头 |
| | | const secondRowHeaders = [ |
| | | "", // A2 å±å¼åå ä½ |
| | | "åºé¢ç
åº", |
| | | "ç§å®¤", |
| | | "åºé¢äººæ¬¡", |
| | | "æ éé访人次", |
| | | "åºé访人次", // B2 to F2 |
| | | // 馿¬¡åºé¢é访å表头 |
| | | "éé访", |
| | | "å¾
é访", |
| | | "é访æå", |
| | | "é访失败", |
| | | "é访ç", |
| | | "åæ¶ç", |
| | | "人工", |
| | | "çä¿¡", |
| | | "微信", |
| | | ]; |
| | | |
| | | // æ·»å 第äºè¡ |
| | | secondRowHeaders.forEach((header, index) => { |
| | | const cell = worksheet.getCell(3, index + 1); |
| | | cell.value = header; |
| | | cell.style = headerStyle; |
| | | }); |
| | | |
| | | // 3. åå¹¶åå
æ ¼ |
| | | // åå¹¶ A2:A3, B2:B3, C2:C3, D2:D3, E2:E3, F2:F3 |
| | | for (let i = 1; i <= 6; i++) { |
| | | 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 = "åºé访人次"; |
| | | |
| | | // 4. åå¹¶"馿¬¡åºé¢é访"æ é¢ |
| | | worksheet.mergeCells(2, 7, 2, 15); // G2:O2 |
| | | worksheet.getCell(2, 7).value = "馿¬¡åºé¢é访"; |
| | | worksheet.getCell(2, 7).style = headerStyle; |
| | | |
| | | // 5. 设置è¡é« |
| | | worksheet.getRow(2).height = 28; |
| | | worksheet.getRow(3).height = 25; |
| | | |
| | | // 6. æ·»å æ°æ®è¡ |
| | | data.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, |
| | | ], |
| | | rowIndex + 4 |
| | | ); |
| | | |
| | | // åºç¨æ°æ®è¡æ ·å¼ |
| | | dataRow.eachCell((cell) => { |
| | | cell.style = cellStyle; |
| | | }); |
| | | dataRow.height = 24; |
| | | }); |
| | | |
| | | // 7. æ·»å åè®¡è¡ |
| | | const summaries = this.getFirstFollowUpSummaries(data); |
| | | const summaryRow = worksheet.addRow(summaries); |
| | | summaryRow.eachCell((cell, colNumber) => { |
| | | cell.style = summaryStyle; |
| | | if (colNumber === 1) { |
| | | cell.value = "å计"; |
| | | } |
| | | }); |
| | | summaryRow.height = 28; |
| | | |
| | | // 8. 设置å宽 |
| | | 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 }, // 微信 |
| | | ]; |
| | | }, |
| | | |
| | | /** 馿¬¡éè®¿æ°æ®å计è¡è®¡ç® */ |
| | | getFirstFollowUpSummaries(data) { |
| | | const summaries = [ |
| | | "å计", |
| | | "/", |
| | | "/", |
| | | 0, |
| | | 0, |
| | | 0, |
| | | 0, |
| | | 0, |
| | | 0, |
| | | 0, |
| | | "0%", |
| | | "0%", |
| | | 0, |
| | | 0, |
| | | 0, |
| | | ]; |
| | | |
| | | data.forEach((item) => { |
| | | // æ°å¼å段æ±å |
| | | summaries[3] += Number(item.dischargeCount) || 0; |
| | | summaries[4] += Number(item.nonFollowUp) || 0; |
| | | summaries[5] += Number(item.followUpNeeded) || 0; |
| | | summaries[6] += Number(item.needFollowUp) || 0; |
| | | summaries[7] += Number(item.pendingFollowUp) || 0; |
| | | summaries[8] += Number(item.followUpSuccess) || 0; |
| | | summaries[9] += Number(item.followUpFail) || 0; |
| | | summaries[12] += Number(item.manual) || 0; |
| | | summaries[13] += Number(item.sms) || 0; |
| | | summaries[14] += Number(item.weChat) || 0; |
| | | }); |
| | | |
| | | // 计ç®ç¾åæ¯å段çå¹³åå¼ |
| | | const followUpRateValues = data |
| | | .map((item) => this.extractPercentageValue(item.followUpRate)) |
| | | .filter((value) => value !== null); |
| | | |
| | | const rateValues = data |
| | | .map((item) => this.extractPercentageValue(item.rate)) |
| | | .filter((value) => value !== null); |
| | | |
| | | if (followUpRateValues.length > 0) { |
| | | const avgFollowUpRate = |
| | | followUpRateValues.reduce((sum, val) => sum + val, 0) / |
| | | followUpRateValues.length; |
| | | summaries[10] = (avgFollowUpRate * 100).toFixed(2) + "%"; |
| | | } |
| | | |
| | | if (rateValues.length > 0) { |
| | | const avgRate = |
| | | rateValues.reduce((sum, val) => sum + val, 0) / rateValues.length; |
| | | summaries[11] = (avgRate * 100).toFixed(2) + "%"; |
| | | } |
| | | |
| | | // æ ¼å¼åæ°å |
| | | 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[12] = this.formatNumber(summaries[12]); |
| | | summaries[13] = this.formatNumber(summaries[13]); |
| | | summaries[14] = this.formatNumber(summaries[14]); |
| | | |
| | | return summaries; |
| | | }, |
| | | |
| | | /** æå»ºå次é访导åºè¡¨æ ¼ */ |
| | | buildSecondFollowUpExportSheet(worksheet, data, 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" } }, |
| | | }, |
| | | }; |
| | | |
| | | 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, 15); // åå¹¶A1å°O1 |
| | | const titleCell = worksheet.getCell(1, 1); |
| | | titleCell.value = `忬¡åºé¢é访ç»è®¡è¡¨_${sheetNameSuffix}`; |
| | | titleCell.style = titleStyle; |
| | | worksheet.getRow(1).height = 35; |
| | | |
| | | // 2. å建表头 |
| | | const secondRowHeaders = [ |
| | | "", // A2 å±å¼åå ä½ |
| | | "åºé¢ç
åº", |
| | | "ç§å®¤", |
| | | "åºé¢äººæ¬¡", |
| | | "æ éé访人次", |
| | | "åºé访人次", // B2 to F2 |
| | | // 忬¡åºé¢é访å表头 |
| | | "éé访", |
| | | "å¾
é访", |
| | | "é访æå", |
| | | "é访失败", |
| | | "é访ç", |
| | | "人工", |
| | | "çä¿¡", |
| | | "微信", |
| | | ]; |
| | | |
| | | // æ·»å 第äºè¡ |
| | | secondRowHeaders.forEach((header, index) => { |
| | | const cell = worksheet.getCell(3, index + 1); |
| | | cell.value = header; |
| | | cell.style = headerStyle; |
| | | }); |
| | | |
| | | // 3. åå¹¶åå
æ ¼ |
| | | // åå¹¶ A2:A3, B2:B3, C2:C3, D2:D3, E2:E3, F2:F3 |
| | | for (let i = 1; i <= 6; i++) { |
| | | 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 = "åºé访人次"; |
| | | |
| | | // 4. åå¹¶"忬¡åºé¢é访"æ é¢ |
| | | worksheet.mergeCells(2, 7, 2, 14); // G2:N2 |
| | | worksheet.getCell(2, 7).value = "忬¡åºé¢é访"; |
| | | worksheet.getCell(2, 7).style = headerStyle; |
| | | |
| | | // 5. 设置è¡é« |
| | | worksheet.getRow(2).height = 28; |
| | | worksheet.getRow(3).height = 25; |
| | | |
| | | // 6. æ·»å æ°æ®è¡ |
| | | data.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 |
| | | ); |
| | | |
| | | // åºç¨æ°æ®è¡æ ·å¼ |
| | | dataRow.eachCell((cell) => { |
| | | cell.style = cellStyle; |
| | | }); |
| | | dataRow.height = 24; |
| | | }); |
| | | |
| | | // 7. æ·»å åè®¡è¡ |
| | | const summaries = this.getSecondFollowUpSummaries(data); |
| | | const summaryRow = worksheet.addRow(summaries); |
| | | summaryRow.eachCell((cell, colNumber) => { |
| | | cell.style = summaryStyle; |
| | | if (colNumber === 1) { |
| | | cell.value = "å计"; |
| | | } |
| | | }); |
| | | summaryRow.height = 28; |
| | | |
| | | // 8. 设置å宽 |
| | | 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 }, // 微信 |
| | | ]; |
| | | }, |
| | | |
| | | /** 忬¡éè®¿æ°æ®å计è¡è®¡ç® */ |
| | | getSecondFollowUpSummaries(data) { |
| | | const summaries = ["å计", "/", "/", 0, 0, 0, 0, 0, 0, 0, "0%", 0, 0, 0]; |
| | | |
| | | data.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; |
| | | }); |
| | | |
| | | // 计ç®é访çç¾åæ¯å段çå¹³åå¼ |
| | | const followUpRateAgainValues = data |
| | | .map((item) => this.extractPercentageValue(item.followUpRateAgain)) |
| | | .filter((value) => value !== null); |
| | | |
| | | if (followUpRateAgainValues.length > 0) { |
| | | const avgFollowUpRateAgain = |
| | | followUpRateAgainValues.reduce((sum, val) => sum + val, 0) / |
| | | followUpRateAgainValues.length; |
| | | summaries[10] = (avgFollowUpRateAgain * 100).toFixed(2) + "%"; |
| | | } |
| | | |
| | | // æ ¼å¼åæ°å |
| | | 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]); |
| | | |
| | | return summaries; |
| | | }, |
| | | |
| | | /** 忬¡éè®¿è¡¨æ ¼çå计è¡è®¡ç®æ¹æ³ */ |
| | | getSummariesSecond(param) { |
| | | const { columns, data } = param; |
| | | const sums = []; |
| | | |
| | | columns.forEach((column, index) => { |
| | | if (index === 0) { |
| | | sums[index] = "å计"; |
| | | return; |
| | | } |
| | | if (index === 1 || index === 2) { |
| | | sums[index] = "/"; |
| | | return; |
| | | } |
| | | |
| | | if (column.property === "followUpRateAgain") { |
| | | const percentageValues = data |
| | | .map((item) => { |
| | | 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; |
| | | } else { |
| | | const numValue = parseFloat(value); |
| | | return isNaN(numValue) ? null : numValue; |
| | | } |
| | | }) |
| | | .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) + "%"; |
| | | } else { |
| | | 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; |
| | | }); |
| | | |
| | | if (!values.every((value) => isNaN(value))) { |
| | | sums[index] = values.reduce((prev, curr) => prev + curr, 0); |
| | | sums[index] = this.formatNumber(sums[index]); |
| | | } else { |
| | | sums[index] = "-"; |
| | | } |
| | | } |
| | | }); |
| | | |
| | | return sums; |
| | | }, |
| | | /** 忬¡é访å
é¨è¡¨æ ¼å计è¡è®¡ç®æ¹æ³ */ |
| | | getInnerSummariesSecond(param) { |
| | | const { columns, data } = param; |
| | | const sums = []; |
| | | |
| | | columns.forEach((column, index) => { |
| | | if (index === 0) { |
| | | sums[index] = "å°è®¡"; |
| | | return; |
| | | } |
| | | |
| | | if (column.property === "drname" || column.property === "deptname") { |
| | | sums[index] = "-"; |
| | | return; |
| | | } |
| | | |
| | | if (column.property === "followUpRateAgain") { |
| | | const percentageValues = data |
| | | .map((item) => { |
| | | 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; |
| | | } else { |
| | | const numValue = parseFloat(value); |
| | | return isNaN(numValue) ? null : numValue; |
| | | } |
| | | }) |
| | | .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) + "%"; |
| | | } else { |
| | | 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; |
| | | }); |
| | | |
| | | if (!values.every((value) => isNaN(value))) { |
| | | sums[index] = values.reduce((prev, curr) => prev + curr, 0); |
| | | sums[index] = this.formatNumber(sums[index]); |
| | | } else { |
| | | sums[index] = "-"; |
| | | } |
| | | } |
| | | }); |
| | | |
| | | return sums; |
| | | }, |
| | | /** 忬¡éè®¿è¡¨æ ¼çè¡ç¹å»å±å¼ */ |
| | | handleRowClickSecond(row) { |
| | | if (this.expandsSecond.includes(this.getRowKey(row))) { |
| | | this.expandsSecond = []; |
| | | return; |
| | | } |
| | | |
| | | const params = { |
| | | ...this.queryParams, |
| | | deptcodes: this.queryParams.deptcodes.includes("all") |
| | | ? this.allDeptCodes |
| | | : this.queryParams.deptcodes, |
| | | leavehospitaldistrictcodes: [row.leavehospitaldistrictcode], |
| | | drcode: "1", |
| | | visitCount: 2, // è®¾ç½®ä¸ºåæ¬¡é访 |
| | | }; |
| | | |
| | | delete params.leavehospitaldistrictcodes.all; |
| | | delete params.deptcodes.all; |
| | | |
| | | if (!row.doctorStats) { |
| | | this.loadingSecond = true; |
| | | getSfStatistics(params).then((res) => { |
| | | this.$set(row, "doctorStats", res.data); |
| | | this.expandsSecond = [this.getRowKey(row)]; |
| | | this.loadingSecond = false; |
| | | }); |
| | | } else { |
| | | this.expandsSecond = [this.getRowKey(row)]; |
| | | } |
| | | }, |
| | | |
| | | /** 忬¡éè®¿è¡¨æ ¼çå¤éæ¡é䏿°æ® */ |
| | | handleSelectionChangeSecond(selection) { |
| | | this.idsSecond = selection.map((item) => item.tagid); |
| | | this.single = selection.length != 1; |
| | | this.multiple = !selection.length; |
| | | }, |
| | | // æ¾ç¤ºå¾è¡¨å¼¹çª |
| | | |
| | | showChartDialog() { |
| | | this.chartDialogVisible = true; |
| | | this.$nextTick(() => { |
| | | this.initPieChart(); |
| | | this.initBarLineChart(); |
| | | }); |
| | | }, |
| | | // å¨methodsä¸ä¿®æ¹ç»è®¡æ¹æ³ |
| | | showChartDialog() { |
| | | this.chartDialogVisible = true; |
| | | this.$nextTick(() => { |
| | | console.log(this.userList, "this.userList"); |
| | | |
| | | this.initCharts(); |
| | | }); |
| | | }, |
| | | |
| | | // æ°å¢åå§åå¾è¡¨æ¹æ³ |
| | | initCharts() { |
| | | this.initPieChart(); |
| | | this.initBarLineChart(); |
| | | }, |
| | | |
| | | // åå§åé¥¼å¾ |
| | | initPieChart() { |
| | | const echarts = require("echarts"); |
| | | const pieDom = document.getElementById("pieChart"); |
| | | if (!pieDom) return; |
| | | |
| | | if (this.pieChart) { |
| | | this.pieChart.dispose(); |
| | | } |
| | | |
| | | this.pieChart = echarts.init(pieDom); |
| | | |
| | | // 计ç®é¥¼å¾æ°æ® |
| | | const followUpData = { |
| | | pending: 0, |
| | | success: 0, |
| | | fail: 0, |
| | | }; |
| | | |
| | | this.userList.forEach((item) => { |
| | | followUpData.pending += item.pendingFollowUp || 0; |
| | | followUpData.success += item.followUpSuccess || 0; |
| | | followUpData.fail += item.followUpFail || 0; |
| | | }); |
| | | |
| | | // ä½¿ç¨æ´ç¾è§çé¢è²æ¹æ¡ |
| | | const pieOption = { |
| | | title: { |
| | | text: "éè®¿ç¶æåå¸", |
| | | left: "center", |
| | | textStyle: { |
| | | color: "#333", |
| | | fontSize: 16, |
| | | }, |
| | | }, |
| | | tooltip: { |
| | | trigger: "item", |
| | | formatter: "{a} <br/>{b}: {c} ({d}%)", |
| | | }, |
| | | legend: { |
| | | orient: "vertical", |
| | | left: "left", |
| | | data: ["å¾
é访", "é访æå", "é访失败"], |
| | | textStyle: { |
| | | color: "#666", |
| | | }, |
| | | }, |
| | | color: ["#FF9D4D", "#36B37E", "#FF5C5C"], // æ°çé
è²æ¹æ¡ |
| | | series: [ |
| | | { |
| | | name: "éè®¿ç¶æ", |
| | | type: "pie", |
| | | radius: ["40%", "70%"], |
| | | avoidLabelOverlap: true, |
| | | itemStyle: { |
| | | borderRadius: 10, |
| | | borderColor: "#fff", |
| | | borderWidth: 2, |
| | | }, |
| | | label: { |
| | | show: true, |
| | | formatter: "{b}: {c} ({d}%)", |
| | | color: "#333", |
| | | }, |
| | | emphasis: { |
| | | label: { |
| | | show: true, |
| | | fontSize: "18", |
| | | fontWeight: "bold", |
| | | }, |
| | | itemStyle: { |
| | | shadowBlur: 10, |
| | | shadowOffsetX: 0, |
| | | shadowColor: "rgba(0, 0, 0, 0.5)", |
| | | }, |
| | | }, |
| | | data: [ |
| | | { |
| | | value: followUpData.pending, |
| | | name: "å¾
é访", |
| | | }, |
| | | { |
| | | value: followUpData.success, |
| | | name: "é访æå", |
| | | }, |
| | | { |
| | | value: followUpData.fail, |
| | | name: "é访失败", |
| | | }, |
| | | ], |
| | | }, |
| | | ], |
| | | }; |
| | | |
| | | this.pieChart.setOption(pieOption); |
| | | window.addEventListener("resize", this.resizePieChart); |
| | | }, |
| | | |
| | | // åå§åæ±ç¶æçº¿å¾ |
| | | initBarLineChart() { |
| | | const echarts = require("echarts"); |
| | | const barDom = document.getElementById("barLineChart"); |
| | | if (!barDom) return; |
| | | |
| | | if (this.barLineChart) { |
| | | this.barLineChart.dispose(); |
| | | } |
| | | |
| | | this.barLineChart = echarts.init(barDom); |
| | | |
| | | // å夿°æ® |
| | | const categories = this.userList.map( |
| | | (item) => item.leavehospitaldistrictname || item.deptname |
| | | ); |
| | | |
| | | const dischargeData = this.userList.map( |
| | | (item) => item.dischargeCount || 0 |
| | | ); |
| | | const followUpData = this.userList.map( |
| | | (item) => item.followUpNeeded || 0 |
| | | ); |
| | | |
| | | // æ°å¢ä¸¤æ¡æçº¿æ°æ® |
| | | const followUpRateData = this.userList.map((item) => { |
| | | if (!item.followUpRate) return 0; |
| | | // 廿ç¾åå·å¹¶è½¬ä¸ºæ°å |
| | | const rateStr = String(item.followUpRate).replace("%", ""); |
| | | return parseFloat(rateStr) || 0; |
| | | }); |
| | | |
| | | const timelyRateData = this.userList.map((item) => |
| | | item.rate ? (Number(item.rate) * 100).toFixed(2) : 0 |
| | | ); |
| | | |
| | | const option = { |
| | | title: { |
| | | text: "ç§å®¤/ç
åºé访è¶å¿", |
| | | left: "center", |
| | | textStyle: { |
| | | color: "#333", |
| | | fontSize: 16, |
| | | }, |
| | | }, |
| | | tooltip: { |
| | | trigger: "axis", |
| | | axisPointer: { |
| | | type: "cross", |
| | | crossStyle: { |
| | | color: "#999", |
| | | }, |
| | | }, |
| | | }, |
| | | legend: { |
| | | data: ["åºé¢äººæ¬¡", "åºé访人次", "é访ç(%)", "åæ¶ç(%)"], |
| | | top: "bottom", |
| | | textStyle: { |
| | | color: "#666", |
| | | }, |
| | | }, |
| | | color: ["#5470C6", "#91CC75", "#EE6666", "#9A60B4"], // æ°å¢ç´«è²ç¨äºåæ¶ç |
| | | xAxis: { |
| | | type: "category", |
| | | data: categories, |
| | | axisLabel: { |
| | | interval: 0, |
| | | rotate: 30, |
| | | color: "#666", |
| | | }, |
| | | axisLine: { |
| | | lineStyle: { |
| | | color: "#ddd", |
| | | }, |
| | | }, |
| | | }, |
| | | yAxis: [ |
| | | { |
| | | type: "value", |
| | | name: "人次", |
| | | min: 0, |
| | | axisLabel: { |
| | | color: "#666", |
| | | }, |
| | | axisLine: { |
| | | lineStyle: { |
| | | color: "#ddd", |
| | | }, |
| | | }, |
| | | splitLine: { |
| | | lineStyle: { |
| | | color: "#f0f0f0", |
| | | }, |
| | | }, |
| | | }, |
| | | { |
| | | type: "value", |
| | | name: "ç¾åæ¯(%)", |
| | | min: 0, |
| | | max: 100, |
| | | axisLabel: { |
| | | color: "#666", |
| | | formatter: "{value}%", |
| | | }, |
| | | axisLine: { |
| | | lineStyle: { |
| | | color: "#ddd", |
| | | }, |
| | | }, |
| | | splitLine: { |
| | | show: false, |
| | | }, |
| | | }, |
| | | ], |
| | | series: [ |
| | | { |
| | | name: "åºé¢äººæ¬¡", |
| | | type: "bar", |
| | | barWidth: "25%", |
| | | data: dischargeData, |
| | | itemStyle: { |
| | | borderRadius: [4, 4, 0, 0], |
| | | }, |
| | | }, |
| | | { |
| | | name: "åºé访人次", |
| | | type: "bar", |
| | | barWidth: "25%", |
| | | data: followUpData, |
| | | itemStyle: { |
| | | borderRadius: [4, 4, 0, 0], |
| | | }, |
| | | }, |
| | | { |
| | | name: "é访ç(%)", |
| | | type: "line", |
| | | yAxisIndex: 1, |
| | | data: followUpRateData, |
| | | symbolSize: 8, |
| | | lineStyle: { |
| | | width: 3, |
| | | }, |
| | | markLine: { |
| | | silent: true, |
| | | data: [ |
| | | { |
| | | yAxis: 80, |
| | | lineStyle: { |
| | | color: "#EE6666", |
| | | type: "dashed", |
| | | }, |
| | | // label: { |
| | | // position: 'end', |
| | | // formatter: 'ç®æ 80%' |
| | | // } |
| | | }, |
| | | ], |
| | | }, |
| | | }, |
| | | { |
| | | name: "åæ¶ç(%)", |
| | | type: "line", |
| | | yAxisIndex: 1, |
| | | data: timelyRateData, |
| | | symbolSize: 8, |
| | | lineStyle: { |
| | | width: 3, |
| | | type: "dotted", // 使ç¨è线åºå |
| | | }, |
| | | markLine: { |
| | | silent: true, |
| | | data: [ |
| | | { |
| | | yAxis: 90, |
| | | lineStyle: { |
| | | color: "#9A60B4", |
| | | type: "dashed", |
| | | }, |
| | | // label: { |
| | | // position: 'end', |
| | | // formatter: 'ç®æ 90%' |
| | | // } |
| | | }, |
| | | ], |
| | | }, |
| | | }, |
| | | ], |
| | | grid: { |
| | | top: "15%", |
| | | left: "3%", |
| | | right: "4%", |
| | | bottom: "15%", |
| | | containLabel: true, |
| | | }, |
| | | }; |
| | | |
| | | this.barLineChart.setOption(option); |
| | | window.addEventListener("resize", this.resizeBarLineChart); |
| | | }, |
| | | |
| | | // å¾è¡¨ååºå¼è°æ´æ¹æ³ |
| | | resizePieChart() { |
| | | if (this.pieChart) { |
| | | this.pieChart.resize(); |
| | | } |
| | | }, |
| | | |
| | | resizeBarLineChart() { |
| | | if (this.barLineChart) { |
| | | this.barLineChart.resize(); |
| | | } |
| | | }, |
| | | |
| | | // å¨ç»ä»¶éæ¯æ¶æ¸
ç |
| | | beforeDestroy() { |
| | | // ç§»é¤äºä»¶çå¬ |
| | | window.removeEventListener("resize", this.resizePieChart); |
| | | window.removeEventListener("resize", this.resizeBarLineChart); |
| | | |
| | | // 鿝å¾è¡¨å®ä¾ |
| | | if (this.pieChart) { |
| | | this.pieChart.dispose(); |
| | | this.pieChart = null; |
| | | } |
| | | if (this.barLineChart) { |
| | | this.barLineChart.dispose(); |
| | | this.barLineChart = null; |
| | | } |
| | | }, |
| | | }, |
| | | }; |
| | | handleSearch() { |
| | | // æç´¢é»è¾ |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | ::v-deep .el-tabs__header { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | ::v-deep .el-tabs__item { |
| | | font-size: 16px; |
| | | padding: 0 20px; |
| | | height: 40px; |
| | | line-height: 40px; |
| | | } |
| | | |
| | | ::v-deep .el-tabs__active-bar { |
| | | height: 3px; |
| | | } |
| | | |
| | | /* Tabå
容åºåæ ·å¼ */ |
| | | .el-tab-pane { |
| | | .your-table-container { |
| | | margin-top: 10px; |
| | | } |
| | | } |
| | | .sidecolumn { |
| | | width: 180px; |
| | | min-height: 100vh; |
| | | text-align: center; |
| | | // display: flex; |
| | | margin-top: 20px; |
| | | margin: 20px; |
| | | padding: 30px; |
| | | background: #edf1f7; |
| | | border: 1px solid #dcdfe6; |
| | | -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), |
| | | 0 0 6px 0 rgba(0, 0, 0, 0.04); |
| | | .sidecolumn-top { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | .top-wj { |
| | | font-size: 20px; |
| | | } |
| | | .top-tj { |
| | | font-size: 18px; |
| | | |
| | | color: rgb(0, 89, 255); |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | .center-ss { |
| | | margin-top: 30px; |
| | | .input-with-select { |
| | | height: 40px !important; |
| | | } |
| | | } |
| | | .bottom-fl { |
| | | margin-top: 30px; |
| | | display: center !important; |
| | | } |
| | | } |
| | | .qrcode-dialo { |
| | | text-align: center; |
| | | // display: flex; |
| | | margin: 20px; |
| | | padding: 30px; |
| | | background: #edf1f7; |
| | | border: 1px solid #dcdfe6; |
| | | -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), |
| | | 0 0 6px 0 rgba(0, 0, 0, 0.04); |
| | | .qrcode-text { |
| | | font-size: 20px; |
| | | span { |
| | | margin-left: 20px; |
| | | } |
| | | } |
| | | .qrcode-img { |
| | | width: 300px; |
| | | height: 400px; |
| | | } |
| | | } |
| | | ::v-deep.el-tabs--left, |
| | | .el-tabs--right { |
| | | overflow: hidden; |
| | | align-items: center; |
| | | display: flex; |
| | | } |
| | | ::v-deep.el-input--medium .el-input__inner { |
| | | height: 40px !important; |
| | | } |
| | | ::v-deep.el-tabs--right .el-tabs__active-bar.is-right { |
| | | height: 40px; |
| | | width: 5px; |
| | | left: 0; |
| | | } |
| | | ::v-deep.el-tabs--right .el-tabs__item.is-right { |
| | | display: block; |
| | | text-align: left; |
| | | font-size: 20px; |
| | | } |
| | | // ç¾ååè®¡è¡æ ·å¼ |
| | | ::v-deep .el-table__footer { |
| | | .el-table__cell { |
| | | background-color: #f5f7fa; |
| | | font-weight: 600; |
| | | color: #409eff; |
| | | |
| | | .cell { |
| | | font-weight: 600; |
| | | color: #409eff; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // å
é¨è¡¨æ ¼åè®¡è¡æ ·å¼ |
| | | ::v-deep .inner-table .el-table__footer { |
| | | .el-table__cell { |
| | | background-color: #ecf5ff; |
| | | font-weight: 500; |
| | | color: #67c23a; |
| | | |
| | | .cell { |
| | | font-weight: 500; |
| | | color: #67c23a; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // ç¾åæ¯åæ®µç¹æ®æ ·å¼ |
| | | .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; |
| | | } |
| | | |
| | | .leftvlue { |
| | | // display: flex; |
| | | // flex: 1; |
| | | // width: 80%; |
| | | // margin-top: 20px; |
| | | margin: 20px; |
| | | padding: 30px; |
| | | .follow-up-statistics { |
| | | padding: 20px; |
| | | background: #ffff; |
| | | border: 1px solid #dcdfe6; |
| | | -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), |
| | | 0 0 6px 0 rgba(0, 0, 0, 0.04); |
| | | .mulsz { |
| | | font-size: 20px; |
| | | } |
| | | } |
| | | /* ä½¿è¡ææåæé */ |
| | | .el-table__row { |
| | | cursor: pointer; |
| | | } |
| | | /* å
å±å»çè¡¨æ ¼æ ·å¼ */ |
| | | .inner-table { |
| | | // è¡¨å¤´èæ¯è² |
| | | ::v-deep .el-table__header-wrapper { |
| | | background-color: #f0f7ff !important; |
| | | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), 0 0 6px 0 rgba(0, 0, 0, 0.04); |
| | | |
| | | th { |
| | | background-color: #f0f7ff !important; |
| | | .search-section { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .tab-section { |
| | | ::v-deep .el-tabs__header { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | ::v-deep .el-tabs__item { |
| | | font-size: 16px; |
| | | padding: 0 20px; |
| | | height: 40px; |
| | | line-height: 40px; |
| | | } |
| | | |
| | | ::v-deep .el-tabs__active-bar { |
| | | height: 3px; |
| | | } |
| | | } |
| | | |
| | | // è¡¨æ ¼è¡èæ¯è² |
| | | ::v-deep .el-table__body-wrapper { |
| | | tr { |
| | | background-color: #f9fbfe !important; |
| | | |
| | | &:hover { |
| | | background-color: #e6f1ff !important; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // è¾¹æ¡é¢è² |
| | | ::v-deep .el-table--border { |
| | | border-color: #d9e8ff !important; |
| | | |
| | | td, |
| | | th { |
| | | border-color: #d9e8ff !important; |
| | | } |
| | | } |
| | | |
| | | // æé©¬çº¹ææ |
| | | ::v-deep .el-table--striped .el-table__body tr.el-table__row--striped td { |
| | | background-color: #f5f9ff !important; |
| | | } |
| | | } |
| | | /* å±å¼è¡æ ·å¼ */ |
| | | .el-table__expanded-cell { |
| | | padding: 10px 0 !important; |
| | | background: #f8f8f8; |
| | | } |
| | | .document { |
| | | width: 100px; |
| | | height: 50px; |
| | | } |
| | | .data-list { |
| | | max-height: 800px; |
| | | overflow-y: auto; |
| | | } |
| | | .documentf { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | } |
| | | .button-text { |
| | | color: rgb(70, 204, 238); |
| | | } |
| | | .button-textck { |
| | | color: rgb(39, 167, 67); |
| | | } |
| | | .button-textxg { |
| | | color: rgb(35, 81, 233); |
| | | } |
| | | .button-textsc { |
| | | color: rgb(235, 23, 23); |
| | | } |
| | | </style> |
| | |
| | | // detail: https://cli.vuejs.org/config/#devserver-proxy |
| | | [process.env.VUE_APP_BASE_API]: { |
| | | // target: `https://www.health-y.cn/lssf`, |
| | | target: `http://192.168.100.10:8096`, |
| | | // target: `http://192.168.100.10:8094`,//çç«åå¾· |
| | | // target: `http://192.168.100.10:8096`, |
| | | target: `http://192.168.100.10:8094`,//çç«åå¾· |
| | | // target: `http://192.168.100.10:8095`,//æ°å |
| | | // target: `http://192.168.100.10:8098`,//å¸ä¸ |
| | | // target:`http://localhost:8095`, |
| | | // target:`http://35z1t16164.qicp.vip`, |
| | | // target: `http://192.168.100.172:8095`, |