risk-loss-event-statistics.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. <template>
  2. <div :class="$style.searchdiv">
  3. <a-card :class="$style.searchWrap">
  4. <a-form-model
  5. ref="advancedSearchForm"
  6. class="ant-advanced-search-form"
  7. :model="form"
  8. :rules="rules"
  9. v-bind="formItemLayout"
  10. >
  11. <a-row :gutter="24" :class="$style.antformitem">
  12. <a-col :span="8">
  13. <a-form-model-item label="年度" prop="timeRange">
  14. <AuditRangePicker v-model="form.timeRange" :time-range.sync="form.timeRange" />
  15. </a-form-model-item>
  16. </a-col>
  17. <a-col :span="8">
  18. <a-form-model-item label="机构" prop="unitNames">
  19. <audit-group-picker
  20. v-model="form.unitNames"
  21. :selectall="false"
  22. :top-node-text="'风控机构'"
  23. :root-node="{ code: JgId, name: orgName, id: JgId }"
  24. :treeparams="{
  25. moduleId: 'iamOrg2',
  26. }"
  27. :single="true"
  28. />
  29. </a-form-model-item>
  30. </a-col>
  31. </a-row>
  32. <a-row>
  33. <a-col :span="16"> </a-col>
  34. <a-col :class="$style.searchbutton" :span="8">
  35. <div class="reportbuttonContent" style="margin-right:15%">
  36. <a-button @click="handleReset">重置</a-button>
  37. <a-button type="primary" html-type="submit" @click="submitForm">查询</a-button>
  38. <a-button type="primary" @click="exportData">导出</a-button>
  39. </div>
  40. </a-col>
  41. </a-row>
  42. </a-form-model>
  43. </a-card>
  44. <a-card class="reporttablecardxm">
  45. <span class="header_sd-header_common"
  46. ><span :class="['toptitle', $style.toptitle]">损失事件统计</span></span
  47. >
  48. <template v-if="total !== 0">
  49. <div>
  50. <sd-echart :key="optionkey" :class="$style.echarts" :options="option" autoresize
  51. /></div>
  52. </template>
  53. <div :class="[$style.btns]">
  54. <audit-advanced-export
  55. ref="Export"
  56. :class-style="[$style.buttonSpacing]"
  57. :exclebxh="false"
  58. :expressions="expressions"
  59. :config-id="241"
  60. :v-if="false"
  61. />
  62. </div>
  63. <div v-if="dataKeysum !== 0" id="hj" style="display:none">
  64. <sd-data-table-hj
  65. ref="dataTablehj"
  66. :key="dataKeysum"
  67. :process-req="processReqsum"
  68. :columns="columnssum"
  69. :projectlist="true"
  70. :defultpagination-pagesize="50"
  71. :data-url="dataUrl"
  72. @dataLoaded1="dataLoadedsum"
  73. @rowClick="rowClick"
  74. >
  75. <template slot="SUM1" slot-scope="text, record">
  76. <span v-if="text === '0' || text === 0">{{ text }}</span>
  77. <a v-else @click="rowClick(record, 1)">{{ text }}</a>
  78. </template>
  79. <template slot="SUM2" slot-scope="text, record">
  80. <span v-if="text === '0' || text === 0">{{ text }}</span>
  81. <a v-else @click="rowClick(record, 2)">{{ text }}</a>
  82. </template>
  83. </sd-data-table-hj>
  84. </div>
  85. <sd-data-table
  86. v-if="tableKey !== 0"
  87. :key="tableKey"
  88. ref="dataTable"
  89. class="findTable"
  90. :data-url="dataUrl"
  91. :columns="columns"
  92. :projectlist="true"
  93. :row-key="(record, index) => index"
  94. :process-req="processReq"
  95. :defultpagination-pagesize="50"
  96. @dataLoaded="dataLoaded"
  97. @rowClick="rowClick"
  98. @fnonloadsum="fnonloadsum"
  99. >
  100. <template slot="SUM1" slot-scope="text, record">
  101. <span v-if="text === '0' || text === 0">{{ text }}</span>
  102. <a v-else @click="rowClick(record, 1)">{{ text }}</a>
  103. </template>
  104. <template slot="SUM2" slot-scope="text, record">
  105. <span v-if="text === '0' || text === 0">{{ text }}</span>
  106. <a v-else @click="rowClick(record, 2)">{{ text }}</a>
  107. </template>
  108. </sd-data-table>
  109. </a-card>
  110. </div>
  111. </template>
  112. <script>
  113. import 'echarts/lib/chart/treemap'
  114. import 'echarts/lib/chart/pie'
  115. import 'echarts/lib/chart/pictorialBar'
  116. import 'echarts/lib/component/title'
  117. import 'echarts/lib/chart/bar'
  118. import 'echarts/lib/component/legend'
  119. import 'echarts/lib/component/legendScroll'
  120. import 'echarts/lib/component/tooltip'
  121. import moment from 'moment'
  122. import { Modal, message } from '@/common/one-ui'
  123. import axios from '@/common/services/axios-instance'
  124. import { getUserInfo } from '@/common/store-mixin'
  125. import TableColumnTypes from '@/common/services/table-column-types'
  126. import download from '@/common/services/download'
  127. import AuditRangePicker from '@product/iam/components/picker/audit-range-picker.vue'
  128. import auditGroupPicker from '@product/iam/components/picker/audit-group-picker.vue'
  129. import auditAdvancedExport from '@product/iam/components/audit-advanced-export.vue'
  130. import riskTasksService from '../task/risk-tasks-service'
  131. import StatisticsService from './statistics-service'
  132. import components from './_import-components/risk-loss-event-statistics-import'
  133. const echarts = require('echarts/lib/echarts')
  134. export default {
  135. name: 'RiskLossEventStatistics',
  136. metaInfo: {
  137. title: '损失事件统计',
  138. },
  139. components: {
  140. ...components,
  141. AuditRangePicker,
  142. auditGroupPicker,
  143. auditAdvancedExport,
  144. },
  145. data() {
  146. return {
  147. optionkey: 0,
  148. data: [],
  149. columns: [
  150. {
  151. title: '序号',
  152. dataIndex: 'sortNum',
  153. customRender: (text, record, index) => `${index + 1}`,
  154. width: '80px',
  155. },
  156. {
  157. title: '单位名称',
  158. dataIndex: 'unitName',
  159. width: '30%',
  160. sdHidden: false,
  161. },
  162. {
  163. title: '损失事件数量',
  164. dataIndex: 'num',
  165. width: '30%',
  166. sdHidden: false,
  167. scopedSlots: { customRender: 'number' },
  168. sdClickable: true,
  169. },
  170. {
  171. title: '占比',
  172. dataIndex: 'percent',
  173. width: '30%',
  174. sdHidden: false,
  175. },
  176. ],
  177. columnssum: [
  178. {
  179. title: '单位名称',
  180. dataIndex: 'unitName',
  181. width: '30%',
  182. sdHidden: false,
  183. },
  184. {
  185. title: '损失事件数量',
  186. dataIndex: 'num',
  187. width: '30%',
  188. sdHidden: false,
  189. scopedSlots: { customRender: 'number' },
  190. sdClickable: true,
  191. },
  192. {
  193. title: '占比',
  194. dataIndex: 'percent',
  195. width: '30%',
  196. sdHidden: false,
  197. },
  198. ],
  199. formItemLayout: {
  200. labelCol: { span: 6 },
  201. wrapperCol: { span: 14 },
  202. },
  203. dateFormat: 'YYYY',
  204. form: {
  205. unitNames: [],
  206. timeRange: [],
  207. },
  208. rules: {
  209. timeRange: [{ required: true, message: '请选择统计时间', trigger: 'change' }],
  210. unitNames: [{ required: true, message: '请选择审计机构', trigger: 'change' }],
  211. },
  212. params: {
  213. year: null,
  214. unitId: null,
  215. },
  216. flag: true,
  217. option: {},
  218. total: 0,
  219. tableKey: 0,
  220. dataKeysum: 0,
  221. hj: {},
  222. // hjarr: [],
  223. dataUrl: 'api/xcoa-mobile/v1/risk-statistics-analysis/lossEventStatistics?year=',
  224. expressions: [],
  225. orgName: '',
  226. orgId: '',
  227. JgId: '',
  228. }
  229. },
  230. created() {
  231. let userInfo = getUserInfo()
  232. this.orgName = userInfo.deptName
  233. const params = {
  234. orgId: userInfo.deptId,
  235. }
  236. axios({
  237. url: 'api/xcoa-mobile/v1/iamorg/getCurrentUserGroup',
  238. method: 'get',
  239. }).then((res) => {
  240. userInfo = res.data
  241. this.orgId = res.data.id
  242. this.orgName = res.data.name
  243. this.JgId = res.data.id
  244. riskTasksService.findIamOrgId(res.data.id).then((res1) => {
  245. this.JgId = res1.data
  246. // if (res.data) {
  247. // this.orgId = res.data
  248. this.form.unitNames = [
  249. {
  250. id: parseInt(this.JgId),
  251. text: this.orgName,
  252. name: this.orgName,
  253. title: this.orgName,
  254. code: this.JgId.toString(),
  255. oldId: this.JgId,
  256. type: 'Group',
  257. },
  258. ]
  259. // }
  260. })
  261. })
  262. },
  263. methods: {
  264. dataLoaded(eventData) {
  265. if (this.flag) {
  266. return
  267. }
  268. this.total = eventData.data.length
  269. eventData.data.forEach((item, index) => {
  270. item.sortNum = index + 1
  271. item.id = index
  272. })
  273. const bar = {
  274. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  275. { offset: 0, color: '#6ee394' },
  276. { offset: 0.5, color: '#5ac5c5' },
  277. { offset: 1, color: '#49adef' },
  278. ]),
  279. tooltip: {},
  280. xAxis: {
  281. type: 'category',
  282. data: eventData.data.map((d) => d.unitName),
  283. },
  284. yAxis: {
  285. type: 'value',
  286. },
  287. series: [
  288. {
  289. type: 'bar',
  290. barWidth: 40, // 柱图宽度
  291. barMaxWidth: 40, // 最大宽度
  292. label: {
  293. show: true,
  294. position: 'top',
  295. },
  296. data: eventData.data.map((d) => d.num),
  297. },
  298. ],
  299. }
  300. this.option = bar
  301. this.optionkey++
  302. return eventData
  303. },
  304. dataLoadedsum(res) {
  305. if (res.data.length) {
  306. const obj = {}
  307. let num = 0
  308. res.data.forEach((d) => {
  309. num += d.num
  310. })
  311. obj.id = 1
  312. obj.unitName = '总计'
  313. obj.num = num
  314. obj.percent = '100%'
  315. res.data.splice(0, res.data.length)
  316. res.data.push(obj)
  317. return res
  318. }
  319. },
  320. fnonloadsum() {
  321. if (this.flag) {
  322. document.querySelector('.findTable .ant-table-wrapper').style.display = 'none'
  323. } else {
  324. document.querySelector('.findTable .ant-table-wrapper').style.display = ''
  325. }
  326. setTimeout(() => {
  327. if (
  328. document
  329. .getElementById('hj')
  330. .getElementsByClassName('ant-table-tbody')[0]
  331. .getElementsByTagName('tr').length > 0
  332. ) {
  333. const obj = document.getElementById('hj').getElementsByClassName('ant-table-tbody')[0]
  334. .firstChild
  335. obj.firstChild.colSpan = 2
  336. obj.classList.add('childsum')
  337. document.getElementsByClassName('ant-table-tbody')[1].appendChild(obj)
  338. }
  339. }, 1000)
  340. },
  341. submitForm() {
  342. this.flag = false
  343. this.$refs.advancedSearchForm.validate((valid, values) => {
  344. if (valid) {
  345. const startYear = moment(this.form.timeRange[0]).format('YYYY')
  346. const endYear = moment(this.form.timeRange[1]).format('YYYY')
  347. this.params.year = startYear + '-' + endYear
  348. this.params.unitId = this.form.unitNames[0].id
  349. this.dataUrl =
  350. 'api/xcoa-mobile/v1/risk-statistics-analysis/lossEventStatistics?year=' +
  351. startYear +
  352. '-' +
  353. endYear +
  354. '&unitId=' +
  355. this.form.unitNames[0].id
  356. this.expressions.push({
  357. dataType: 'str',
  358. name: 'year',
  359. op: 'eq',
  360. stringValue: startYear + '-' + endYear,
  361. })
  362. this.expressions.push({
  363. dataType: 'long',
  364. name: 'unitId',
  365. op: 'eq',
  366. longValue: this.form.unitNames[0].id,
  367. })
  368. this.tableKey++
  369. this.dataKeysum++
  370. }
  371. })
  372. },
  373. processReq(req) {
  374. req.data = {
  375. year: this.params.year,
  376. unitId: this.params.unitId,
  377. }
  378. return req
  379. },
  380. processReqsum(req, pagination) {
  381. req.data = {
  382. year: this.params.year,
  383. unitId: this.params.unitId,
  384. }
  385. return req
  386. },
  387. handleReset() {
  388. this.$refs.advancedSearchForm.resetFields()
  389. this.tableKey = 0
  390. this.total = 0
  391. this.dataKeysum = 0
  392. },
  393. // 导出接口
  394. exportData() {
  395. this.$refs.Export.exportdata()
  396. },
  397. rowClick(record, lb) {
  398. const param = {}
  399. if (record.unitName === '总计') {
  400. param.dateStart = moment(this.form.timeRange[0]).format('YYYY')
  401. param.dateEnd = moment(this.form.timeRange[1]).format('YYYY')
  402. param.fillingUnitId = this.form.unitNames[0].id
  403. } else {
  404. param.columnValue = record.unitId
  405. param.dateStart = moment(this.form.timeRange[0]).format('YYYY')
  406. param.dateEnd = moment(this.form.timeRange[1]).format('YYYY')
  407. }
  408. const url =
  409. '#/risk-loss-event-mxlist?params=' +
  410. encodeURIComponent(JSON.stringify(param)) +
  411. '&type=projectlist'
  412. window.open(url)
  413. },
  414. },
  415. }
  416. </script>
  417. <style module lang="scss">
  418. @use '@/common/design' as *;
  419. .toptitle {
  420. color: #404040;
  421. font-weight: bold;
  422. font-size: 22px;
  423. margin-left: calc(50% - 150px);
  424. }
  425. .search-wrap {
  426. margin-bottom: $padding-lg;
  427. :global(.ant-advanced-search-form) {
  428. padding: 0;
  429. background: transparent;
  430. border: none;
  431. }
  432. :global .ant-divider-horizontal {
  433. margin: 10px 0;
  434. }
  435. }
  436. .searchdiv {
  437. background-color: #f0f2f5;
  438. height: 100%;
  439. :global(.sd-has-table.ant-card) {
  440. min-height: calc(100vh - 320px);
  441. }
  442. :global(.reporttablecardxm) {
  443. :global(.ant-table-body) {
  444. height: calc(100vh - 350px);
  445. overflow: auto;
  446. }
  447. }
  448. }
  449. .emptyecharts {
  450. width: 600px;
  451. height: 400px;
  452. margin: auto auto;
  453. text-align: center;
  454. &::after {
  455. content: '无数据';
  456. padding-top: 150px;
  457. display: block;
  458. }
  459. }
  460. .echarts {
  461. width: 100%;
  462. height: 400px;
  463. margin: auto auto;
  464. text-align: center;
  465. }
  466. .piespan {
  467. margin-left: -600px;
  468. position: relative;
  469. .cate {
  470. position: absolute;
  471. right: 300px;
  472. top: 30px;
  473. z-index: 5;
  474. // overflow: auto;
  475. // height: 250px;
  476. li {
  477. cursor: pointer;
  478. list-style: none;
  479. font-size: 13px;
  480. line-height: 23px;
  481. color: #919191;
  482. padding-left: 15px;
  483. position: relative;
  484. }
  485. }
  486. }
  487. .pdiv {
  488. height: 14px;
  489. width: 14px;
  490. background: #54c5eb;
  491. border-radius: 11px;
  492. position: absolute;
  493. left: -7px;
  494. top: 5px;
  495. }
  496. .cateli-span {
  497. color: #0162eb;
  498. display: inline-block;
  499. width: 180px;
  500. }
  501. .cateli-point {
  502. display: inline-block;
  503. width: 80px;
  504. }
  505. .backicon {
  506. position: absolute;
  507. top: 3px;
  508. left: 5px;
  509. cursor: pointer;
  510. }
  511. </style>