kpi-alert-order-form.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. <template>
  2. <div>
  3. <sd-webflow
  4. ref="flow"
  5. :removed-tabs="['sdRelatedDoc']"
  6. :class="$style.form"
  7. :validate-form="validForm"
  8. >
  9. <template v-slot:form="{ model, fields }">
  10. <table>
  11. <tr>
  12. <td style="border: none">
  13. <audit-advanced-group
  14. :expand="expand"
  15. expand-str="expand"
  16. :group-label="'基本信息'"
  17. tablestyle="''"
  18. @changedClick="changedClick"
  19. ></audit-advanced-group>
  20. </td>
  21. </tr>
  22. </table>
  23. <table v-show="expand">
  24. <colgroup>
  25. <col style="width: 185px;" /><col /> <col style="width: 185px;" /><col />
  26. </colgroup>
  27. <tr>
  28. <!-- 标题 -->
  29. <sd-form-item-td name="title" label="预警内容" :colspan="3" />
  30. </tr>
  31. <tr>
  32. <!-- 接收人 -->
  33. <sd-form-item-td name="receiverMember" @change="userChange" />
  34. <!-- 接收人id -->
  35. <sd-form-item-td name="receiverId" :hidden="true" />
  36. <!-- 接收人account -->
  37. <sd-form-item-td name="receiverAccount" :hidden="true" />
  38. <!-- 接收人中文名 -->
  39. <sd-form-item-td name="receiverName" :hidden="true" />
  40. <!-- 联系电话 -->
  41. <sd-form-item-td name="contactPhone"> </sd-form-item-td>
  42. </tr>
  43. <tr>
  44. <!-- 接收单位 -->
  45. <sd-form-item-td name="receiverDeptMember" label="接收单位">
  46. <template v-slot:read-and-edit="{ editable }">
  47. {{ getDeptName(model.receiverDeptMember) }}
  48. </template>
  49. </sd-form-item-td>
  50. <!-- 办理时限 -->
  51. <sd-form-item-td name="limitDate" />
  52. </tr>
  53. <tr>
  54. <!-- 说明 -->
  55. <sd-form-item-td name="remark" :colspan="3">
  56. <template v-slot:read-and-edit="{ editable }">
  57. <a-textarea
  58. v-if="editable"
  59. v-model="model.remark"
  60. :auto-size="{ minRows: 3, maxRows: 3 }"
  61. ></a-textarea>
  62. <div v-else>
  63. {{ model.remark }}
  64. </div>
  65. </template>
  66. </sd-form-item-td>
  67. </tr>
  68. <tr>
  69. <!-- 附件 -->
  70. <sd-form-item-td name="attachment" :colspan="3">
  71. <template v-slot:read-and-edit="{ editable }">
  72. <sd-attachment
  73. v-model="model.attachment"
  74. :group-id="JSON.parse(fields.attachment.value).value"
  75. :read-only="!editable"
  76. ></sd-attachment>
  77. </template>
  78. </sd-form-item-td>
  79. </tr>
  80. <tr>
  81. <!-- 创建人员 -->
  82. <sd-form-item-td name="creatorName" />
  83. <!-- 创建单位 -->
  84. <sd-form-item-td name="createDeptName" />
  85. </tr>
  86. <tr>
  87. <!-- 创建日期 -->
  88. <sd-form-item-td v-show="formReady()" name="creationTime" :colspan="3" />
  89. </tr>
  90. </table>
  91. <table>
  92. <tr :class="$style.childTableTr">
  93. <!-- 预警指标 -->
  94. <sd-form-item-td name="kpiAlertOrderDetailList" :label="null" :colspan="4">
  95. <template v-slot:read-and-edit="{ editable }">
  96. <audit-advanced-group
  97. :expand="orderExpand"
  98. expand-str="orderExpand"
  99. group-label="预警指标"
  100. @changedClick="changedClick"
  101. >
  102. <template>
  103. <div v-show="showBtn && orderExpand && editable" :class="$style.btnselect">
  104. <a-button type="link" :class="$style.batchselect" @click="showSelectName">
  105. <a-icon type="check-circle" :theme="'filled'" />
  106. 选择
  107. </a-button>
  108. </div>
  109. <kpi-alert-order-child-table
  110. :key="childTableKey"
  111. ref="orderTable"
  112. v-model="model.kpiAlertOrderDetailList"
  113. :class="$style.orderChild"
  114. :edit-row="editRow"
  115. :show-btn="showBtn"
  116. :label="null"
  117. :read-only="false"
  118. :addbuttonvisiable="false"
  119. :fields="
  120. [
  121. {
  122. caption: '序号',
  123. name: 'sortNum',
  124. dataType: 'number',
  125. },
  126. ]
  127. .concat(Array.from(fields.kpiAlertOrderDetailList.attr.dync))
  128. .concat([
  129. {
  130. caption: '操作',
  131. name: 'action',
  132. dataType: 'string',
  133. },
  134. ])
  135. "
  136. :columns="orderColumns"
  137. >
  138. <!-- 指标名称 -->
  139. <template v-slot:indiName="{ field, text, record }">
  140. <a :title="text" @click="rowClick($event, record)">{{ text }}</a>
  141. </template>
  142. <!-- 数据时期 -->
  143. <template v-slot:dataPeriod="{ field, text, record }">
  144. {{ record.year + '年' + record.dataPeriod }}
  145. </template>
  146. <!-- 指标值单位 -->
  147. <template v-slot:indiUnit="{ field, text }">
  148. {{ text }}
  149. </template>
  150. <!-- 预警状态 -->
  151. <template v-slot:alertStatus="{ field, text, record }">
  152. <div
  153. :title="
  154. '\n红:' +
  155. record.redStrs +
  156. '\r\n黄:' +
  157. record.yellowStrs +
  158. '\r\n绿:' +
  159. record.grenStrs +
  160. ' '
  161. "
  162. >
  163. <div v-if="record.alertStatus === 'D'" :class="$style.status">无</div>
  164. <div v-else-if="record.alertStatus === 'A'" :class="$style.redstatus"
  165. >红</div
  166. >
  167. <div v-else-if="record.alertStatus === 'B'" :class="$style.ystatus"
  168. >黄</div
  169. >
  170. <div v-else-if="record.alertStatus === 'C'" :class="$style.lstatus"
  171. >绿</div
  172. >
  173. </div>
  174. </template>
  175. <!-- 操作 -->
  176. <template v-slot:action="{ field, text, record }">
  177. <a :title="text">反馈</a>
  178. </template>
  179. <!-- 表单插槽 -->
  180. <template v-slot:form="{ fields, model }">
  181. <!-- 异常原因 -->
  182. <sd-form-item name="abnormalReason" :label="'异常原因'">
  183. <template v-slot:read-and-edit="{ editable }">
  184. <a-textarea
  185. v-model="model.abnormalReason"
  186. :auto-size="{ maxRows: 3, minRows: 3 }"
  187. ></a-textarea>
  188. </template>
  189. </sd-form-item>
  190. <!-- 整改措施 -->
  191. <sd-form-item name="correctWay" :label="'整改措施'">
  192. <template v-slot:read-and-edit="{ editable }">
  193. <a-textarea
  194. v-model="model.correctWay"
  195. :auto-size="{ maxRows: 3, minRows: 3 }"
  196. ></a-textarea>
  197. </template>
  198. </sd-form-item>
  199. <!-- 附件 -->
  200. <sd-form-item name="attachment" :label="'附件'"> </sd-form-item>
  201. </template>
  202. </kpi-alert-order-child-table>
  203. </template>
  204. </audit-advanced-group>
  205. </template>
  206. </sd-form-item-td>
  207. </tr>
  208. </table>
  209. </template>
  210. </sd-webflow>
  211. <!-- 异常指标选择器 -->
  212. <kpi-analysis-select-modal
  213. :visible="visible"
  214. type="yc"
  215. :select-expressions="[
  216. {
  217. dataType: 'long',
  218. name: 'creationTime',
  219. op: 'ge',
  220. longValue: `${new Date(new Date().getFullYear() - 1 + '-01-01 00:00:00').getTime()}`,
  221. },
  222. ]"
  223. @handleCancel="handleCancel"
  224. @handleOk="handleOk"
  225. />
  226. </div>
  227. </template>
  228. <script>
  229. import { message } from '@/common/one-ui'
  230. import crossWindowWatcher from '@/common/services/cross-window-watcher'
  231. import auditAdvancedGroup from '@product/iam/components/audit-advanced-group.vue'
  232. import auditAdvancedGroupMixins from '@product/iam/components/audit-advanced-group-mixins'
  233. import kpiAnalysisSelectModal from '../analysis/kpi-analysis-select-modal.vue'
  234. import KpiService from '../kpi-service'
  235. import kpiAlertOrderChildTable from './kpi-alert-order-child-table.vue'
  236. import kpiAlertOrderService from './kpi-alert-order-service'
  237. import components from './_import-components/kpi-alert-order-form-import'
  238. export default {
  239. name: 'KpiAlertOrderForm',
  240. metaInfo: {
  241. title: '指标预警单',
  242. },
  243. components: {
  244. kpiAlertOrderChildTable,
  245. kpiAnalysisSelectModal,
  246. auditAdvancedGroup,
  247. ...components,
  248. },
  249. mixins: [auditAdvancedGroupMixins],
  250. data() {
  251. return {
  252. isReady: false,
  253. childTableKey: 0,
  254. indiUnitDict: [], // 指标值单位字典
  255. editRow: false,
  256. showBtn: false,
  257. visible: false,
  258. expand: true,
  259. orderExpand: true,
  260. orderColumns: [
  261. {
  262. title: '序号',
  263. dataIndex: 'sortNum',
  264. customRender: (text, record, index) => `${index + 1}`,
  265. width: '80px',
  266. },
  267. { dataIndex: 'id', sdHidden: true },
  268. { dataIndex: 'indiId', sdHidden: true },
  269. { dataIndex: 'monitorId', sdHidden: true },
  270. { dataIndex: 'orderId', sdHidden: true },
  271. { dataIndex: 'monitorDeptId', sdHidden: true },
  272. { dataIndex: 'monitorDeptCode', sdHidden: true },
  273. { dataIndex: 'year', sdHidden: true },
  274. {
  275. title: '指标名称',
  276. dataIndex: 'indiName',
  277. },
  278. {
  279. title: '指标编号',
  280. dataIndex: 'indiNo',
  281. },
  282. {
  283. title: '指标时间维度',
  284. dataIndex: 'indiFrequency',
  285. },
  286. {
  287. title: '监测单位',
  288. dataIndex: 'monitorDeptName',
  289. },
  290. {
  291. title: '数据时期',
  292. dataIndex: 'dataPeriod',
  293. },
  294. { title: '指标值', dataIndex: 'indiVal' },
  295. { title: '指标值单位', dataIndex: 'indiUnit' },
  296. { title: '预警状态', dataIndex: 'alertStatus' },
  297. { title: '异常原因', dataIndex: 'abnormalReason' },
  298. { title: '整改措施', dataIndex: 'correctWay' },
  299. { title: '附件', dataIndex: 'attachment', width: '230px' },
  300. ],
  301. }
  302. },
  303. created() {
  304. // 获取指标值单位
  305. kpiAlertOrderService.getDictValue('INDI_UNIT').then((res) => {
  306. this.indiUnitDict = res.data
  307. })
  308. if (this.$route.query.extParams) {
  309. const e = this.$route.query.extParams
  310. const eo = JSON.parse(e)
  311. const id = eo.zbid
  312. KpiService.getIndiMonitorsByIds(id).then((res) => {
  313. if (res.data) {
  314. let data = []
  315. res.data.forEach((item) => {
  316. if (item.monitorDeptNameStrs.indexOf(',') > -1) {
  317. const monitorDepts = item.monitorDeptNameStrs.split(',')
  318. const monitorDeptsid = item.monitorDeptIdStrs.split(',')
  319. const alertStatus = item.alertStatus.split(',')
  320. const indiUnit = item.indiUnit.split(',')
  321. const indiVal = item.indiVal.split(',')
  322. const indiNo = item.indiNo.split(',')
  323. const year = item.year.split(',')
  324. const dataPeriod = item.dataPeriod.split(',')
  325. const monitorId = item.id.split(',')
  326. monitorDepts.forEach((mitem, mindex) => {
  327. const nitem = { ...item }
  328. nitem.monitorDeptStr = mitem
  329. nitem.monitorDeptId = monitorDeptsid[mindex]
  330. nitem.alertStatus = alertStatus[mindex]
  331. nitem.indiUnit = indiUnit[mindex]
  332. nitem.indiVal = indiVal[mindex]
  333. nitem.indiNo = indiNo[mindex]
  334. nitem.year = year[mindex]
  335. nitem.dataPeriod = dataPeriod[mindex]
  336. nitem.monitorId = monitorId[mindex]
  337. data = this.fnpd(data, nitem)
  338. })
  339. } else {
  340. item.monitorDeptId = item.monitorDeptIdStrs
  341. item.monitorDeptStr = item.monitorDeptNameStrs
  342. item.monitorId = item.id
  343. data = this.fnpd(data, item)
  344. }
  345. })
  346. this.$refs.flow.setFieldValue('kpiAlertOrderDetailList', data)
  347. }
  348. })
  349. }
  350. },
  351. methods: {
  352. fnpd(data, d) {
  353. const attach = this.fncreaterd()
  354. data.push({
  355. id: null,
  356. indiId: d.indiId,
  357. monitorId: d.monitorId,
  358. monitorDeptId: d.monitorDeptId,
  359. monitorDeptCode: d.monitorDeptCode,
  360. indiName: d.indiName,
  361. indiNo: d.indiNo,
  362. indiFrequency: d.indiFrequency,
  363. monitorDeptName: d.monitorDeptStr,
  364. dataTime: d.dataTime,
  365. year: d.year,
  366. dataPeriod: d.dataPeriod,
  367. indiVal: d.indiVal,
  368. indiUnit: d.indiUnit,
  369. alertStatus: d.alertStatus,
  370. attachment: '{"value":"' + attach + '"}',
  371. })
  372. return data
  373. },
  374. fncreaterd() {
  375. var num = ''
  376. for (var i = 0; i < 17; i++) {
  377. if (i === 0) {
  378. num += Math.floor(Math.random() * 9 + 1)
  379. } else {
  380. num += Math.floor(Math.random() * 10)
  381. }
  382. }
  383. return num
  384. },
  385. rowClick(e, record) {
  386. const url = '/kpi-indi-form?record=' + record.indiId + '&mode=view' // 新页面要打开的路由地址
  387. crossWindowWatcher.waitForChanged(url)
  388. e.stopPropagation()
  389. },
  390. // 显示选择异常指标列表
  391. showSelectName(e) {
  392. this.visible = true
  393. },
  394. // 异常指标选择确认
  395. handleOk(rows) {
  396. // 已有数据
  397. const tableData = this.$refs.flow.getFieldValue('kpiAlertOrderDetailList')
  398. const tableId = tableData.map((item) => item.monitorId + '')
  399. const selectData = []
  400. let flag = false // 会否有重复
  401. rows.forEach((item) => {
  402. item.monitorDeptName = item.monitorDeptStr
  403. item.monitorId = item.id
  404. item.indiNo = item.indiNo.includes(',') ? item.indiNo.split(',')[0] : item.indiNo
  405. item.id = null
  406. item.attachment =
  407. '{"value":"' + Math.round(Math.random() * 100000000000000000).toString() + '"}'
  408. if (!tableId.includes(item.monitorId)) {
  409. selectData.push(item)
  410. } else {
  411. flag = true
  412. }
  413. })
  414. if (flag) {
  415. message.info('请勿选择重复数据', 1)
  416. }
  417. this.$refs.flow.setFieldValue('kpiAlertOrderDetailList', tableData.concat(selectData))
  418. this.handleCancel()
  419. },
  420. // 异常指标选择取消
  421. handleCancel(event) {
  422. this.visible = false
  423. },
  424. // 用户变化时
  425. userChange(val) {
  426. if (val.length === 0) {
  427. this.$refs.flow.setFieldValue('receiverDeptMember', [])
  428. return
  429. }
  430. this.$refs.flow.setFieldValue('receiverAccount', val[0].code)
  431. this.$refs.flow.setFieldValue('receiverName', val[0].name)
  432. kpiAlertOrderService.getGroupByUserAccount(val[0].code).then((res) => {
  433. this.$refs.flow.setFieldValue('receiverDeptMember', [
  434. {
  435. id: res.data.id,
  436. text: res.data.name,
  437. leaf: false,
  438. expandable: true,
  439. differentDisplay: false,
  440. props: {
  441. expandFlag: 'false',
  442. code: res.data.code,
  443. fullpath: '',
  444. weight: res.data.props.weight,
  445. fullpathId: '',
  446. type: 'G',
  447. lev: res.data.props.lev,
  448. levPath: res.data.name,
  449. },
  450. title: res.data.name,
  451. code: res.data.id,
  452. name: res.data.name,
  453. type: 'Group',
  454. },
  455. ])
  456. })
  457. },
  458. // 表单加载时
  459. formReady() {
  460. if (this.$refs.flow) {
  461. if (this.isReady) return true
  462. this.isReady = true
  463. this.orderColumns.push({
  464. title: '操作',
  465. dataIndex: 'action',
  466. sdHidden: true,
  467. })
  468. if (this.$refs.flow.FlowData.mode === 'VIEW') {
  469. this.editRow = false
  470. this.showBtn = false
  471. } else if (this.$refs.flow.FlowData.attrs.kpi$alertOrderReview) {
  472. this.editRow = true
  473. this.orderColumns.find((item) => {
  474. return item.dataIndex === 'action'
  475. }).sdHidden = false
  476. this.childTableKey++
  477. }
  478. // 起草环节不能编辑行
  479. if (this.$refs.flow.FlowData.attrs.stepN === 0) {
  480. this.editRow = false
  481. this.showBtn = true
  482. }
  483. }
  484. return true
  485. },
  486. // 获取指标值单位
  487. getIndiUnitValue(val) {
  488. return this.indiUnitDict.find((item) => {
  489. return item.id === val
  490. })?.name
  491. },
  492. getDeptName(val) {
  493. if (val && val.length !== 0) {
  494. return val[0].name
  495. } else {
  496. return ''
  497. }
  498. },
  499. // 自定义校验
  500. validForm() {
  501. // 获取环节号
  502. const flowNum = this.$refs.flow.flowData.attrs.stepN
  503. // 起草环节才校验,至少选择一条指标定义单,否则无意义
  504. if (flowNum === 0) {
  505. const data = this.$refs.flow.getFieldValue('kpiAlertOrderDetailList')
  506. if (data.length === 0) {
  507. message.info('请选择需要预警的异常指标', 1)
  508. return Promise.resolve(false)
  509. }
  510. return Promise.resolve(true)
  511. } else {
  512. return Promise.resolve(true)
  513. }
  514. },
  515. },
  516. }
  517. </script>
  518. <style module lang="scss">
  519. @use '@/common/design' as *;
  520. .form {
  521. :global(.ant-calendar-picker) {
  522. width: 100%;
  523. }
  524. }
  525. .child-table-tr {
  526. td:first-child {
  527. padding: 0 !important;
  528. }
  529. }
  530. .btnselect {
  531. position: relative;
  532. top: -1px;
  533. right: 100px;
  534. float: right;
  535. .batchselect {
  536. z-index: 100;
  537. margin-left: 10px;
  538. }
  539. }
  540. .status {
  541. width: 25px;
  542. height: 25px;
  543. background-color: #aaaaaa;
  544. margin-left: 20px;
  545. color: #fff;
  546. padding-left: 4px;
  547. border-radius: 3px;
  548. }
  549. .redstatus {
  550. width: 25px;
  551. height: 25px;
  552. background-color: #fb0606;
  553. margin-left: 20px;
  554. color: #fff;
  555. padding-left: 4px;
  556. border-radius: 3px;
  557. }
  558. .ystatus {
  559. width: 25px;
  560. height: 25px;
  561. background-color: #fff600;
  562. margin-left: 20px;
  563. color: #fff;
  564. padding-left: 4px;
  565. border-radius: 3px;
  566. }
  567. .lstatus {
  568. width: 25px;
  569. height: 25px;
  570. background-color: #8dcb98;
  571. margin-left: 20px;
  572. color: #fff;
  573. padding-left: 4px;
  574. border-radius: 3px;
  575. }
  576. </style>