You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

542 lines
16 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. <template>
  2. <div class="box">
  3. <div>
  4. <div class="middlebox">
  5. <div class="contenttitle">
  6. 工作量统计 /
  7. <span class="contenttitleBold"
  8. >医生工作量统计</span
  9. >
  10. </div>
  11. </div>
  12. <div :style="'display: block;'">
  13. <div style="background-color: #fff; padding: 15px; border-radius: 8px;display: flex;flex-wrap: wrap; margin-bottom: 10px;height:35px;margin-top: 7px;">
  14. <div class="query">
  15. <span>医生</span>
  16. <el-select
  17. v-model="username"
  18. placeholder="请选择"
  19. size="small"
  20. multiple
  21. >
  22. <el-option
  23. v-for="item in registrardata"
  24. :key="item.id"
  25. :label="item.surname"
  26. :value="item.id"
  27. >
  28. </el-option>
  29. </el-select>
  30. </div>
  31. <div class="query">
  32. <span>开始日期</span>
  33. <el-date-picker
  34. type="date"
  35. placeholder="选择开始日期"
  36. size="small"
  37. v-model="startDate"
  38. value-format="yyyy-MM-dd"
  39. editable
  40. style="width: 177px;"
  41. >
  42. </el-date-picker>
  43. </div>
  44. <div class="query">
  45. <span>结束日期</span>
  46. <el-date-picker
  47. type="date"
  48. placeholder="选择结束日期"
  49. size="small"
  50. v-model="endDate"
  51. value-format="yyyy-MM-dd"
  52. editable
  53. style="width: 177px;"
  54. >
  55. </el-date-picker>
  56. </div>
  57. <div class="query">
  58. <el-button size="small" @click="onSubmit" class="commonbutton">查询</el-button>
  59. </div>
  60. <div class="query">
  61. <el-button size="small" @click="handleExport" class="commonbutton">导出excel</el-button>
  62. </div>
  63. <div class="query">
  64. <el-button size="small" @click="onPrint" class="commonbutton">打印</el-button>
  65. </div>
  66. <div class="query">
  67. <el-button size="small" @click="columnarChart" class="commonbutton">柱状图</el-button>
  68. </div>
  69. <div class="query">
  70. <el-button size="small" @click="peiChart" class="commonbutton">饼图</el-button>
  71. </div>
  72. </div>
  73. <div
  74. style="
  75. display: flex;
  76. justify-content: space-between;
  77. position: relative;
  78. "
  79. id="domTable"
  80. >
  81. <div style="width: 47.7%;background-color: #fff; padding: 15px; border-radius: 8px;" ref="imageDom">
  82. <!-- <h3 align="center">登记员工作量统计</h3>
  83. - 53-18
  84. <h5 align="right" style="margin-bottom: 5px;">
  85. 时间<span>{{ startDate }}</span
  86. ><span>{{ endDate }}</span>
  87. </h5> -->
  88. <el-table
  89. border
  90. :span-method="objectSpanMethod"
  91. :height="
  92. flag
  93. ? window.pageHeight < 600
  94. ? 415
  95. : window.pageHeight - 185 - 20
  96. : ''
  97. "
  98. :data="tableData"
  99. id="table"
  100. ref="table"
  101. style="width: 100%"
  102. :header-cell-class-name="headerStyle"
  103. :cell-style="tableRowClassName"
  104. >
  105. <el-table-column label="医生工作量统计">
  106. <el-table-column :label="'时间:' + startDate + '至' + endDate">
  107. <el-table-column
  108. prop="doctorName"
  109. label="医生"
  110. ></el-table-column>
  111. <el-table-column
  112. prop="asbitemName"
  113. label="组合项目"
  114. ></el-table-column>
  115. <el-table-column
  116. prop="checkCount"
  117. label="人数"
  118. ></el-table-column>
  119. <el-table-column prop="avgStandardPrice" label="标准价格">
  120. </el-table-column>
  121. <el-table-column prop="avgChargePrice" label="实际价格">
  122. </el-table-column>
  123. <el-table-column prop="sumStandardPrice" label="标准金额">
  124. </el-table-column>
  125. <el-table-column prop="sumChargePrice" label="实际金额">
  126. </el-table-column>
  127. </el-table-column>
  128. </el-table-column>
  129. </el-table>
  130. </div>
  131. <div
  132. :style="
  133. 'width: 47.7%;overflow: hidden;height:' +
  134. (window.pageHeight < 600 ? 415 : window.pageHeight - 185 - 20) +
  135. 'px;background-color: #fff; padding: 15px; border-radius: 8px;'
  136. "
  137. >
  138. <div style=" font-size: 20px;
  139. font-weight: 700;
  140. color: #232748;
  141. font-family: 'NotoSansSC-Bold';
  142. text-align: center;">医生工作量统计</div>
  143. <div :style="
  144. 'height:' +(window.pageHeight < 600 ? 387 : window.pageHeight - 185 - 48) +'px;'
  145. ">
  146. <ChartBlock ref="chart2"></ChartBlock>
  147. </div>
  148. </div>
  149. </div>
  150. </div>
  151. </div>
  152. </div>
  153. </template>
  154. <script>
  155. import { mapState, mapActions } from "vuex";
  156. import { getapi, postapi, putapi, deletapi } from "@/api/api";
  157. import ChartBlock from "../../components/workload/chartsBlock";
  158. import { exportToExcel } from "../../utlis/Export2Excel";
  159. import html2canvas from "html2canvas";
  160. import printJs from "print-js";
  161. export default {
  162. components: {
  163. ChartBlock,
  164. },
  165. data() {
  166. return {
  167. registrardata: [],
  168. username: [],
  169. startDate: "",
  170. endDate: "",
  171. tableData: [],
  172. seriesData: [],
  173. yAxisData: [],
  174. flag: true,
  175. arr1: [],
  176. pieData: [],
  177. };
  178. },
  179. created() {
  180. this.getList();
  181. },
  182. mounted() {
  183. this.getNowTime();
  184. },
  185. methods: {
  186. tableRowClassName({row, rowIndex}){
  187. if(row.asbitemName==='合计'){
  188. return { backgroundColor: "#F5F7FA" };
  189. }
  190. },
  191. peiChart() {
  192. let option2 = {
  193. // title: {
  194. // text: "医生工作量统计",
  195. // left: "center",
  196. // },
  197. tooltip: {
  198. trigger: "item",
  199. confine: true,
  200. },
  201. legend: {
  202. data:this.yAxisData,
  203. orient: "horizontal",
  204. right: "3%",
  205. top: "0%",
  206. },
  207. grid: {
  208. show: false,
  209. left: "0%",
  210. right: "0%",
  211. top: "0%",
  212. bottom: "0%",
  213. containLabel: true,
  214. },
  215. series: [
  216. {
  217. type: "pie",
  218. label: {
  219. show: true,
  220. formatter: "{b} : {c}人 ({d}%)" // b代表名称,c代表对应值,d代表百分比
  221. },
  222. data: this.pieData
  223. }
  224. ],
  225. };
  226. this.$refs.chart2.setOption(option2);
  227. },
  228. columnarChart() {
  229. let option2 = {
  230. // title: {
  231. // text: "医生工作量统计",
  232. // left: "center",
  233. // },
  234. tooltip: {
  235. trigger: "axis",
  236. confine: true,
  237. },
  238. legend: {
  239. type: "scroll",
  240. orient: "horizontal",
  241. right: "3%",
  242. top: "0%",
  243. },
  244. grid: {
  245. show: false,
  246. left: "0%",
  247. right: "0%",
  248. top: "0%",
  249. bottom: "0%",
  250. containLabel: true,
  251. },
  252. xAxis: {
  253. type: "value",
  254. axisLabel: {
  255. textStyle: {
  256. fontSize: "14",
  257. },
  258. },
  259. axisLine: {
  260. show: true,
  261. },
  262. },
  263. yAxis: {
  264. type: "category",
  265. data: this.yAxisData,
  266. axisLabel: {
  267. textStyle: {
  268. fontSize: "14",
  269. },
  270. },
  271. },
  272. series: [
  273. {
  274. name: "人数",
  275. type: "bar",
  276. data: this.seriesData,
  277. },
  278. ],
  279. };
  280. this.$refs.chart2.setOption(option2);
  281. },
  282. headerStyle({ row, column, rowIndex, columnIndex }) {
  283. if (rowIndex === 1) {
  284. return "left-align";
  285. }
  286. },
  287. summarizeRegisterCount(param) {
  288. const { columns, data } = param;
  289. const sums = [];
  290. columns.forEach((column, index) => {
  291. if (index === 0) {
  292. sums[index] = "合计";
  293. return;
  294. }
  295. const values = data.map((item) => Number(item[column.property]));
  296. if (index === 1) {
  297. sums[index] = values.reduce((prev, curr) => {
  298. const value = Number(curr);
  299. if (!isNaN(value)) {
  300. return prev + curr;
  301. } else {
  302. return prev;
  303. }
  304. }, 0);
  305. sums[index] = "共" + sums[index] + "人";
  306. } else {
  307. sums[index] = "";
  308. }
  309. });
  310. return sums;
  311. },
  312. onPrint() {
  313. this.flag = false;
  314. this.$nextTick(() => {
  315. let width = this.$refs.imageDom.style.width;
  316. let cloneDom = this.$refs.imageDom.cloneNode(true);
  317. let imageDom = this.$refs.imageDom;
  318. cloneDom.style.position = "absolute";
  319. cloneDom.style.top = "0px";
  320. cloneDom.style.zIndex = "-1";
  321. cloneDom.style.width = width;
  322. console.log(cloneDom);
  323. imageDom.appendChild(cloneDom);
  324. html2canvas(cloneDom).then((canvas) => {
  325. // 转成图片,生成图片地址
  326. const url = canvas.toDataURL("image/png");
  327. printJs({
  328. printable: url,
  329. type: "image",
  330. documentTitle: "", // 标题
  331. style: "@page{size:auto;margin: 0cm 1cm 0cm 1cm;}", // 去除页眉页脚
  332. });
  333. });
  334. cloneDom.style.display = "none";
  335. this.flag = true;
  336. });
  337. },
  338. onSubmit() {
  339. let that = this;
  340. if (this.startDate == "") {
  341. return this.$message({
  342. message: "请先选择开始日期",
  343. type: "error",
  344. });
  345. }
  346. if (this.endDate == "") {
  347. return this.$message({
  348. message: "请先选择结束日期",
  349. type: "error",
  350. });
  351. }
  352. postapi("/api/app/internalreport/getdoctorpersonnelworkloadreport", {
  353. userIds: that.username,
  354. startDate: that.startDate,
  355. endDate: that.endDate,
  356. }).then((res) => {
  357. if (res.code != -1) {
  358. // that.tableData = res.data;
  359. that.computedTableData(res.data);
  360. }
  361. });
  362. },
  363. setdates(arr) {
  364. var obj = {},
  365. k,
  366. arr1 = [];
  367. this.arr1 = [];
  368. for (var i = 0, len = arr.length; i < len; i++) {
  369. k = arr[i].doctorName; //需要合并的字段
  370. if (obj[k]) obj[k]++;
  371. else obj[k] = 1;
  372. }
  373. //保存结果{el-'元素',count-出现次数}
  374. for (var o in obj) {
  375. for (let i = 0; i < obj[o]; i++) {
  376. if (i === 0) {
  377. this.arr1.push(obj[o]);
  378. } else {
  379. this.arr1.push(0);
  380. }
  381. }
  382. }
  383. },
  384. objectSpanMethod({ row, column, rowIndex, columnIndex }) {
  385. if (columnIndex === 0) {
  386. let _row = this.arr1[rowIndex];
  387. let _col = this.arr1[rowIndex] > 0 ? 1 : 0;
  388. return [_row, _col];
  389. }
  390. },
  391. getList() {
  392. getapi("/api/identity/users/getlist").then((res) => {
  393. if (res.code != -1) {
  394. this.registrardata = [...res.data.items];
  395. }
  396. });
  397. },
  398. getNowTime() {
  399. var now = new Date();
  400. var year = now.getFullYear(); // 得到年份
  401. var month = now.getMonth(); // 得到月份
  402. var date = now.getDate(); // 得到日期
  403. month = month + 1;
  404. month = month.toString().padStart(2, "0");
  405. date = date.toString().padStart(2, "0");
  406. var defaultDate = `${year}-${month}-${date}`;
  407. this.startDate = defaultDate;
  408. this.endDate = defaultDate;
  409. },
  410. ForwardRanking(data, p) {
  411. for (var i = 0; i < data.length - 1; i++) {
  412. for (var j = 0; j < data.length - 1 - i; j++) {
  413. var dd = data[j][p].localeCompare(data[j + 1][p], "zh"); //1---前者往后移,-1===位置不变
  414. if (dd > 0) {
  415. var temp = data[j];
  416. data[j] = data[j + 1];
  417. data[j + 1] = temp;
  418. }
  419. }
  420. }
  421. this.tableData = data;
  422. this.setdates(this.tableData);
  423. },
  424. computedTableData(tableData) {
  425. const newData = [...tableData]; // 创建一个新的数组,避免修改原始数据
  426. const totalRows = {
  427. doctorName: "",
  428. asbitemName: "合计",
  429. checkCount: 0,
  430. avgStandardPrice: 0,
  431. avgChargePrice: 0,
  432. sumStandardPrice: 0,
  433. sumChargePrice: 0,
  434. }; // 合计行的数据
  435. let pies = {
  436. name: "",
  437. value: 0,
  438. };
  439. let obj = {};
  440. for (let i = 0; i < tableData.length; i++) {
  441. var item = tableData[i].doctorName;
  442. obj[item] = obj[item] + 1 || 1;
  443. }
  444. Object.keys(obj).forEach((key) => {
  445. let totalRow = JSON.parse(JSON.stringify(totalRows));
  446. let pie = JSON.parse(JSON.stringify(pies));
  447. tableData.forEach((item) => {
  448. if (item.doctorName == key) {
  449. totalRow.doctorName = item.doctorName;
  450. pie.name = item.doctorName;
  451. totalRow.checkCount += item.checkCount;
  452. pie.value += item.checkCount;
  453. totalRow.avgStandardPrice =
  454. (totalRow.avgStandardPrice * 100000 +
  455. item.avgStandardPrice * 100000) /
  456. 100000;
  457. totalRow.avgChargePrice =
  458. (totalRow.avgChargePrice * 100000 +
  459. item.avgChargePrice * 100000) /
  460. 100000;
  461. totalRow.sumStandardPrice =
  462. (totalRow.sumStandardPrice * 100000 +
  463. item.sumStandardPrice * 100000) /
  464. 100000;
  465. totalRow.sumChargePrice =
  466. (totalRow.sumChargePrice * 100000 +
  467. item.sumChargePrice * 100000) /
  468. 100000;
  469. }
  470. });
  471. newData.push(totalRow);
  472. this.pieData.push(pie);
  473. this.yAxisData.push(totalRow.doctorName);
  474. this.seriesData.push(totalRow.checkCount);
  475. });
  476. this.ForwardRanking(newData, "doctorName");
  477. this.columnarChart();
  478. },
  479. handleExport() {
  480. exportToExcel("#table", "医生工作量统计",false);
  481. },
  482. },
  483. computed: {
  484. ...mapState(["window", "dict", "patientRegister", "report"]),
  485. },
  486. updated() {
  487. this.$nextTick(() => {
  488. this.$refs.table.doLayout();
  489. });
  490. },
  491. };
  492. </script>
  493. <style scoped>
  494. @import "../../assets/css/global_button.css";
  495. @import "../../assets/css/global_dialog.css";
  496. @import "../../assets/css/global_table.css";
  497. @import "../../assets/css/global_form.css";
  498. @import "../../assets/css/global_input.css";
  499. @import "../../assets/css/global.css";
  500. .query{
  501. margin-right: 15px;
  502. display: flex;
  503. justify-content: center;
  504. align-items: center;
  505. font-size: 14px;
  506. color: #232748;
  507. font-size: 400;
  508. font-family: "NotoSansSC-Regular";
  509. }
  510. .box {
  511. display: flex;
  512. flex-direction: column;
  513. }
  514. :deep .left-align .cell {
  515. text-align: left !important;
  516. }
  517. ::v-deep .el-table__body-wrapper::-webkit-scrollbar {
  518. width: 0px;
  519. background: rgba(213, 215, 220, 0.3);
  520. border: none;
  521. }
  522. ::v-deep .el-table__body-wrapper::-webkit-scrollbar-track {
  523. border: none;
  524. }
  525. ::v-deep .el-table th.gutter {
  526. display: none;
  527. width: 0;
  528. }
  529. ::v-deep .el-table colgroup col[name="gutter"] {
  530. display: none;
  531. width: 0;
  532. }
  533. ::v-deep .el-table__body {
  534. width: 100% !important;
  535. }
  536. .query:last-child{
  537. margin-right: 0;
  538. }
  539. </style>