kpi-analysis-select-modal.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. <template>
  2. <a-modal
  3. ref="auditModal"
  4. title="指标选择"
  5. :destroy-on-close="true"
  6. :visible="visible"
  7. width="1350px"
  8. :body-style="{
  9. padding: '0 24px',
  10. }"
  11. :class="$style.selectModal"
  12. @ok="handleOk"
  13. @cancel="handleCancel"
  14. >
  15. <!-- 高级搜索组件 -->
  16. <audit-advanced-query
  17. :expand="expand"
  18. :search-data="formData"
  19. ref-name="searchform"
  20. :search-style="{
  21. height: '220px',
  22. left: '20px',
  23. top: '100px !important',
  24. margin: 'auto',
  25. }"
  26. :search-fun="handleSearch"
  27. @searchedClick="searchedClick"
  28. @resetForm="resetForm"
  29. >
  30. <template>
  31. <a-col :span="12">
  32. <a-form-model-item :label="'\u2003\u2003业务分类'">
  33. <sd-tree-picker
  34. v-model="formData.busiClass"
  35. single
  36. :load-tree-data="loadTreeData"
  37. :class="$style.treeSelect"
  38. :data-source="[]"
  39. :selected-keys="[]"
  40. >
  41. </sd-tree-picker>
  42. </a-form-model-item>
  43. </a-col>
  44. <a-col :span="12">
  45. <a-form-model-item :label="'指标名称'">
  46. <a-input v-model="formData.indiName" allow-clear />
  47. </a-form-model-item>
  48. </a-col>
  49. <a-col :span="12">
  50. <a-form-model-item :label="'指标时间维度'">
  51. <a-select v-model="formData.indiFrequency" :options="optionsArray.optionsFrequency" />
  52. </a-form-model-item>
  53. </a-col>
  54. <a-col :span="12">
  55. <a-form-model-item :label="'监测范围'">
  56. <a-select v-model="formData.monitorRange" :options="optionsArray.optionsRange" />
  57. </a-form-model-item>
  58. </a-col>
  59. <a-col :span="12">
  60. <a-form-model-item :label="'\u2003\u2003监测单位'">
  61. <sd-group-picker v-model="formData.monitorDept" :read-only="false" />
  62. </a-form-model-item>
  63. </a-col>
  64. <!-- <a-col :span="12">
  65. <a-form-model-item :label="'预警状态'" prop="alertStatus">
  66. <a-select v-model="formData.alertStatus" :options="optionsArray.optionsStatus" />
  67. </a-form-model-item>
  68. </a-col> -->
  69. </template>
  70. </audit-advanced-query>
  71. <!-- 列表 -->
  72. <sd-data-table
  73. ref="dataTable"
  74. :row-key="'id'"
  75. :filter-expressions="expressions"
  76. :columns="columns"
  77. :show-advance-query="true"
  78. form-id="kpiIndiDef"
  79. :data-url="dataUrl"
  80. show-selection
  81. :modal-props="{ class: 'noBottom' }"
  82. :search-fields="['indiName']"
  83. :process-res="processRes"
  84. @searchbtnClick="searchbtnClick"
  85. >
  86. <div slot="dataTime" slot-scope="text, record">
  87. {{ record.year + '年' + record.dataPeriod }}
  88. </div>
  89. <div
  90. slot="alertStatus"
  91. slot-scope="text, record"
  92. :title="
  93. '\n红:' +
  94. record.redStrs +
  95. '\r\n黄:' +
  96. record.yellowStrs +
  97. '\r\n绿:' +
  98. record.grenStrs +
  99. ' '
  100. "
  101. >
  102. <div v-if="record.alertStatus === 'D'" :class="$style.status">无</div>
  103. <div v-else-if="record.alertStatus === 'A'" :class="$style.redstatus">红</div>
  104. <div v-else-if="record.alertStatus === 'B'" :class="$style.ystatus">黄</div>
  105. <div v-else-if="record.alertStatus === 'C'" :class="$style.lstatus">绿</div>
  106. </div>
  107. <div slot="indiUnit" slot-scope="text, record">
  108. {{ text }}
  109. </div>
  110. </sd-data-table>
  111. </a-modal>
  112. </template>
  113. <script>
  114. import { message } from '@/common/one-ui'
  115. import auditAdvancedQueryMixins from '@product/iam/components/audit-advanced-query-mixins'
  116. import auditAdvancedQuery from '@product/iam/components/audit-advanced-query.vue'
  117. import KpiService from '../kpi-service'
  118. import kpiAnalysisFormService from './kpi-analysis-form-service'
  119. import components from './_import-components/kpi-analysis-select-modal-import'
  120. export default {
  121. name: 'KpiAnalysisSelectModal',
  122. metaInfo: {
  123. title: '指标选择器',
  124. },
  125. components: {
  126. auditAdvancedQuery,
  127. ...components,
  128. },
  129. mixins: [auditAdvancedQueryMixins],
  130. props: {
  131. // 是否显示
  132. visible: {
  133. type: Boolean,
  134. default: false,
  135. },
  136. // 过滤条件
  137. selectExpressions: {
  138. type: Array,
  139. default: () => {
  140. return []
  141. },
  142. },
  143. // 列表类型 指标/异常指标
  144. type: {
  145. type: String,
  146. default: '',
  147. },
  148. },
  149. data() {
  150. return {
  151. dataUrl: '',
  152. listExpressions: [],
  153. treeparams: {
  154. configId: 101,
  155. },
  156. optionsArray: {
  157. optionsFrequency: [], // 指标时间维度下拉选项
  158. optionsStatus: [], // 指标状态下拉选项
  159. optionsRange: [], // 监测范围
  160. optionsindiUnit: [], // 指标值单位
  161. },
  162. formData: {
  163. indiName: '',
  164. busiClass: [],
  165. alertStatus: '',
  166. indiFrequency: '',
  167. monitorRange: '',
  168. monitorDept: '',
  169. },
  170. columns: [
  171. {
  172. title: '序号',
  173. dataIndex: 'sortNum',
  174. customRender: (text, record, index) => `${index + 1}`,
  175. width: '80px',
  176. },
  177. {
  178. title: '指标名称',
  179. dataIndex: 'indiName',
  180. },
  181. {
  182. title: '业务分类',
  183. dataIndex: 'busiClassName',
  184. },
  185. {
  186. title: '维护单位',
  187. dataIndex: 'createDeptName',
  188. },
  189. ],
  190. }
  191. },
  192. computed: {
  193. expressions() {
  194. return this.selectExpressions.concat(this.listExpressions)
  195. },
  196. },
  197. mounted() {
  198. // 获取数据字典-状态
  199. this.getDictionary('ALERT_STATUS', 'optionsStatus')
  200. // 获取数据字典-指标时间维度
  201. this.getDictionary('KPI_FREQUENCY', 'optionsFrequency')
  202. // 获取数据字典-监测范围
  203. this.getDictionary('MONITOR_RANGE', 'optionsRange')
  204. // 指标值单位
  205. this.getDictionary('INDI_UNIT', 'optionsindiUnit')
  206. // 判断类型
  207. if (this.type === 'yc') {
  208. this.dataUrl = 'api/xcoa-mobile/v1/kpiindimonitor/getAbnormalIndiVal'
  209. this.columns = [
  210. {
  211. title: '序号',
  212. customRender: (text, record, index) => `${index + 1}`,
  213. width: '80px',
  214. },
  215. {
  216. title: '业务分类',
  217. dataIndex: 'busiClass',
  218. width: '150px',
  219. customRender: (text) => {
  220. if (text.indexOf('[') !== -1) {
  221. const data = JSON.parse(text)
  222. if (data.length > 0) {
  223. return JSON.parse(text)[0].name
  224. }
  225. return ''
  226. }
  227. return text
  228. },
  229. },
  230. {
  231. title: '指标名称',
  232. dataIndex: 'indiName',
  233. width: '150px',
  234. scopedSlots: { customRender: 'islink' },
  235. },
  236. {
  237. title: '指标时间维度',
  238. dataIndex: 'indiFrequency',
  239. },
  240. {
  241. title: '监测单位',
  242. dataIndex: 'monitorDeptStr',
  243. },
  244. {
  245. title: '数据时期',
  246. dataIndex: 'dataTime',
  247. scopedSlots: { customRender: 'dataTime' },
  248. },
  249. {
  250. title: '指标值',
  251. dataIndex: 'indiVal',
  252. },
  253. {
  254. title: '指标值单位',
  255. dataIndex: 'indiUnit',
  256. scopedSlots: { customRender: 'indiUnit' },
  257. },
  258. {
  259. title: '预警状态',
  260. dataIndex: 'alertStatus',
  261. scopedSlots: { customRender: 'alertStatus' },
  262. },
  263. ]
  264. } else {
  265. this.dataUrl = ' api/xcoa-mobile/v1/kpi-indi-def/list'
  266. }
  267. },
  268. methods: {
  269. // 获取指标值单位
  270. getIndiUnitValue(val) {
  271. return this.optionsArray.optionsindiUnit.find((item) => {
  272. return item.value === val
  273. })?.label
  274. },
  275. // 数据返回后,整理response对象
  276. processRes(res) {
  277. if (this.type === 'yc') {
  278. if (res.data) {
  279. res.data.forEach((item) => {
  280. if (item.monitorDeptNameStrs.indexOf(',') > -1) {
  281. const monitorDepts = item.monitorDeptNameStrs.split(',')
  282. const monitorDeptsid = item.monitorDeptIdStrs.split(',')
  283. const alertStatus = item.alertStatus.split(',')
  284. const indiUnit = item.indiUnit.split(',')
  285. const indiVal = item.indiVal.split(',')
  286. const indiNo = item.indiNo.split(',')
  287. const ids = item.id.split(',')
  288. const indiId = item.indiId
  289. const indiName = item.indiName
  290. const year = item.year.split(',')
  291. const dataPeriod = item.dataPeriod.split(',')
  292. const redStrs = item.redStrs.split('*~*')
  293. const yellowStrs = item.yellowStrs.split('*~*')
  294. const grenStrs = item.grenStrs.split('*~*')
  295. monitorDepts.forEach((mitem, mindex) => {
  296. if (mindex !== 0) {
  297. res.data.push({
  298. id: ids[mindex],
  299. busiClass: item.busiClass,
  300. indiName: item.indiName,
  301. indiFrequency: item.indiFrequency,
  302. monitorRange: item.monitorRange,
  303. monitorDeptStr: mitem,
  304. alertStatus: alertStatus[mindex],
  305. indiNo: indiNo[mindex],
  306. indiVal: indiVal[mindex],
  307. indiUnit: indiUnit[mindex],
  308. indiId: indiId,
  309. indiNameChildren: indiName,
  310. year: year[mindex],
  311. dataPeriod: dataPeriod[mindex],
  312. redStrs: redStrs[mindex],
  313. yellowStrs: yellowStrs[mindex],
  314. grenStrs: grenStrs[mindex],
  315. })
  316. } else {
  317. // 首级
  318. item.monitorDeptStr = mitem // 监测单位
  319. item.alertStatus = alertStatus[mindex]
  320. item.indiVal = indiVal[mindex]
  321. item.indiUnit = indiUnit[mindex]
  322. item.indiNo = indiNo[mindex]
  323. item.id = ids[mindex]
  324. item.year = year[mindex]
  325. item.dataPeriod = dataPeriod[mindex]
  326. item.redStrs = redStrs[mindex]
  327. item.yellowStrs = yellowStrs[mindex]
  328. item.grenStrs = grenStrs[mindex]
  329. }
  330. })
  331. } else {
  332. item.monitorDeptStr = item.monitorDeptNameStrs
  333. }
  334. })
  335. }
  336. }
  337. return res
  338. },
  339. handleOk() {
  340. const rows = this.$refs.dataTable.getSelectedRows()
  341. this.$emit('handleOk', rows)
  342. },
  343. handleCancel(event) {
  344. this.$emit('handleCancel', event)
  345. },
  346. // 获取用于选择的业务类型分类树
  347. loadTreeData(id) {
  348. const topDepId = !id ? 0 : id
  349. const params = {
  350. type: this.treeparams.type,
  351. }
  352. return KpiService.getCategoryTree(topDepId, this.treeparams, params)
  353. .then((res) => {
  354. const treeNode = res.data
  355. return this.mapCategoryItems(treeNode)
  356. })
  357. .catch((e) => {
  358. message.error({ content: '应用类型获取失败' })
  359. })
  360. },
  361. mapCategoryItems(items) {
  362. return (items || []).map((item) => {
  363. const result = {
  364. id: item.id + '',
  365. name: item.text,
  366. // checkable: true,
  367. isLeaf: item.leaf,
  368. checkable: !item.expandable,
  369. }
  370. return result
  371. })
  372. },
  373. // 获取数据字典
  374. getDictionary(id, fieldName) {
  375. return kpiAnalysisFormService
  376. .getDictValue(id)
  377. .then((res) => {
  378. if (res.data) {
  379. res.data.forEach((item) => {
  380. this.optionsArray[fieldName].push({
  381. label: item.name,
  382. value: item.id,
  383. })
  384. })
  385. }
  386. })
  387. .catch((e) => {
  388. message.error({ content: '数据字典获取失败' })
  389. })
  390. },
  391. // 重置查询
  392. resetForm() {
  393. this.listExpressions = []
  394. this.formData = {
  395. indiName: '',
  396. busiClass: [],
  397. alertStatus: '',
  398. indiFrequency: '',
  399. monitorRange: '',
  400. monitorDept: '',
  401. }
  402. },
  403. // 查询
  404. handleSearch() {
  405. this.listExpressions = []
  406. if (this.type === 'yc') {
  407. this.expressions.push({
  408. dataType: 'long',
  409. name: 'creationTime',
  410. op: 'ge',
  411. longValue: `${new Date(new Date().getFullYear() - 1 + '-01-01 00:00:00').getTime()}`,
  412. })
  413. }
  414. // 业务分类
  415. if (this.formData.busiClass[0]) {
  416. this.listExpressions.push({
  417. dataType: 'str',
  418. name: 'busiClass',
  419. op: 'eq',
  420. stringValue: `${this.formData.busiClass[0].name}`,
  421. })
  422. }
  423. // 指标名称
  424. if (this.formData.indiName) {
  425. this.listExpressions.push({
  426. dataType: 'str',
  427. name: 'indiName',
  428. op: 'like',
  429. stringValue: `${this.formData.indiName}`,
  430. })
  431. }
  432. // 指标时间维度
  433. if (this.formData.indiFrequency) {
  434. this.listExpressions.push({
  435. dataType: 'str',
  436. name: 'indiFrequency',
  437. op: 'eq',
  438. stringValue: `${this.formData.indiFrequency}`,
  439. })
  440. }
  441. // 监测范围
  442. if (this.formData.monitorRange) {
  443. this.listExpressions.push({
  444. dataType: 'str',
  445. name: 'monitorRange',
  446. op: 'eq',
  447. stringValue: `${this.formData.monitorRange}`,
  448. })
  449. }
  450. // 监测单位
  451. if (this.formData.monitorDept[0]) {
  452. let deptnames = ''
  453. this.formData.monitorDept.forEach((item) => {
  454. if (deptnames === '') {
  455. deptnames = item.name
  456. } else {
  457. deptnames = deptnames + ',' + item.name
  458. }
  459. })
  460. this.listExpressions.push({
  461. dataType: 'str',
  462. name: 'monitorDept',
  463. op: 'eq',
  464. stringValue: `${deptnames}`,
  465. })
  466. }
  467. // 预警状态
  468. if (this.formData.alertStatus) {
  469. this.expressions.push({
  470. dataType: 'str',
  471. name: 'alertStatus',
  472. op: 'eq',
  473. stringValue: `${this.formData.alertStatus}`,
  474. })
  475. }
  476. },
  477. },
  478. }
  479. </script>
  480. <style module lang="scss">
  481. @use '@/common/design' as *;
  482. .tree-select {
  483. :global .ant-select {
  484. padding: 0;
  485. }
  486. }
  487. .select-modal {
  488. :global(.ant-table) {
  489. min-height: 300px;
  490. }
  491. }
  492. .status {
  493. width: 25px;
  494. height: 25px;
  495. background-color: #aaaaaa;
  496. margin-left: 20px;
  497. color: #fff;
  498. padding-left: 4px;
  499. border-radius: 3px;
  500. }
  501. .redstatus {
  502. width: 25px;
  503. height: 25px;
  504. background-color: #fb0606;
  505. margin-left: 20px;
  506. color: #fff;
  507. padding-left: 4px;
  508. border-radius: 3px;
  509. }
  510. .ystatus {
  511. width: 25px;
  512. height: 25px;
  513. background-color: #fff600;
  514. margin-left: 20px;
  515. color: #fff;
  516. padding-left: 4px;
  517. border-radius: 3px;
  518. }
  519. .lstatus {
  520. width: 25px;
  521. height: 25px;
  522. background-color: #8dcb98;
  523. margin-left: 20px;
  524. color: #fff;
  525. padding-left: 4px;
  526. border-radius: 3px;
  527. }
  528. </style>