From 449f7391d38bff272e5d928bb945f5f27b668220 Mon Sep 17 00:00:00 2001 From: WXL (wul) <wl_5969728@163.com> Date: 星期日, 24 八月 2025 12:24:42 +0800 Subject: [PATCH] 统计趋势图 --- src/views/sfstatistics/percentage/index.vue | 769 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 710 insertions(+), 59 deletions(-) diff --git a/src/views/sfstatistics/percentage/index.vue b/src/views/sfstatistics/percentage/index.vue index e919b2f..bb119e0 100644 --- a/src/views/sfstatistics/percentage/index.vue +++ b/src/views/sfstatistics/percentage/index.vue @@ -1,37 +1,6 @@ <template> <div class="Questionnairemanagement"> - <!-- 宸︿晶鏍� --> - <!-- <div class="sidecolumn"> - <div class="sidecolumn-top"> - <div class="top-wj">鎮h�呰寖鍥�</div> - </div> - - <div class="bottom-fl"> - <el-tabs - tab-position="right" - v-model="activeName" - @tab-click="handleClick" - > - <el-tab-pane label="鍏ㄩ儴" name="first"></el-tab-pane> - <el-tab-pane label="浣忛櫌" name="bhospitalized"></el-tab-pane> - <el-tab-pane label="鍦ㄩ櫌" name="Inhospital"></el-tab-pane> - <el-tab-pane label="闂ㄨ瘖" name="outpatient"></el-tab-pane> - <el-tab-pane label="浣撴" name="physical"></el-tab-pane> - </el-tabs> - </div> - </div> --> - <!-- 鍙充晶鏁版嵁 --> <div class="leftvlue"> - <!-- <div class="leftvlue-top"> - <el-tabs v-model="topactiveName" @tab-click="tophandleClick"> - <el-tab-pane name="Local"> - <span class="mulsz" slot="label">鎸夊嚭闄㈢梾鍖虹粺璁� </span> - </el-tab-pane> - <el-tab-pane name="sharing"> - <span class="mulsz" slot="label">鎸夊嚭闄㈢瀹ょ粺璁� </span> - </el-tab-pane> - </el-tabs> - </div> --> <div class="leftvlue-bg"> <el-row :gutter="20"> <!--鏍囩鏁版嵁--> @@ -44,17 +13,6 @@ v-show="showSearch" label-width="98px" > - <!-- <el-form-item label="鍖婚櫌" prop="userName"> - <el-select v-model="queryParams.value1" 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="缁熻绫诲瀷" prop="userName"> <el-select v-model="queryParams.statisticaltype" @@ -150,7 +108,7 @@ > </el-form-item> <el-col :span="19"> - <el-button + <el-button type="warning" plain icon="el-icon-download" @@ -158,19 +116,230 @@ @click="handleExport" >瀵煎嚭</el-button > - </el-col> + <el-button + type="primary" + plain + icon="el-icon-data-line" + size="medium" + @click="showChartDialog" + >缁熻瓒嬪娍鍥�</el-button + > + </el-col> </el-form> - <!-- <right-toolbar - :showSearch.sync="showSearch" - @queryTable="getList" - :columns="columns" - ></right-toolbar> --> <el-table v-loading="loading" :data="userList" :border="true" @selection-change="handleSelectionChange" + @row-click="handleRowClick" + @expand-change="handleRowClick" + :row-key="getRowKey" + :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" + > + <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" + > + <!-- <template slot-scope="scope"> + <span + >{{ + (Number(scope.row.followUpRate) * 100).toFixed(2) + }}%</span + > + </template> --> + </el-table-column> + <el-table-column + 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-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" + > + <!-- <template slot-scope="scope"> + <span + >{{ + (Number(scope.row.FollowUpRateAgain) * 100).toFixed(2) + }}%</span + > + </template> --> + </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" @@ -374,6 +543,26 @@ </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" @@ -649,9 +838,13 @@ return { topactiveName: "Local", //椤堕儴閫夋嫨 activeName: "first", //渚ц竟閫夋嫨 + expands: [], // 閬僵灞� loading: false, Seedloading: false, + chartDialogVisible: false, + pieChart: null, + barLineChart: null, // 閫変腑鏁扮粍 ids: [], // 闈炲崟涓鐢� @@ -708,6 +901,10 @@ postOptions: [], // 瑙掕壊閫夐」 roleOptions: [], + // 瀛樺偍鎵�鏈夌瀹や唬鐮� + allDeptCodes: [], + // 瀛樺偍鎵�鏈夌梾鍖轰唬鐮� + allWardCodes: [], // 琛ㄥ崟鍙傛暟 form: {}, forms: { @@ -784,6 +981,8 @@ serviceType: [2], dateRange: [], statisticaltype: 1, + leavehospitaldistrictcodes: ["all"], // 榛樿閫変腑鍏ㄩ儴鐥呭尯 + deptcodes: [], // 榛樿閫変腑鍏ㄩ儴绉戝 }, // 鍒椾俊鎭� columns: [ @@ -799,18 +998,68 @@ }, watch: {}, created() { - this.getList(); this.getDeptTree(); + this.getList(); }, methods: { /** 鏌ヨ鏍囩鍒楄〃 */ getList() { - getSfStatistics(this.queryParams).then((response) => { + // 澶勭悊鏌ヨ鍙傛暟 + const params = { + ...this.queryParams, + // 濡傛灉閫夋嫨浜�"鍏ㄩ儴"锛屽垯浼犳墍鏈夌梾鍖�/绉戝浠g爜 + leavehospitaldistrictcodes: + this.queryParams.leavehospitaldistrictcodes.includes("all") + ? this.allWardCodes + : this.queryParams.leavehospitaldistrictcodes, + deptcodes: this.queryParams.deptcodes.includes("all") + ? this.allDeptCodes + : this.queryParams.deptcodes, + }; + + // 绉婚櫎鍙兘瀛樺湪鐨�"all"鍊� + delete params.leavehospitaldistrictcodes.all; + delete params.deptcodes.all; + getSfStatistics(params).then((response) => { console.log(response); // this.total = response.total; this.userList = response.data; }); + }, + 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, + // 濡傛灉閫夋嫨浜�"鍏ㄩ儴"锛屽垯浼犳墍鏈夌梾鍖�/绉戝浠g爜 + leavehospitaldistrictcodes: [row.leavehospitaldistrictcode], + drcode: "1", + }; + // 濡傛灉璇ヨ杩樻病鏈夊姞杞藉尰鐢熸暟鎹紝鍒欏姞杞� + 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)]; + } }, /** 淇敼鏍囩 */ handleUpdate(row) { @@ -834,17 +1083,25 @@ value: dept.deptCode, }; }); - this.flatArrayhospit = store.getters.belongWards.map((dept) => { + // 瀛樺偍鎵�鏈夌瀹や唬鐮� + this.allDeptCodes = store.getters.belongDepts.map( + (dept) => dept.deptCode + ); + + // 鐥呭尯鍒楄〃 + this.flatArrayhospit = store.getters.belongWards.map((ward) => { return { - label: dept.districtName, - value: dept.districtCode, + label: ward.districtName, + value: ward.districtCode, }; }); - // deptTreeSelect().then((response) => { - // this.deptOptions = response.data; - // console.log(this.deptOptions, " this.deptOptions"); - // this.flatArray = this.flattenArray(response.data); - // }); + + // 瀛樺偍鎵�鏈夌梾鍖轰唬鐮� + 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 = []; @@ -1038,6 +1295,354 @@ `user_${new Date().getTime()}.xlsx` ); }, + // 鏄剧ず鍥捐〃寮圭獥 + + showChartDialog() { + this.chartDialogVisible = true; + this.$nextTick(() => { + this.initPieChart(); + this.initBarLineChart(); + }); + }, + // 鍦╩ethods涓慨鏀圭粺璁℃柟娉� + 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> @@ -1134,6 +1739,52 @@ 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; -- Gitblit v1.9.3