SmsCheckWorkLogList.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. <template>
  2. <div>
  3. <a-row :gutter="16" style="height: 1622px">
  4. <a-col :span="5" style="height: 100%;">
  5. <a-card title="任务选择" :bordered="false" style="height: 100%">
  6. <a-directory-tree
  7. style="height: auto"
  8. v-model:expandedKeys="expandedKeys"
  9. v-model:selectedKeys="selectedKeys"
  10. multiple
  11. :tree-data="treeData"
  12. @expand="onExpand"
  13. @select="onTreeNodeSelect"
  14. ></a-directory-tree>
  15. </a-card>
  16. </a-col>
  17. <!--筛选条件-->
  18. <a-col :span="19">
  19. <a-form layout="inline">
  20. <a-row :gutter="24">
  21. <a-col :xl="16" :lg="7" :md="8" :sm="24">
  22. <a-form-item label="稽核工作日期范围">
  23. <a-range-picker @change="handleChange" v-model:value="taskDate"/>
  24. <a-radio-group @change="changeReportDate()" style="padding-left: 10px" v-model:value="latestDate" button-style="solid">
  25. <a-radio-button value="7">最近7天</a-radio-button>
  26. <a-radio-button value="30">最近30天</a-radio-button>
  27. <a-radio-button value="180">最近180天</a-radio-button>
  28. </a-radio-group>
  29. </a-form-item>
  30. </a-col>
  31. </a-row>
  32. </a-form>
  33. </a-col>
  34. <a-col :span="5" style="padding-top: 10px">
  35. <a-card>
  36. <a-statistic
  37. title="未完善客户数量"
  38. :value="toImproveUser"
  39. :precision="0"
  40. suffix="个"
  41. :value-style="{ color: '#fa073f' }"
  42. style="margin-right: 50px"
  43. >
  44. <template #prefix>
  45. <arrow-up-outlined/>
  46. </template>
  47. </a-statistic>
  48. </a-card>
  49. </a-col>
  50. <a-col :span="5" style="padding-top: 10px">
  51. <a-card>
  52. <a-statistic
  53. title="待整改客户数量"
  54. :value="tobeRectified"
  55. :precision="0"
  56. suffix="个"
  57. :value-style="{ color: '#810320' }"
  58. style="margin-right: 50px"
  59. >
  60. <template #prefix>
  61. <arrow-up-outlined/>
  62. </template>
  63. </a-statistic>
  64. </a-card>
  65. </a-col>
  66. <a-col :span="5" style="padding-top: 10px">
  67. <a-card>
  68. <a-statistic
  69. title="待稽核客户数量"
  70. :value="toBeAudited"
  71. :precision="0"
  72. suffix="个"
  73. :value-style="{ color: '#0a0a09' }"
  74. style="margin-right: 50px"
  75. >
  76. <template #prefix>
  77. <arrow-up-outlined/>
  78. </template>
  79. </a-statistic>
  80. </a-card>
  81. </a-col>
  82. <a-col :span="4" style="padding-top: 10px">
  83. <a-card>
  84. <a-statistic
  85. title="稽核通过客户数量"
  86. :value="auditPassed"
  87. :precision="0"
  88. suffix="个"
  89. :value-style="{ color: '#3f8600' }"
  90. style="margin-right: 50px"
  91. >
  92. <template #prefix>
  93. <arrow-up-outlined/>
  94. </template>
  95. </a-statistic>
  96. </a-card>
  97. </a-col>
  98. <a-col :span="19" style="top: 10px">
  99. <a-card title="稽核概况统计" :bordered="false">
  100. <div id="statusRefusePie" ref="statusRefusePie" style="width:100%;height:370px"></div>
  101. </a-card>
  102. </a-col>
  103. <a-col :span="19" style="padding-top: 30px">
  104. <a-card title="稽核历史异常分析" :bordered="false">
  105. <div id="statusAuditPie" ref="statusAuditPie" style="width:50%;height:370px;float: left"></div>
  106. <div id="statusAuditHistogram" ref="statusAuditHistogram" style="width:50%;height:370px;left: 50%"></div>
  107. </a-card>
  108. </a-col>
  109. <a-col :span="19" style="top: 10px">
  110. <a-card title="稽核历史异常时间分布" :bordered="false">
  111. <div id="abnormalCreateTimeTrend" ref="abnormalCreateTimeTrend" style="width:100%;height:370px"></div>
  112. </a-card>
  113. </a-col>
  114. </a-row>
  115. </div>
  116. <!-- 查询区域 -->
  117. </template>
  118. <script>
  119. import moment from 'moment';
  120. import {getAction} from "@api/manage";
  121. import * as echarts from 'echarts';
  122. export default {
  123. name: 'SmsCheckWorkLogList',
  124. data() {
  125. return {
  126. description: '稽核工作日志管理页面',
  127. taskDate: '',
  128. url: {
  129. "statusRefuse": "/smsCheck/customerInfo/status/refuse",
  130. "taskList": "/smsCheck/task/list",
  131. "dateList": "/smsCheck/task/year/list",
  132. //基本信息 规范信息 附件资料 异常稽核统计
  133. "checkStateCount": "/smsCheck/workLog/check/state/count",
  134. "abnormalCreateTime": "/smsCheck/workLog/check/abnormal/count"
  135. },
  136. // '1': '未完善',
  137. statusMap: {
  138. '0': '未完善',
  139. '2': '待稽核',
  140. '4': '待整改',
  141. "5": '稽核通过',
  142. },
  143. abnormalMap: {
  144. "basicCheckState": "基本信息异常",
  145. "standardState": "规范信息异常",
  146. "dataState": "附件资料异常异常"
  147. },
  148. $statusRefusePie: "",
  149. $abnormalCheckPie: "",
  150. $abnormalCheckHistogram: "",
  151. $abnormalCreateTimeTrend: "",
  152. toImproveUser: 0,
  153. latestDate: '180',
  154. toBeAudited: 0,
  155. tobeRectified: 0,
  156. auditPassed: 0,
  157. treeData: [],
  158. expandedKeys: ['2022', '2022-10'],
  159. selectedKeys: {},
  160. statusAuditPieData: [],
  161. canvas: {},
  162. taskId:null,
  163. }
  164. },
  165. created() {
  166. const waterMarkText = '业务风险管控智能化系统';
  167. this.canvas = document.createElement('canvas');
  168. const ctx = this.canvas.getContext('2d');
  169. this.canvas.width = this.canvas.height = 100;
  170. ctx.textAlign = 'center';
  171. ctx.textBaseline = 'middle';
  172. ctx.globalAlpha = 0.08;
  173. ctx.font = '20px Microsoft Yahei';
  174. ctx.translate(50, 50);
  175. ctx.rotate(-Math.PI / 4);
  176. ctx.fillText(waterMarkText, 0, 0);
  177. //初始化日期 默认最近180天
  178. this.taskDate = [this.getRecentDay(parseInt(this.latestDate)), this.getRecentDay(0)]
  179. //稽核任务列表(树)
  180. this.taskList();
  181. //稽核概况统计
  182. this.statusRefuse();
  183. //稽核历史异常分析
  184. this.checkStateCount(this.url.checkStateCount);
  185. this.abnormalCreateTime();
  186. },
  187. computed: {},
  188. methods: {
  189. changeReportDate(a, event){
  190. //当前 value this.latestDatec
  191. //console.log(this.latestDate)
  192. this.taskDate = [this.getRecentDay(parseInt(this.latestDate)), this.getRecentDay(0)]
  193. this.statusRefuse(this.taskId);
  194. this.checkStateCount(this.url.checkStateCount, this.taskId);
  195. this.abnormalCreateTime(this.taskId);
  196. },
  197. handleChange(value,model){
  198. this.taskDate = model
  199. // model 当前value
  200. this.statusRefuse(this.taskId);
  201. this.checkStateCount(this.url.checkStateCount, this.taskId);
  202. this.abnormalCreateTime(this.taskId);
  203. },
  204. abnormalCreateTime(infoId) {
  205. let taskDate = this.taskDate;
  206. let queryParam = {
  207. "startDate": taskDate[0],
  208. "endDate": taskDate[1],
  209. "infoId": infoId
  210. }
  211. getAction(this.url.abnormalCreateTime, queryParam).then(res => {
  212. if (res.success) {
  213. let data = [];
  214. let resultList = res.resultList;
  215. for (var i in resultList) {
  216. let resultListElement = resultList[i];
  217. let time = resultListElement.createTime;
  218. let count = parseInt(resultListElement.count);
  219. data.push([time, count])
  220. }
  221. let dateList = data.map(function (item) {
  222. return item[0];
  223. });
  224. let valueList = data.map(function (item) {
  225. return item[1];
  226. });
  227. this.abnormalCreateTimetrend(dateList, valueList)
  228. }
  229. }).finally(() => {
  230. })
  231. },
  232. abnormalCreateTimetrend(dateList, valueList) {
  233. let option = {
  234. title: {
  235. text: '稽核异常数量',
  236. left: 'center',
  237. },
  238. lineStyle: {
  239. color: '#5a6fc0'
  240. },
  241. backgroundColor: {
  242. type: 'pattern',
  243. image: this.canvas,
  244. repeat: 'repeat'
  245. },
  246. visualMap: [
  247. {
  248. show: false,
  249. type: 'continuous',
  250. seriesIndex: 0,
  251. min: 0,
  252. max: 400
  253. },
  254. {
  255. show: false,
  256. type: 'continuous',
  257. seriesIndex: 1,
  258. dimension: 0,
  259. min: 0,
  260. max: dateList.length - 1
  261. }
  262. ],
  263. tooltip: {
  264. trigger: 'axis'
  265. },
  266. legend: {
  267. data: ['稽核异常']
  268. },
  269. grid: {
  270. left: '3%',
  271. right: '4%',
  272. bottom: '3%',
  273. containLabel: true
  274. },
  275. toolbox: {
  276. feature: {
  277. saveAsImage: {}
  278. }
  279. },
  280. xAxis: {
  281. type: 'category',
  282. boundaryGap: false,
  283. data: dateList
  284. },
  285. yAxis: {
  286. type: 'value'
  287. },
  288. series: [
  289. {
  290. name: '异常数',
  291. type: 'line',
  292. stack: 'Total',
  293. data: valueList
  294. }
  295. ]
  296. };
  297. this.$abnormalCreateTimeTrend = echarts.init(document.getElementById('abnormalCreateTimeTrend'))
  298. this.$abnormalCreateTimeTrend.setOption(option)
  299. },
  300. checkStateCount(url, taskId) {
  301. let taskDate = this.taskDate;
  302. let queryParam = {
  303. "startDate": taskDate[0],
  304. "endDate": taskDate[1],
  305. "infoId": taskId
  306. }
  307. getAction(url, queryParam).then(res => {
  308. if (res.success) {
  309. let resultList = res.resultList;
  310. let pieData = [];
  311. let histogramSource = ['资料驳回分布']
  312. let dimensions = ['product']
  313. for (var i in resultList) {
  314. let resultListElement = resultList[i];
  315. let name = resultListElement.name;
  316. let state = resultListElement.state;
  317. let count = resultListElement.count;
  318. if (state === "2") {
  319. var abnormalMapElement = this.abnormalMap[name];
  320. if (abnormalMapElement != null && abnormalMapElement != undefined) {
  321. pieData.push({
  322. "name": abnormalMapElement,
  323. "value": count
  324. })
  325. dimensions.push(abnormalMapElement.toString())
  326. histogramSource.push(parseInt(count));
  327. }
  328. }
  329. }
  330. this.checkStatePie(pieData);
  331. this.checkStateHistogram(dimensions, histogramSource)
  332. }
  333. }).finally(() => {
  334. })
  335. },
  336. checkStateHistogram(dimensions, source) {
  337. let option = {
  338. backgroundColor: {
  339. type: 'pattern',
  340. image: this.canvas,
  341. repeat: 'repeat'
  342. },
  343. legend: {},
  344. tooltip: {},
  345. dataset: {
  346. source: [
  347. dimensions,
  348. source
  349. ]
  350. },
  351. xAxis: {type: 'category'},
  352. yAxis: {},
  353. // Declare several bar series, each will be mapped
  354. // to a column of dataset.source by default.
  355. series: [{type: 'bar'}, {type: 'bar'}, {type: 'bar'}]
  356. };
  357. this.$abnormalCheckHistogram = echarts.init(document.getElementById('statusAuditHistogram'))
  358. this.$abnormalCheckHistogram.setOption(option)
  359. },
  360. checkStatePie(data) {
  361. let option = {
  362. tooltip: {
  363. trigger: 'item'
  364. },
  365. backgroundColor: {
  366. type: 'pattern',
  367. image: this.canvas,
  368. repeat: 'repeat'
  369. },
  370. /*title: [
  371. {
  372. text: '异常类型占比',
  373. //subtext: '总计 ' + builderJson.all + " 稽核通过 " + builderJson.charts["稽核通过"],
  374. left: '25%',
  375. textAlign: 'center'
  376. },
  377. ],*/
  378. legend: {
  379. top: '5%',
  380. left: 'center'
  381. },
  382. series: [
  383. {
  384. name: '',
  385. type: 'pie',
  386. radius: ['40%', '70%'],
  387. avoidLabelOverlap: false,
  388. itemStyle: {
  389. borderRadius: 10,
  390. borderColor: '#fff',
  391. borderWidth: 2
  392. },
  393. label: {
  394. show: false,
  395. position: 'center'
  396. },
  397. emphasis: {
  398. label: {
  399. show: true,
  400. fontSize: '40',
  401. fontWeight: 'bold'
  402. }
  403. },
  404. labelLine: {
  405. show: false
  406. },
  407. data: data
  408. }
  409. ]
  410. };
  411. this.$abnormalCheckPie = echarts.init(document.getElementById('statusAuditPie'))
  412. this.$abnormalCheckPie.setOption(option)
  413. },
  414. //树点击事件
  415. onTreeNodeSelect(id) {
  416. if (id && id.length > 0) {
  417. if (id == "all") {
  418. this.statusRefuse();
  419. this.checkStateCount(this.url.checkStateCount);
  420. this.abnormalCreateTime();
  421. this.taskId = null;
  422. return;
  423. }
  424. let split = id[0].split("key-");
  425. if (split.length == 2) {
  426. let taskId = split[1];
  427. this.statusRefuse(taskId);
  428. this.checkStateCount(this.url.checkStateCount, taskId);
  429. this.abnormalCreateTime(taskId);
  430. this.taskId = id;
  431. }
  432. }
  433. },
  434. onExpand(expandedKeys) {
  435. this.expandedKeys = expandedKeys;
  436. },
  437. taskDateList(taskData) {
  438. getAction(this.url["dateList"]).then(res => {
  439. if (res.success) {
  440. let result = res.result;
  441. let years = result[0];
  442. let months = result[1];
  443. let YearLevel = {}
  444. let monthLevel = {}
  445. for (var i in years) {
  446. let year = years[i].yearTime;
  447. let children = {
  448. "title": year,
  449. "key": year,
  450. "children": []
  451. }
  452. YearLevel[year] = children
  453. }
  454. for (var j in months) {
  455. let month = months[j].monthTime;
  456. let splitElement = month.split("-")[0];
  457. let children = {
  458. "title": month,
  459. "key": month,
  460. "children": []
  461. }
  462. YearLevel[splitElement].children.push(children)
  463. }
  464. for (var k in taskData) {
  465. let taskDatum = taskData[k];
  466. let taskStartTime = taskDatum.taskStartTime;
  467. if (taskStartTime != null && taskStartTime != undefined) {
  468. let children = {
  469. "title": taskDatum.taskName + "[" + taskDatum.customerCount + "]",
  470. "key": "key" + "-" + taskDatum.id,
  471. "isLeaf": true,
  472. }
  473. let strings = taskStartTime.split("-");
  474. let year = strings[0];
  475. let month = strings[0] + "-" + strings[1];
  476. for (var z in YearLevel[year].children) {
  477. let title = YearLevel[year].children[z].title;
  478. if (title == month) {
  479. YearLevel[year].children[z].children.push(children);
  480. break;
  481. }
  482. }
  483. }
  484. }
  485. let allChildren = {
  486. "title": "全部任务",
  487. "key": "all",
  488. "children": []
  489. }
  490. for (var u in YearLevel) {
  491. this.treeData.push(YearLevel[u])
  492. }
  493. this.treeData.push(allChildren)
  494. this.treeData = this.treeData.reverse();
  495. }
  496. }
  497. )
  498. },
  499. //任务列表数据
  500. taskList() {
  501. let queryParam = {
  502. pageNo: 1,
  503. pageSize: 1000000,
  504. }
  505. getAction(this.url["taskList"], queryParam).then(res => {
  506. if (res.success) {
  507. let records = res.result.records;
  508. //稽核任务菜单
  509. this.taskDateList(records);
  510. }
  511. })
  512. },
  513. //查询各类型稽核进度
  514. statusRefuse(taskId) {
  515. let taskDate = this.taskDate;
  516. let queryParam = {
  517. "startDate": taskDate[0],
  518. "endDate": taskDate[1],
  519. "taskId": taskId
  520. }
  521. if (taskDate.length = 2) {
  522. getAction(this.url["statusRefuse"], queryParam).then(res => {
  523. if (res.success) {
  524. let builderJson = {};
  525. let columnDate = {};
  526. let pieDate = {};
  527. let all = 0;
  528. let resultList = res.resultList;
  529. for (var i in resultList) {
  530. let resultListElement = resultList[i];
  531. let status = this.statusMap[resultListElement.checkState];
  532. if (status != undefined && status != null) {
  533. all = all + resultListElement.count
  534. columnDate[status] = resultListElement.count
  535. }
  536. }
  537. builderJson = {
  538. "all": all,
  539. "charts": columnDate,
  540. "ie": 9743
  541. }
  542. this.statusRefusePie(builderJson)
  543. }
  544. })
  545. }
  546. },
  547. statusRefusePie(builderJson) {
  548. if (builderJson.charts["稽核通过"] == null || builderJson.charts["稽核通过"] == undefined) {
  549. builderJson.charts["稽核通过"] = 0;
  550. }
  551. if (builderJson.charts["未完善"] == null || builderJson.charts["未完善"] == undefined) {
  552. builderJson.charts["未完善"] = 0;
  553. }
  554. if (builderJson.charts["待稽核"] == null || builderJson.charts["待稽核"] == undefined) {
  555. builderJson.charts["待稽核"] = 0;
  556. }
  557. if (builderJson.charts["待整改"] == null || builderJson.charts["待整改"] == undefined) {
  558. builderJson.charts["待整改"] = 0;
  559. }
  560. this.toImproveUser = builderJson.charts["未完善"];
  561. this.toBeAudited = builderJson.charts["待稽核"];
  562. this.tobeRectified = builderJson.charts["待整改"];
  563. this.auditPassed = builderJson.charts["稽核通过"];
  564. let option = {
  565. backgroundColor: {
  566. type: 'pattern',
  567. image: this.canvas,
  568. repeat: 'repeat'
  569. },
  570. tooltip: {},
  571. title: [
  572. {
  573. text: '稽核完成进度',
  574. subtext: '总计 ' + builderJson.all + " 稽核通过 " + builderJson.charts["稽核通过"],
  575. left: '25%',
  576. textAlign: 'center'
  577. },
  578. {
  579. text: '稽核类型占比',
  580. subtext: '总计 ' + builderJson.all,
  581. left: '75%',
  582. textAlign: 'center'
  583. }
  584. ],
  585. grid: [
  586. {
  587. top: 50,
  588. width: '50%',
  589. bottom: '5%',
  590. left: 10,
  591. containLabel: true
  592. },
  593. {
  594. top: 50,
  595. width: '50%',
  596. bottom: '5%',
  597. left: 10,
  598. containLabel: true
  599. }
  600. ],
  601. xAxis: [
  602. {
  603. type: 'value',
  604. max: builderJson.all,
  605. splitLine: {
  606. show: false
  607. }
  608. }
  609. ],
  610. yAxis: [
  611. {
  612. type: 'category',
  613. data: Object.keys(builderJson.charts),
  614. axisLabel: {
  615. interval: 0,
  616. rotate: 30
  617. },
  618. splitLine: {
  619. show: false
  620. }
  621. }
  622. ],
  623. series: [
  624. {
  625. type: 'bar',
  626. stack: 'chart',
  627. z: 3,
  628. label: {
  629. position: 'right',
  630. show: true
  631. },
  632. data: Object.keys(builderJson.charts).map(function (key) {
  633. return builderJson.charts[key];
  634. }),
  635. itemStyle: {
  636. normal: {
  637. //这里是颜色
  638. color: function (params) {
  639. //注意,如果颜色太少的话,后面颜色不会自动循环,最好多定义几个颜色
  640. var colorList = ['#5c6fc4', '#f0be47', '#d2232c', '#81c463', '#BBFFAA', '#749f83', '#ca8622'];
  641. return colorList[params.dataIndex]
  642. }
  643. }
  644. }
  645. },
  646. {
  647. type: 'bar',
  648. stack: 'chart',
  649. silent: true,
  650. itemStyle: {
  651. color: '#eee'
  652. },
  653. data: Object.keys(builderJson.charts).map(function (key) {
  654. return builderJson.all - builderJson.charts[key];
  655. }),
  656. },
  657. {
  658. type: 'pie',
  659. radius: [0, '80%'],
  660. center: ['75%', '55%'],
  661. data: Object.keys(builderJson.charts).map(function (key) {
  662. return {
  663. name: key,
  664. value: builderJson.charts[key]
  665. };
  666. }),
  667. itemStyle: {
  668. normal: {
  669. //这里是颜色
  670. color: function (params) {
  671. //注意,如果颜色太少的话,后面颜色不会自动循环,最好多定义几个颜色
  672. var colorList = ['#5a6fc0', '#f0be47', '#d2232c', '#81c463', '#BBFFAA', '#749f83', '#ca8622'];
  673. return colorList[params.dataIndex]
  674. }
  675. }
  676. }
  677. },
  678. ]
  679. };
  680. this.$statusRefusePie = echarts.init(document.getElementById('statusRefusePie'))
  681. this.$statusRefusePie.setOption(option)
  682. },
  683. getRecentDay: function (n) {
  684. let day = moment(new Date())
  685. .subtract(n, "days")
  686. .format("YYYY-MM-DD");
  687. return day;
  688. },
  689. }
  690. }
  691. </script>
  692. <style scoped>
  693. </style>