InsurIncomeAnalysis.vue 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102
  1. <template>
  2. <el-container>
  3. <el-header style="height: 35px; margin-top: 5px; padding: 0 5px">
  4. <el-date-picker v-model="dateRange" type="monthrange" range-separator="至" start-placeholder="开始月份"
  5. end-placeholder="结束月份" style="width: 220px">
  6. </el-date-picker>
  7. <el-cascader v-model="setlCondition.dataInfo" :options="setlCondition.options" :props="{ expandTrigger: 'hover' }"
  8. @change="handleChange" :clearable="true" :filterable="true" placeholder="请选择险种">
  9. </el-cascader>
  10. <el-divider direction="vertical"></el-divider>
  11. <el-button icon="Search" type="success" @click="fetchSetlinfos">查询</el-button>
  12. <el-button icon="Download" type="primary" @click="exportSetlinfoExcel">导出Excel</el-button>
  13. <el-button type="primary" @click="selectChart">分析图</el-button>
  14. </el-header>
  15. <el-main>
  16. <el-tabs type="border-card" v-model="setlCondition.selectType" @tab-click="handleClick">
  17. <el-tab-pane label="数据" name="first">
  18. <el-table :data="setlinfos" :height="tableHeight" border highlight-current-row row-key="childKey" show-summary
  19. :summary-method="getSummaries1" stripe @row-dblclick="fetchSetldetails">
  20. <el-table-column label="险种类型" prop="insurName" fixed header-align="center"></el-table-column>
  21. <el-table-column label="住院人次" prop="psnCount" align="center" header-align="center"></el-table-column>
  22. <el-table-column label="住院天数" prop="inDays" align="center" header-align="center"></el-table-column>
  23. <el-table-column label="平均住院日" prop="avgInDays" align="right" header-align="center"></el-table-column>
  24. <el-table-column label="总费用" prop="totalFee" align="right" header-align="center"></el-table-column>
  25. <el-table-column label="药品费用" prop="drugFee" align="right" header-align="center"></el-table-column>
  26. <el-table-column label="药品占比(%)" prop="drugFeeRatio" align="right" header-align="center"></el-table-column>
  27. <el-table-column label="耗材费用" prop="matFee" align="right" header-align="center"></el-table-column>
  28. <el-table-column label="耗材占比(%)" prop="matFeeRatio" align="right" header-align="center"></el-table-column>
  29. <el-table-column label="基本医疗统筹金额" prop="fundPooling" align="right" header-align="center"></el-table-column>
  30. <el-table-column label="大病基金" prop="bigIllFundPooling" align="right" header-align="center">
  31. </el-table-column>
  32. <el-table-column label="公务员基金支付" prop="civilServiceFund" align="right" header-align="center">
  33. </el-table-column>
  34. <el-table-column label="其他基金" prop="otherFunds" align="right" header-align="center"></el-table-column>
  35. <el-table-column label="全部基金" prop="allFunds" align="right" header-align="center"></el-table-column>
  36. </el-table>
  37. <el-dialog v-model="showSetldetails" :close-on-click-modal="false" :close-on-press-escape="false"
  38. :title="filterDialogTitle" width="70%">
  39. <div style="width: 130px; height: 36px; position: absolute; top: 16px; right: 60px">
  40. <el-button icon="Download" type="primary" @click="exportYbDetailExcel">导出Excel</el-button>
  41. </div>
  42. <el-table :data="setldetails.slice(pageSize * (currentPage - 1), pageSize * currentPage)" height="560"
  43. highlight-current-row stripe @row-dblclick="openSetlinfoComponent">
  44. <el-table-column fixed label="序号" type="index" width="40"></el-table-column>
  45. <el-table-column fixed label="姓名" prop="psnName" width="60"></el-table-column>
  46. <el-table-column label="住院号" prop="patNo" width="70"></el-table-column>
  47. <el-table-column label="次数" prop="times" width="40"></el-table-column>
  48. <el-table-column label="性别" prop="gendName" width="50"></el-table-column>
  49. <el-table-column label="出生日期" prop="brdy"></el-table-column>
  50. <el-table-column label="身份证" prop="certno"></el-table-column>
  51. <el-table-column label="参保地区" prop="insuplcAdmdvsName"></el-table-column>
  52. <el-table-column label="险种类型" prop="insutypeName"></el-table-column>
  53. <el-table-column label="人员类别" prop="psnTypeName"></el-table-column>
  54. <el-table-column label="就诊ID" prop="mdtrtId"></el-table-column>
  55. <el-table-column label="结算ID" prop="setlId"></el-table-column>
  56. <el-table-column label="入院时间" prop="begntime"></el-table-column>
  57. <el-table-column label="出院时间" prop="endtime"></el-table-column>
  58. <el-table-column label="结算时间" prop="setlTime"></el-table-column>
  59. <el-table-column label="医疗类别" prop="medTypeName"></el-table-column>
  60. <el-table-column label="总费用" prop="medfeeSumamt"></el-table-column>
  61. <el-table-column label="报销金额" prop="fundPaySumamt"></el-table-column>
  62. <el-table-column label="医疗救助" prop="mafPay"></el-table-column>
  63. <el-table-column label="个人账户支出" prop="acctPay"></el-table-column>
  64. <el-table-column label="个人现金支出" prop="psnCashPay"></el-table-column>
  65. <el-table-column label="大病支出" prop="hifmiPay"></el-table-column>
  66. <el-table-column label="西药费" prop="chargeWesternMedicine"></el-table-column>
  67. <el-table-column label="中成药费" prop="chargePatentMedicine"></el-table-column>
  68. <el-table-column label="中药饮片费" prop="chargeHerbal"></el-table-column>
  69. <el-table-column label="耗材费" prop="chargeSanitaryMaterial"></el-table-column>
  70. </el-table>
  71. <el-pagination :current-page="currentPage" :page-size="pageSize" :page-sizes="[15, 30, 45, 60]"
  72. :total="setldetails.length" layout="total, sizes, prev, pager, next, jumper" style="margin-top: 5px"
  73. @size-change="handleSizeChange" @current-change="handleCurrentChange"></el-pagination>
  74. </el-dialog>
  75. <el-dialog v-model="showSetlinfoComponent" :close-on-click-modal="false" title="结算信息" width="70%">
  76. <Setlinfo :setlinfo="currentSetldetail" />
  77. </el-dialog>
  78. </el-tab-pane>
  79. <el-tab-pane label="同比" name="second">
  80. <el-table :data="setlinfos" :height="tableHeight" border highlight-current-row row-key="childKey" show-summary
  81. :summary-method="getSummaries1">
  82. <el-table-column label="月份" prop="month" fixed align="center" header-align="center"></el-table-column>
  83. <el-table-column label="总费用" prop="zfy" header-align="center">
  84. <el-table-column label="今年" prop="zfy_jn" align="right" header-align="center"></el-table-column>
  85. <el-table-column label="去年" prop="zfy_qn" align="right" header-align="center"></el-table-column>
  86. <el-table-column label="同比" prop="zfy_tb" align="right" header-align="center"></el-table-column>
  87. </el-table-column>
  88. <el-table-column label="全部基金" prop="zjj" header-align="center">
  89. <el-table-column label="今年" prop="zjj_jn" align="right" header-align="center"></el-table-column>
  90. <el-table-column label="去年" prop="zjj_qn" align="right" header-align="center"></el-table-column>
  91. <el-table-column label="同比" prop="zjj_tb" align="right" header-align="center"></el-table-column>
  92. </el-table-column>
  93. <el-table-column label="药品费用" prop="ypf" header-align="center">
  94. <el-table-column label="今年" prop="ypf_jn" align="right" header-align="center"></el-table-column>
  95. <el-table-column label="去年" prop="ypf_qn" align="right" header-align="center"></el-table-column>
  96. <el-table-column label="同比" prop="ypf_tb" align="right" header-align="center"></el-table-column>
  97. </el-table-column>
  98. <el-table-column label="耗材费用" prop="clf" header-align="center">
  99. <el-table-column label="今年" prop="clf_jn" align="right" header-align="center"></el-table-column>
  100. <el-table-column label="去年" prop="clf_qn" align="right" header-align="center"></el-table-column>
  101. <el-table-column label="同比" prop="clf_tb" align="right" header-align="center"></el-table-column>
  102. </el-table-column>
  103. </el-table>
  104. </el-tab-pane>
  105. <el-tab-pane label="环比" name="third">
  106. <el-table :data="setlinfos" :height="tableHeight" border highlight-current-row row-key="childKey" show-summary
  107. :summary-method="getSummaries1">
  108. <el-table-column label="月份" prop="month" align="center" fixed header-align="center"></el-table-column>
  109. <el-table-column label="总费用" prop="zfys" header-align="center">
  110. <el-table-column label="费用" prop="zfy" align="right" header-align="center"></el-table-column>
  111. <el-table-column label="环比" prop="zfy_hb" align="right" header-align="center"></el-table-column>
  112. </el-table-column>
  113. <el-table-column label="全部基金" prop="zjjs" header-align="center">
  114. <el-table-column label="费用" prop="zjj" align="right" header-align="center"></el-table-column>
  115. <el-table-column label="环比" prop="zjj_hb" align="right" header-align="center"></el-table-column>
  116. </el-table-column>
  117. <el-table-column label="药品费用" prop="ypfs" header-align="center">
  118. <el-table-column label="费用" prop="ypf" align="right" header-align="center"></el-table-column>
  119. <el-table-column label="环比" prop="ypf_hb" align="right" header-align="center"></el-table-column>
  120. </el-table-column>
  121. <el-table-column label="耗材费用" prop="clfs" header-align="center">
  122. <el-table-column label="费用" prop="clf" align="right" header-align="center"></el-table-column>
  123. <el-table-column label="环比" prop="clf_hb" align="right" header-align="center"></el-table-column>
  124. </el-table-column>
  125. </el-table>
  126. </el-tab-pane>
  127. </el-tabs>
  128. </el-main>
  129. <el-drawer :title="titleChart" v-model="qxtDrawer" size="80%">
  130. <!-- <div style="width: 100%; height: 90%" id="ybChart"></div> -->
  131. <el-main>
  132. <el-row :gutter="10">
  133. <el-col :span="6">
  134. <div style="width: 100%; height: 400px" id="zfyDst"></div>
  135. </el-col>
  136. <el-col :span="6">
  137. <div style="width: 100%; height: 400px" id="zjjDst"></div>
  138. </el-col>
  139. <el-col :span="6">
  140. <div style="width: 100%; height: 400px" id="ypfDst"></div>
  141. </el-col>
  142. <el-col :span="6">
  143. <div style="width: 100%; height: 400px" id="clfDst"></div>
  144. </el-col>
  145. </el-row>
  146. <el-row :gutter="10">
  147. <!-- <el-form-item label="汇总项">
  148. <el-select v-model="pieChartData.selectPie" class="m-2" placeholder="请选择">
  149. <el-option label="住院人次" value="1"></el-option>
  150. <el-option label="住院天数" value="2"></el-option>
  151. <el-option label="总费用" value="3"></el-option>
  152. </el-select>
  153. </el-form-item> -->
  154. <el-col :span="8">
  155. <div style="width: 100%; height: 400px" id="rcpie"></div>
  156. </el-col>
  157. <el-col :span="8">
  158. <div style="width: 100%; height: 400px" id="zytsPie"></div>
  159. </el-col>
  160. <el-col :span="8">
  161. <div style="width: 100%; height: 400px" id="zfyPie"></div>
  162. </el-col>
  163. </el-row>
  164. </el-main>
  165. </el-drawer>
  166. </el-container>
  167. </template>
  168. <script>
  169. import { computed, onMounted, reactive, ref, watch } from 'vue'
  170. import { useStore } from 'vuex'
  171. import store from '@/store'
  172. import { getDateRangeFormatDate, formatDatetime } from '@/utils/date'
  173. import {
  174. selectYbStatInfo, selectYbStatRatio, selectYbChart, selectYbStatDetail, querySettlementInfo
  175. } from '@/api/medical-insurance/si-ybkf'
  176. import { clone } from '@/utils/clone'
  177. import { Export } from '@/utils/ExportExcel'
  178. import { ElMessage, ElMessageBox } from 'element-plus'
  179. import { downloadExcel } from '@/utils/excel'
  180. import { pieUtilsOne, barUtilsTwo } from '@/utils/echarts-utils'
  181. import Setlinfo from '../../../components/medical-insurance/setlinfo/Index.vue'
  182. export default {
  183. components: {
  184. Setlinfo,
  185. },
  186. setup() {
  187. const storeU = useStore()
  188. const windowSize = storeU.state.app.windowSize
  189. const tableHeight = windowSize.h - 120
  190. const dateRange = ref([])
  191. const dateS = getDateRangeFormatDate(dateRange.value)
  192. const setlinfos = ref([])
  193. const qxtDrawer = ref(false)
  194. const titleChart = ref('图形')
  195. const chartData = ref([])
  196. const pieChartData = reactive({
  197. selectPie: '1'
  198. })
  199. const setldetails = ref([])
  200. const showSetldetails = ref(false)
  201. const setlCondition = reactive({
  202. startTime: dateS.startTime,
  203. endTime: dateS.endTime,
  204. setlType: '21',
  205. selectType: 'first',
  206. insurType: null,
  207. dataInfo: null,
  208. options: initInsurOptions(),
  209. })
  210. const fetchSetldetails = (row) => {
  211. let selectInfo = clone(setlCondition)
  212. selectInfo.insurType = row.insurType
  213. selectYbStatDetail(selectInfo)
  214. .then((res) => {
  215. setldetails.value = res
  216. showSetldetails.value = true
  217. })
  218. .catch(() => {
  219. setldetails.value = []
  220. })
  221. }
  222. const filterDialogTitle = computed(() => {
  223. let yearL = setlCondition.startTime.substr(0, 4)
  224. const setlTypeName = filterSetlTypeName()
  225. return yearL + setlTypeName + '结算明细'
  226. })
  227. const showSetlinfoComponent = ref(false)
  228. const currentSetldetail = ref({})
  229. const openSetlinfoComponent = (row) => {
  230. const param = {
  231. psnNo: row.psnNo,
  232. mdtrtId: row.mdtrtId,
  233. }
  234. querySettlementInfo(param).then((res) => {
  235. currentSetldetail.value = res
  236. showSetlinfoComponent.value = true
  237. })
  238. }
  239. const fetchSetlinfos = () => {
  240. if (!dateRange.value) {
  241. ElMessage({
  242. message: '请选择时间范围!',
  243. type: 'warning',
  244. duration: 2500,
  245. showClose: true,
  246. })
  247. return
  248. }
  249. if (!setlCondition.dataInfo) {
  250. ElMessage({
  251. message: '请选择险种!',
  252. type: 'warning',
  253. duration: 2500,
  254. showClose: true,
  255. })
  256. return
  257. }
  258. setlCondition.setlType = setlCondition.dataInfo[0]
  259. setlCondition.insurType = setlCondition.dataInfo[1]
  260. setlCondition.startTime = formatDatetime(dateRange.value[0])
  261. setlCondition.endTime = formatDatetime(dateRange.value[1])
  262. let yearL = setlCondition.startTime.substr(0, 4)
  263. let yearR = setlCondition.endTime.substr(0, 4)
  264. if (yearL != yearR) {
  265. ElMessage({
  266. message: '请选择同一年份!',
  267. type: 'warning',
  268. duration: 2500,
  269. showClose: true,
  270. })
  271. return
  272. }
  273. if (setlCondition.selectType === "first") {
  274. selectYbStatInfo(setlCondition)
  275. .then((res) => {
  276. setlinfos.value = res
  277. })
  278. .catch(() => {
  279. setlinfos.value = []
  280. })
  281. } else {
  282. selectYbStatRatio(setlCondition)
  283. .then((res) => {
  284. setlinfos.value = res
  285. })
  286. .catch(() => {
  287. setlinfos.value = []
  288. })
  289. }
  290. }
  291. const exportYbDetailExcel = () => {
  292. if (setldetails.value.length === 0) {
  293. ElMessage({
  294. message: '没有可以导出的数据!',
  295. type: 'warning',
  296. duration: 2500,
  297. showClose: true,
  298. })
  299. } else {
  300. const title = {
  301. patNo: '住院号',
  302. times: '住院次数',
  303. psnName: '姓名',
  304. gendName: '性别',
  305. brdy: '出生日期',
  306. certno: '身份证',
  307. insuplcAdmdvsName: '参保地名称',
  308. insutypeName: '险种类型',
  309. medTypeName: '医疗类别',
  310. psnTypeName: '人员类别',
  311. mdtrtId: '就诊ID',
  312. setlId: '结算ID',
  313. begntime: '入院时间',
  314. endtime: '出院时间',
  315. setlTime: '结算时间',
  316. medfeeSumamt: '总费用',
  317. fundPaySumamt: '报销金额',
  318. mafPay: '医疗救助',
  319. acctPay: '个人账户支出',
  320. psnCashPay: '个人现金支出',
  321. hifmiPay: '大病支出',
  322. medfeeSumamt: '西药费',
  323. medfeeSumamt: '中成药费',
  324. medfeeSumamt: '中药饮片费',
  325. medfeeSumamt: '总耗材费费用',
  326. }
  327. Export(setldetails.value, title, filterDialogTitle.value)
  328. }
  329. }
  330. const handleChange = (value) => {
  331. }
  332. const pageSize = ref(30)
  333. const currentPage = ref(1)
  334. const handleSizeChange = (val) => {
  335. pageSize.value = val
  336. }
  337. const handleCurrentChange = (val) => {
  338. currentPage.value = val
  339. }
  340. const selectChart = async () => {
  341. if (!dateRange.value) {
  342. ElMessage({
  343. message: '请选择时间范围!',
  344. type: 'warning',
  345. duration: 2500,
  346. showClose: true,
  347. })
  348. return
  349. }
  350. if (!setlCondition.dataInfo) {
  351. ElMessage({
  352. message: '请选择险种!',
  353. type: 'warning',
  354. duration: 2500,
  355. showClose: true,
  356. })
  357. return
  358. }
  359. setlCondition.setlType = setlCondition.dataInfo[0]
  360. setlCondition.insurType = setlCondition.dataInfo[1]
  361. setlCondition.startTime = formatDatetime(dateRange.value[0])
  362. setlCondition.endTime = formatDatetime(dateRange.value[1])
  363. let yearL = setlCondition.startTime.substr(0, 4)
  364. let yearR = setlCondition.endTime.substr(0, 4)
  365. if (yearL != yearR) {
  366. ElMessage({
  367. message: '请选择同一年份!',
  368. type: 'warning',
  369. duration: 2500,
  370. showClose: true,
  371. })
  372. return
  373. }
  374. qxtDrawer.value = true
  375. titleChart.value = yearL + '年医保收入分析图'
  376. let data = []
  377. data = await selectYbChart(setlCondition)
  378. let setlCondition1 = clone(setlCondition)
  379. setlCondition1.selectType = 'first'
  380. data = data.concat(await selectYbStatInfo(setlCondition1))
  381. chartData.value = data
  382. }
  383. watch(chartData, (orlData, newData) => {
  384. let nameText
  385. let barTitles = ['总费用', '全部基金', '药品费', '耗材费']
  386. if (setlCondition.setlType === '21') {
  387. nameText = '住院'
  388. } else {
  389. nameText = '门诊'
  390. }
  391. nameText = titleChart.value + '(' + nameText + ')-'
  392. let yAxisName = '单位:百万元'
  393. let tipUnit = '元'
  394. let echartsXdata = []
  395. let zfy = []
  396. let zjj = []
  397. let ypf = []
  398. let clf = []
  399. let pieRc = []
  400. let pieZyts = []
  401. let pieZfy = []
  402. chartData.value.forEach((item) => {
  403. if (item.month) {
  404. zfy.push(item.zfy_jn)
  405. zjj.push(item.zjj_jn)
  406. if (item.ypf_jn > 0.00) {
  407. ypf.push(item.ypf_jn)
  408. }
  409. if (item.clf_jn > 0.00) {
  410. clf.push(item.clf_jn)
  411. }
  412. echartsXdata.push(item.month)
  413. } else {
  414. let dataRc = {}
  415. let dataZyts = {}
  416. let dataZfy = {}
  417. dataRc.value = item.psnCount
  418. dataRc.name = item.insurName
  419. dataRc.unit = '人'
  420. pieRc.push(dataRc)
  421. dataZyts.value = item.inDays
  422. dataZyts.name = item.insurName
  423. dataZyts.unit = '天'
  424. pieZyts.push(dataZyts)
  425. dataZfy.value = item.totalFee
  426. dataZfy.name = item.insurName
  427. dataZfy.unit = '元'
  428. pieZfy.push(dataZfy)
  429. }
  430. })
  431. barUtilsTwo(zfyDst, nameText + barTitles[0], echartsXdata, zfy, barTitles[0], yAxisName, tipUnit)
  432. barUtilsTwo(zjjDst, nameText + barTitles[1], echartsXdata, zjj, barTitles[1], yAxisName, tipUnit)
  433. barUtilsTwo(ypfDst, nameText + barTitles[2], echartsXdata, ypf, barTitles[2], yAxisName, tipUnit)
  434. barUtilsTwo(clfDst, nameText + barTitles[3], echartsXdata, clf, barTitles[3], yAxisName, tipUnit)
  435. pieUtilsOne(rcpie, '住院人次', pieRc)
  436. pieUtilsOne(zytsPie, '住院天数', pieZyts)
  437. pieUtilsOne(zfyPie, '总费用', pieZfy)
  438. })
  439. const handleClick = (tab, event) => {
  440. if (!dateRange.value) {
  441. ElMessage({
  442. message: '请选择时间范围!',
  443. type: 'warning',
  444. duration: 2500,
  445. showClose: true,
  446. })
  447. return
  448. }
  449. if (!setlCondition.dataInfo) {
  450. ElMessage({
  451. message: '请选择险种!',
  452. type: 'warning',
  453. duration: 2500,
  454. showClose: true,
  455. })
  456. return
  457. }
  458. setlCondition.setlType = setlCondition.dataInfo[0]
  459. setlCondition.insurType = setlCondition.dataInfo[1]
  460. setlCondition.startTime = formatDatetime(dateRange.value[0])
  461. setlCondition.endTime = formatDatetime(dateRange.value[1])
  462. // 查询哪个tab页面
  463. setlCondition.selectType = tab.props.name
  464. if (setlCondition.selectType === "first") {
  465. selectYbStatInfo(setlCondition)
  466. .then((res) => {
  467. setlinfos.value = res
  468. })
  469. .catch(() => {
  470. setlinfos.value = []
  471. })
  472. } else {
  473. selectYbStatRatio(setlCondition)
  474. .then((res) => {
  475. setlinfos.value = res
  476. })
  477. .catch(() => {
  478. setlinfos.value = []
  479. })
  480. }
  481. }
  482. const getSummaries = () => {
  483. if (setlCondition.selectType === 'first') {
  484. let sums1 = {
  485. psnCount: 0,
  486. inDays: 0,
  487. avgInDays: 0,
  488. totalFee: 0,
  489. drugFee: 0,
  490. drugFeeRatio: 0,
  491. matFee: 0,
  492. matFeeRatio: 0,
  493. fundPooling: 0,
  494. bigIllFundPooling: 0,
  495. civilServiceFund: 0,
  496. otherFunds: 0,
  497. allFunds: 0,
  498. }
  499. setlinfos.value.forEach((itm) => {
  500. for (let k in sums1) {
  501. sums1[k] = Number(sums1[k]) + Number(itm[k])
  502. }
  503. })
  504. sums1.insurName = '合计'
  505. sums1.avgInDays = (sums1.inDays / sums1.psnCount).toFixed(2)
  506. sums1.drugFeeRatio = (sums1.drugFee / sums1.totalFee * 100).toFixed(2)
  507. sums1.matFeeRatio = (sums1.matFee / sums1.totalFee * 100).toFixed(2)
  508. return sums1
  509. } else if (setlCondition.selectType === 'second') {
  510. let sums2 = {
  511. zfy_jn: 0,
  512. zfy_qn: 0,
  513. zfy_tb: 0,
  514. zjj_jn: 0,
  515. zjj_qn: 0,
  516. zjj_tb: 0,
  517. ypf_jn: 0,
  518. ypf_qn: 0,
  519. ypf_tb: 0,
  520. clf_jn: 0,
  521. clf_qn: 0,
  522. clf_tb: 0,
  523. }
  524. setlinfos.value.forEach((itm) => {
  525. for (let k in sums2) {
  526. sums2[k] = Number(sums2[k]) + Number(itm[k])
  527. }
  528. })
  529. sums2.month = '合计'
  530. sums2.zfy_tb = ((sums2.zfy_jn - sums2.zfy_qn) / sums2.zfy_qn * 100).toFixed(2) + '%'
  531. sums2.zjj_tb = ((sums2.zjj_jn - sums2.zjj_qn) / sums2.zjj_qn * 100).toFixed(2) + '%'
  532. sums2.ypf_tb = ((sums2.ypf_jn - sums2.ypf_qn) / sums2.ypf_qn * 100).toFixed(2) + '%'
  533. sums2.clf_tb = ((sums2.clf_jn - sums2.clf_qn) / sums2.clf_qn * 100).toFixed(2) + '%'
  534. return sums2
  535. } else {
  536. let sums3 = {
  537. zfy: 0,
  538. zfy_hb: 0,
  539. zjj: 0,
  540. zjj_hb: 0,
  541. ypf: 0,
  542. ypf_hb: 0,
  543. clf: 0,
  544. clf_hb: 0,
  545. }
  546. setlinfos.value.forEach((itm) => {
  547. for (let k in sums3) {
  548. sums3[k] = Number(sums3[k]) + Number(itm[k])
  549. }
  550. })
  551. sums3.month = '合计'
  552. sums3.zfy_hb = ''
  553. sums3.zjj_hb = ''
  554. sums3.ypf_hb = ''
  555. sums3.clf_hb = ''
  556. return sums3
  557. }
  558. }
  559. const getSummaries1 = (param) => {
  560. const { columns, data } = param
  561. const sums = []
  562. // 住院人次下标
  563. let psnCountIndex = 0
  564. // 住院天数下标
  565. let inDaysIndex = 0
  566. // 总费用下标
  567. let zfyIndex = 0
  568. // 药品费下标
  569. let ypfIndex = 0
  570. // 材料费下标
  571. let clfIndex = 0
  572. // 今年总费用下标
  573. let jn_zfy = 0
  574. // 去年总费用下标
  575. let qn_zfy = 0
  576. // 今年总基金下标
  577. let jn_zjj = 0
  578. // 去年总基金下标
  579. let qn_zjj = 0
  580. // 今年药品费下标
  581. let jn_ypf = 0
  582. // 去年药品费下标
  583. let qn_ypf = 0
  584. // 今年耗材费下标
  585. let jn_clf = 0
  586. // 去年耗材费下标
  587. let qn_clf = 0
  588. columns.forEach((column, index) => {
  589. if (index === 0) {
  590. sums[index] = '合计'
  591. return
  592. }
  593. if (column.property === 'psnCount') {
  594. psnCountIndex = index
  595. }
  596. if (column.property === 'inDays') {
  597. inDaysIndex = index
  598. }
  599. if (column.property === 'totalFee') {
  600. zfyIndex = index
  601. }
  602. if (column.property === 'drugFee') {
  603. ypfIndex = index
  604. }
  605. if (column.property === 'matFee') {
  606. clfIndex = index
  607. }
  608. if (column.property === 'jn_zfy') {
  609. jn_zfy = index
  610. }
  611. if (column.property === 'qn_zfy') {
  612. qn_zfy = index
  613. }
  614. if (column.property === 'jn_zjj') {
  615. jn_zjj = index
  616. }
  617. if (column.property === 'qn_zjj') {
  618. qn_zjj = index
  619. }
  620. if (column.property === 'jn_ypf') {
  621. jn_ypf = index
  622. }
  623. if (column.property === 'qn_ypf') {
  624. qn_ypf = index
  625. }
  626. if (column.property === 'jn_clf') {
  627. jn_clf = index
  628. }
  629. if (column.property === 'qn_clf') {
  630. qn_clf = index
  631. }
  632. const values = data.map(item => Number(item[column.property]))
  633. if (column.property === 'avgInDays') {
  634. sums[index] = (sums[inDaysIndex] / sums[psnCountIndex]).toFixed(2)
  635. } else if (column.property === 'drugFeeRatio') {
  636. if (sums[zfyIndex] > 0) {
  637. sums[index] = (sums[ypfIndex] / sums[zfyIndex] * 100).toFixed(2)
  638. } else {
  639. sums[index] = 0.00
  640. }
  641. } else if (column.property === 'matFeeRatio') {
  642. if (sums[zfyIndex] > 0) {
  643. sums[index] = (sums[clfIndex] / sums[zfyIndex] * 100).toFixed(2)
  644. } else {
  645. sums[index] = 0.00
  646. }
  647. } else if (column.property === 'zfy_tb') {
  648. if (sums[qn_zfy] > 0) {
  649. sums[index] = ((sums[jn_zfy] - sums[qn_zfy]) / sums[qn_zfy] * 100).toFixed(2) + '%'
  650. } else {
  651. sums[index] = 0.00 + '%'
  652. }
  653. } else if (column.property === 'zjj_tb') {
  654. if (sums[qn_zjj] > 0) {
  655. sums[index] = ((sums[jn_zjj] - sums[qn_zjj]) / sums[qn_zjj] * 100).toFixed(2) + '%'
  656. } else {
  657. sums[index] = 0.00 + '%'
  658. }
  659. } else if (column.property === 'ypf_tb') {
  660. if (sums[qn_ypf] > 0) {
  661. sums[index] = ((sums[jn_ypf] - sums[qn_ypf]) / sums[qn_ypf] * 100).toFixed(2) + '%'
  662. } else {
  663. sums[index] = 0.00 + '%'
  664. }
  665. } else if (column.property === 'clf_tb') {
  666. if (sums[qn_clf] > 0) {
  667. sums[index] = ((sums[jn_clf] - sums[qn_clf]) / sums[qn_clf] * 100).toFixed(2) + '%'
  668. } else {
  669. sums[index] = 0.00 + '%'
  670. }
  671. } else if (column.property === 'zfy_hb') {
  672. sums[index] = ''
  673. } else if (column.property === 'zjj_hb') {
  674. sums[index] = ''
  675. } else if (column.property === 'ypf_hb') {
  676. sums[index] = ''
  677. } else if (column.property === 'clf_hb') {
  678. sums[index] = ''
  679. } else if (!values.every(value => isNaN(value))) {
  680. sums[index] = values.reduce((prev, curr) => {
  681. const value = Number(curr)
  682. if (!isNaN(value)) {
  683. return prev + curr
  684. } else {
  685. return prev
  686. }
  687. }, 0)
  688. //合计特殊处理
  689. if (column.property === 'psnCount' || column.property === 'inDays') {
  690. sums[index] = sums[index].toFixed(0)
  691. } else {
  692. sums[index] = sums[index].toFixed(2)
  693. }
  694. } else {
  695. sums[index] = 0
  696. }
  697. })
  698. sums.avgInDays = (sums.inDays / sums.psnCount).toFixed(2)
  699. sums.drugFeeRatio = (sums.drugFee / sums.totalFee * 100).toFixed(2)
  700. sums.matFeeRatio = (sums.matFee / sums.totalFee * 100).toFixed(2)
  701. return sums
  702. }
  703. const filterSetlTypeName = () => {
  704. if ("21" === setlCondition.setlType) {
  705. return setlCondition.options[0].label
  706. } else {
  707. return setlCondition.options[1].label
  708. }
  709. return ''
  710. }
  711. const filterInsurTypeName = () => {
  712. if ("21" === setlCondition.setlType) {
  713. for (let i = 0; i < setlCondition.options[0].children.length; i++) {
  714. if (setlCondition.options[0].children[i].value === setlCondition.insurType) {
  715. return setlCondition.options[0].children[i].label
  716. }
  717. }
  718. } else {
  719. for (let i = 0; i < setlCondition.options[1].children.length; i++) {
  720. if (setlCondition.options[1].children[i].value === setlCondition.insurType) {
  721. return setlCondition.options[1].children[i].label
  722. }
  723. }
  724. }
  725. return ''
  726. }
  727. const exportSetlinfoExcel = () => {
  728. let year = setlCondition.startTime.substr(0, 4) + '年'
  729. if (setlinfos.value.length === 0) {
  730. ElMessage({
  731. message: '没有可以导出的数据!',
  732. type: 'warning',
  733. duration: 2500,
  734. showClose: true,
  735. })
  736. } else {
  737. const data = clone(setlinfos.value)
  738. data.push(getSummaries())
  739. // 增加导出正在进行中状态
  740. store.commit('app/setLoading', true)
  741. if (setlCondition.selectType === 'first') {
  742. const title = {
  743. insurName: '险种类型',
  744. psnCount: '住院人次',
  745. inDays: '住院天数',
  746. avgInDays: '平均住院日',
  747. totalFee: '总费用',
  748. drugFee: '药品费用',
  749. drugFeeRatio: '药品占比(%)',
  750. matFee: '耗材费用',
  751. matFeeRatio: '耗材占比(%)',
  752. fundPooling: '基本医疗统筹金额',
  753. bigIllFundPooling: '大病基金',
  754. civilServiceFund: '公务员基金支付',
  755. otherFunds: '其他基金',
  756. allFunds: '全部基金',
  757. }
  758. const setlTypeName = filterSetlTypeName()
  759. const insurTypeName = filterInsurTypeName()
  760. Export(data, title, `【${year}】【${setlTypeName}】【${insurTypeName}】`)
  761. } else if (setlCondition.selectType === 'second') {
  762. const setlTypeName = filterSetlTypeName()
  763. const exportName = year + setlTypeName + "同比"
  764. if (setlinfos.value.length <= 0) {
  765. ElMessage({
  766. message: '没有可以导出的数据!',
  767. type: 'warning',
  768. duration: 2500,
  769. showClose: true,
  770. })
  771. }
  772. ElMessageBox.prompt('导出文件名字', '提示', {
  773. confirmButtonText: '确定',
  774. cancelButtonText: '取消',
  775. inputPattern: /\S/,
  776. inputErrorMessage: '文件名不能为空 (∩•̀ω•́)⊃-*⋆',
  777. })
  778. .then(({ value }) => {
  779. const data = {
  780. param: {
  781. startTime: setlCondition.startTime,
  782. endTime: setlCondition.endTime,
  783. setlType: setlCondition.setlType,
  784. insurType: setlCondition.insurType,
  785. selectType: setlCondition.selectType,
  786. exportName: exportName,
  787. },
  788. url: '/ybQuery/exportYbStatRatioExcel',
  789. fileName: value + '.xlsx',
  790. }
  791. setTimeout(() => {
  792. downloadExcel(data)
  793. }, 500)
  794. })
  795. .catch(() => {
  796. })
  797. } else {
  798. const setlTypeName = filterSetlTypeName()
  799. const exportName = year + setlTypeName + "环比"
  800. if (setlinfos.value.length <= 0) {
  801. ElMessage({
  802. message: '没有可以导出的数据!',
  803. type: 'warning',
  804. duration: 2500,
  805. showClose: true,
  806. })
  807. }
  808. ElMessageBox.prompt('导出文件名字', '提示', {
  809. confirmButtonText: '确定',
  810. cancelButtonText: '取消',
  811. inputPattern: /\S/,
  812. inputErrorMessage: '文件名不能为空 (∩•̀ω•́)⊃-*⋆',
  813. })
  814. .then(({ value }) => {
  815. const data = {
  816. param: {
  817. startTime: setlCondition.startTime,
  818. endTime: setlCondition.endTime,
  819. setlType: setlCondition.setlType,
  820. insurType: setlCondition.insurType,
  821. selectType: setlCondition.selectType,
  822. exportName: exportName,
  823. },
  824. url: '/ybQuery/exportYbStatRatioExcel',
  825. fileName: value + '.xlsx',
  826. }
  827. setTimeout(() => {
  828. downloadExcel(data)
  829. }, 500)
  830. })
  831. .catch(() => {
  832. })
  833. }
  834. }
  835. }
  836. const handleClose = (done) => {
  837. if (this.loading) {
  838. return;
  839. }
  840. this.$confirm('确定要提交表单吗?')
  841. .then(_ => {
  842. this.loading = true;
  843. this.timer = setTimeout(() => {
  844. done();
  845. // 动画关闭需要一定的时间
  846. setTimeout(() => {
  847. this.loading = false;
  848. }, 400);
  849. }, 2000);
  850. })
  851. .catch(_ => { });
  852. }
  853. const cancelForm = () => {
  854. this.loading = false;
  855. this.dialog = false;
  856. clearTimeout(this.timer);
  857. }
  858. onMounted(() => {
  859. // 初始化数据
  860. setlCondition.selectType = 'first'
  861. })
  862. return {
  863. tableHeight,
  864. dateRange,
  865. setlCondition,
  866. setlinfos,
  867. qxtDrawer,
  868. titleChart,
  869. chartData,
  870. pieChartData,
  871. pageSize,
  872. currentPage,
  873. filterDialogTitle,
  874. setldetails,
  875. showSetldetails,
  876. showSetlinfoComponent,
  877. currentSetldetail,
  878. handleCurrentChange,
  879. handleSizeChange,
  880. fetchSetldetails,
  881. selectChart,
  882. handleClose,
  883. cancelForm,
  884. getSummaries1,
  885. exportSetlinfoExcel,
  886. exportYbDetailExcel,
  887. handleChange,
  888. handleClick,
  889. openSetlinfoComponent,
  890. fetchSetlinfos,
  891. }
  892. },
  893. }
  894. function initInsurOptions() {
  895. return [
  896. {
  897. value: '21',
  898. label: '住院',
  899. children: [
  900. {
  901. value: 99,
  902. label: '全部',
  903. },
  904. {
  905. value: 43010031001,
  906. label: '长沙市城职',
  907. },
  908. {
  909. value: 43010039001,
  910. label: '长沙市城居',
  911. },
  912. {
  913. value: 43010034001,
  914. label: '长沙市离休',
  915. },
  916. {
  917. value: 43010051052,
  918. label: '长沙市生育',
  919. },
  920. {
  921. value: 43012131001,
  922. label: '长沙县城职',
  923. },
  924. {
  925. value: 43012139001,
  926. label: '长沙县城居',
  927. },
  928. {
  929. value: 43012134001,
  930. label: '长沙县离休',
  931. },
  932. {
  933. value: 43012151052,
  934. label: '长沙县生育',
  935. },
  936. {
  937. value: 43018131001,
  938. label: '浏阳市城职',
  939. },
  940. {
  941. value: 43018139001,
  942. label: '浏阳市城居',
  943. },
  944. {
  945. value: 43018134001,
  946. label: '浏阳市离休',
  947. },
  948. {
  949. value: 43018151052,
  950. label: '浏阳市生育',
  951. },
  952. {
  953. value: 43990031001,
  954. label: '湖南省城职',
  955. },
  956. {
  957. value: 43990034001,
  958. label: '湖南省离休',
  959. },
  960. {
  961. value: 43990051052,
  962. label: '湖南省生育',
  963. },
  964. {
  965. value: 43990001,
  966. label: '省内异地',
  967. },
  968. {
  969. value: 43990002,
  970. label: '省外异地',
  971. },
  972. {
  973. value: 4301002102,
  974. label: '市单病种',
  975. },
  976. {
  977. value: 4399002102,
  978. label: '省单病种',
  979. },
  980. {
  981. value: 4399012102,
  982. label: '省内单病种',
  983. },
  984. ]
  985. },
  986. {
  987. value: '11',
  988. label: '门诊',
  989. children: [
  990. {
  991. value: 99,
  992. label: '全部',
  993. },
  994. {
  995. value: 11,
  996. label: '普通门诊',
  997. },
  998. {
  999. value: 14,
  1000. label: '特殊门诊',
  1001. },
  1002. {
  1003. value: 3,
  1004. label: '工伤门诊',
  1005. },
  1006. {
  1007. value: 51,
  1008. label: '生育门诊',
  1009. },
  1010. ]
  1011. },
  1012. ]
  1013. }
  1014. </script>
  1015. <style scoped>
  1016. :deep(.el-table .children-row) {
  1017. background: rgba(145, 247, 145, 0.5);
  1018. }
  1019. :deep(.el-table--border td:first-child .cell, .el-table--border th:first-child .cell) {
  1020. padding-left: 4px;
  1021. }
  1022. :deep(.el-table) {
  1023. --el-table-row-hover-background-color: #85dbfd7a;
  1024. }
  1025. :deep(.el-table__footer-wrapper tbody td) {
  1026. background: #df4a25;
  1027. color: white;
  1028. font-weight: bold;
  1029. }
  1030. :deep(.el-main) {
  1031. padding: 0 5px;
  1032. }
  1033. </style>