alter-form.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. <template>
  2. <div class="hc-task-form">
  3. <!-- 基础表单 -->
  4. <hc-card-item>
  5. <el-form ref="baseFormRef" :model="baseForm" :rules="baseFormRules" label-position="left" label-width="auto">
  6. <el-row :gutter="20">
  7. <el-col :span="8">
  8. <el-form-item label="变更令编号:" prop="changeNumber">
  9. <el-input
  10. v-model="baseForm.changeNumber" :disabled="!isEdits || tableInfo.status === 2"
  11. @blur="currentInputBlur('changeNumber')" @focus="currentInputFocus('changeNumber')"
  12. />
  13. </el-form-item>
  14. </el-col>
  15. <el-col :span="8">
  16. <el-form-item label="变更令名称:" prop="changeName">
  17. <el-input
  18. v-model="baseForm.changeName" :disabled="!isEdits || tableInfo.status === 2"
  19. @blur="currentInputBlur('changeName')" @focus="currentInputFocus('changeName')"
  20. />
  21. </el-form-item>
  22. </el-col>
  23. <el-col :span="8">
  24. <el-form-item label="变更发起单位:">
  25. <el-input
  26. v-model="baseForm.changeUnit" :disabled="!isEdits || tableInfo.status === 2"
  27. @blur="currentInputBlur('changeUnit')" @focus="currentInputFocus('changeUnit')"
  28. />
  29. </el-form-item>
  30. </el-col>
  31. <el-col :span="8">
  32. <el-form-item label="业务日期:" prop="businessDate">
  33. <el-date-picker
  34. v-model="baseForm.businessDate" class="block" format="YYYY-MM-DD" type="date"
  35. value-format="YYYY-MM-DD" :disabled="!isEdits || tableInfo.status === 2"
  36. @blur="currentInputBlur('businessDate')" @focus="currentInputFocus('businessDate')"
  37. />
  38. </el-form-item>
  39. </el-col>
  40. <el-col :span="8">
  41. <el-form-item label="变更类型:">
  42. <el-select
  43. v-model="baseForm.changeType" filterable block :disabled="!isEdits || tableInfo.status === 2"
  44. @blur="currentInputBlur('changeType')" @focus="currentInputFocus('changeType')"
  45. >
  46. <el-option v-for="item in typeData" :key="item.value" :label="item.label" :value="item.value" />
  47. </el-select>
  48. </el-form-item>
  49. </el-col>
  50. <el-col :span="8">
  51. <el-form-item label="延长工期:">
  52. <el-input
  53. v-model="baseForm.lengthenDays" :disabled="!isEdits || tableInfo.status === 2"
  54. @blur="currentInputBlur('lengthenDays')" @focus="currentInputFocus('lengthenDays')"
  55. />
  56. </el-form-item>
  57. </el-col>
  58. <el-col :span="8">
  59. <el-form-item label="变更申请金额:">
  60. <el-input v-model="baseForm.changeMoney" disabled />
  61. </el-form-item>
  62. </el-col>
  63. <el-col :span="8">
  64. <el-form-item label="设计完成时间:" prop="designDate">
  65. <el-date-picker
  66. v-model="baseForm.designDate" class="block" format="YYYY-MM-DD" type="date"
  67. value-format="YYYY-MM-DD" :disabled="!isEdits || tableInfo.status === 2"
  68. @blur="currentInputBlur('designDate')" @focus="currentInputFocus('designDate')"
  69. />
  70. </el-form-item>
  71. </el-col>
  72. <el-col :span="8">
  73. <el-form-item label="实际变更桩号:">
  74. <el-input
  75. v-model="baseForm.realityChangeNumber" :disabled="!isEdits || tableInfo.status === 2"
  76. @blur="currentInputBlur('realityChangeNumber')" @focus="currentInputFocus('realityChangeNumber')"
  77. />
  78. </el-form-item>
  79. </el-col>
  80. <el-col :span="8">
  81. <el-form-item label="变更归类:">
  82. <el-select
  83. v-model="baseForm.changeClassify" filterable block :disabled="!isEdits || tableInfo.status === 2"
  84. @blur="currentInputBlur('changeClassify')" @focus="currentInputFocus('changeClassify')"
  85. >
  86. <el-option v-for="item in classifyData" :key="item.value" :label="item.label" :value="item.value" />
  87. </el-select>
  88. </el-form-item>
  89. </el-col>
  90. <el-col :span="8">
  91. <el-form-item label="变更批复文号:">
  92. <el-input
  93. v-model="baseForm.changeApprovalNumber" :disabled="!isEdits || tableInfo.status === 2"
  94. @blur="currentInputBlur('changeApprovalNumber')" @focus="currentInputFocus('changeApprovalNumber')"
  95. />
  96. </el-form-item>
  97. </el-col>
  98. <el-col :span="8">
  99. <el-form-item label="变更批复日期:" prop="changeApprovalDate">
  100. <el-date-picker
  101. v-model="baseForm.changeApprovalDate" class="block" format="YYYY-MM-DD" type="date"
  102. value-format="YYYY-MM-DD" :disabled="!isEdits || tableInfo.status === 2"
  103. @blur="currentInputBlur('changeApprovalDate')" @focus="currentInputFocus('changeApprovalDate')"
  104. />
  105. </el-form-item>
  106. </el-col>
  107. <el-col :span="24">
  108. <el-form-item label="变更原因:">
  109. <el-input
  110. v-model="baseForm.changeCause" :autosize="{ minRows: 4, maxRows: 8 }" type="textarea"
  111. :disabled="!isEdits || tableInfo.status === 2" @blur="currentInputBlur('changeCause')"
  112. @focus="currentInputFocus('changeCause')"
  113. />
  114. </el-form-item>
  115. </el-col>
  116. </el-row>
  117. </el-form>
  118. </hc-card-item>
  119. <!-- 变更申请部位 -->
  120. <hc-card-item title="变更申请部位" class="mt-3">
  121. <hc-table ref="tableRef1" :column="tableColumn" :datas="tableData" is-new is-current-row :index-style="{ width: 60 }" @row-click="rowChangeNodeClick">
  122. <template #contractPicture="{ row }">
  123. <hc-table-input
  124. v-model="row.contractPicture" :disabled="!isEdits || tableInfo.status === 2"
  125. @focus="meterInputFocus(row)" @blur="meterInputBlur(row)"
  126. />
  127. </template>
  128. <template #action="{ row, index }">
  129. <el-link type="danger" @click="delChangeNode(row)">删除</el-link>
  130. </template>
  131. </hc-table>
  132. </hc-card-item>
  133. <!-- 变更申请清单 -->
  134. <hc-card-item title="变更申请清单" class="mt-3">
  135. <template #extra>
  136. <el-link type="primary" :disabled="!isEdits || tableInfo.status === 2" @click="changeShowClick">添加</el-link>
  137. </template>
  138. <div class="hc-table-ref-box no-border">
  139. <el-table class="w-full" :data="tableData[tableIndex]?.formList" row-key="id" height="100%" highlight-current-row border>
  140. <el-table-column type="index" label="序号" />
  141. <el-table-column prop="formNumber" label="清单编号" />
  142. <el-table-column prop="formName" label="清单名称" />
  143. <el-table-column prop="currentPrice" label="单价" />
  144. <el-table-column label="数量" align="center">
  145. <el-table-column prop="contractTotal" label="变更前" />
  146. <el-table-column prop="currentChangeTotal" label="变更增减">
  147. <template #default="{ row }">
  148. <hc-table-input
  149. v-model="row.currentChangeTotal" :disabled="!isEdits || tableInfo.status === 2"
  150. @focus="totalInputFocus(row)" @blur="totalInputBlur(row)"
  151. />
  152. </template>
  153. </el-table-column>
  154. <el-table-column prop="changeTotal" label="变更后" />
  155. </el-table-column>
  156. <el-table-column label="金额" align="center">
  157. <el-table-column prop="contractMoney" label="变更前" />
  158. <el-table-column prop="currentChangeMoney" label="变更增减" />
  159. <el-table-column prop="changeMoney" label="变更后" />
  160. </el-table-column>
  161. <el-table-column prop="action" label="操作" width="80" align="center">
  162. <template #default="{ row }">
  163. <el-link type="danger" @click="tableFormListDel(row)">删除</el-link>
  164. </template>
  165. </el-table-column>
  166. </el-table>
  167. </div>
  168. </hc-card-item>
  169. <!-- 附件列表 -->
  170. <hc-card-item class="mt-3" title="附件列表">
  171. <template #extra>
  172. <span class="text-[13px] text-orange font-400">可上传 图片(png、jpg、jpeg)、Excel(xls、xlsx)、PDF、Word(doc、docx)文件</span>
  173. </template>
  174. <el-form :model="baseForm" label-position="left" label-width="auto">
  175. <el-form-item label="上传附件">
  176. <hc-form-upload
  177. v-model="baseForm.fileList" is-del is-res
  178. :disabled="!isEdits || taskInfo.status === 2 || taskInfo.status === 3 || tableInfo.status === 1"
  179. :options="{ type: 'list', props: uploadFormProps, isArr: true, num: 0 }"
  180. :upload="{ options: { multiple: false } }"
  181. @success="uploadFileSuccess" @del="attachmentUploadDel"
  182. />
  183. </el-form-item>
  184. </el-form>
  185. </hc-card-item>
  186. <!-- 变更申请清单 -->
  187. <ChangeRequest v-model="isChangeShow" :info="changeNodeInfo" @finish="changeNodeFinish" />
  188. </div>
  189. </template>
  190. <script setup>
  191. import { nextTick, onMounted, ref, watch } from 'vue'
  192. import { useAppStore } from '~src/store'
  193. import ChangeRequest from './changeRequest.vue'
  194. import { delMessage, getDictionaryData, isNumberReg } from '~uti/tools'
  195. import { arrIndex, arrToKey, getArrValue, getObjVal, getObjValue, isArray, isNullES } from 'js-fast-way'
  196. import mainApi from '~api/tasks/hc-data'
  197. const props = defineProps({
  198. isEdit: {
  199. type: Boolean,
  200. default: true,
  201. },
  202. info: {
  203. type: Object,
  204. default: () => ({}),
  205. },
  206. table: {
  207. type: Object,
  208. default: () => ({}),
  209. },
  210. })
  211. const useAppState = useAppStore()
  212. const projectId = ref(useAppState.getProjectId || '')
  213. const contractId = ref(useAppState.getContractId || '')
  214. //监听可否编辑
  215. const isEdits = ref(props.isEdit)
  216. watch(() => props.isEdit, (val) => {
  217. isEdits.value = val
  218. }, { immediate: true, deep: true })
  219. //监听数据
  220. watch(() => [
  221. props.table,
  222. props.info,
  223. ], ([table, row]) => {
  224. setTaskInfo(table, row)
  225. }, { deep: true })
  226. //渲染完成
  227. onMounted(() => {
  228. setTaskInfo(props.table, props.info)
  229. })
  230. //设置任务信息
  231. const taskInfo = ref({})
  232. const tableInfo = ref({})
  233. const setTaskInfo = (table, row) => {
  234. tableInfo.value = table
  235. taskInfo.value = row
  236. if (getObjVal(table) && getObjVal(row)) {
  237. getMeterChangeClassify()
  238. getMeterChangeType()
  239. getDataDetail()
  240. }
  241. }
  242. //计量变更归类
  243. const classifyData = ref([])
  244. const getMeterChangeClassify = async () => {
  245. classifyData.value = await getDictionaryData('meter_change_classify')
  246. }
  247. //计量变更类型
  248. const typeData = ref([])
  249. const getMeterChangeType = async () => {
  250. typeData.value = await getDictionaryData('meter_change_type')
  251. }
  252. //获取任务数据信息详情
  253. const isLoading = ref(false)
  254. const getDataDetail = async () => {
  255. const id = taskInfo.value.id
  256. const dataId = tableInfo.value.id
  257. const { data } = await mainApi.getDataDetail({ id, dataId })
  258. //转换数据
  259. const { changeTokenFormVO, attachmentFormTask } = getObjValue(data)
  260. const res = getObjValue(changeTokenFormVO)
  261. baseForm.value = res //表单信息
  262. baseForm.value.fileList = getArrValue(attachmentFormTask) //附件列表
  263. const nodeList = getArrValue(res.nodeList)
  264. tableData.value = nodeList //部位列表
  265. if (nodeList.length > 0) {
  266. rowChangeNodeClick({ row: nodeList[0] })
  267. tableRef1.value?.tableRef?.setCurrentRow(nodeList[0])
  268. changeNodeItem.value = nodeList[0]
  269. tableIndex.value = 0
  270. }
  271. }
  272. //基础表单
  273. const baseFormRef = ref(null)
  274. const baseForm = ref({ fileList: [], pictureUrl: '' })
  275. const baseFormRules = {}
  276. //基础表单的输入框获得焦点
  277. const currentBaseForm = ref('')
  278. const currentInputFocus = (key) => {
  279. currentBaseForm.value = baseForm.value[key]
  280. }
  281. //基础表单的输入框失去焦点
  282. const currentInputBlur = async (key) => {
  283. if (currentBaseForm.value === baseForm.value[key]) {
  284. return false
  285. }
  286. //处理数据
  287. let form = {
  288. id: baseForm.value.id,
  289. taskId: taskInfo.value.id,
  290. }
  291. form[key] = baseForm.value[key]
  292. const { error, msg, code } = await mainApi.changeTokenFromUpdate(form)
  293. if (!error && code === 200) {
  294. window.$message.success('更新成功')
  295. } else {
  296. window.$message.error(msg ?? '更新失败')
  297. }
  298. }
  299. //清单表格
  300. const tableRef1 = ref(null)
  301. const tableColumn = ref([
  302. { key: 'nodeName', name: '工程名称' },
  303. { key: 'nodeUrl', name: '节点路径' },
  304. { key: 'contractPicture', name: '合同图号' },
  305. { key: 'changeMoney', name: '变更后金额(元)' },
  306. { key: 'isSupplementName', name: '是否增补' },
  307. { key: 'action', name: '操作', width: 80, align: 'center' },
  308. ])
  309. const tableData = ref([])
  310. //合同图号的输入框获得焦点
  311. const currentPicture = ref('')
  312. const meterInputFocus = (row) => {
  313. currentPicture.value = row.contractPicture
  314. }
  315. //合同图号的输入框失去焦点
  316. const meterInputBlur = async (row) => {
  317. if (currentPicture.value === row.contractPicture) {
  318. return false
  319. }
  320. //处理数据
  321. const { error, msg, code } = await mainApi.changeTokenMeterUpdate({
  322. primaryKeyId: row.primaryKeyId,
  323. taskId: taskInfo.value.id,
  324. contractPicture: row.contractPicture,
  325. })
  326. if (!error && code === 200) {
  327. window.$message.success('更新成功')
  328. } else {
  329. window.$message.error(msg ?? '更新失败')
  330. }
  331. }
  332. //删除变更申请部位
  333. const delChangeNode = (row) => {
  334. delMessage(async () => {
  335. const { code, msg } = await mainApi.remove({
  336. projectId: projectId.value,
  337. contractId: contractId.value,
  338. dataId: tableInfo.value.id,
  339. taskId: taskInfo.value.id,
  340. middleMeterInventoryFormId: '',
  341. changeNodeId: row.primaryKeyId,
  342. changeFormId: '',
  343. type: 1,
  344. })
  345. if (code === 200) {
  346. window.$message.success('删除成功')
  347. getDataDetail()
  348. } else {
  349. window.$message.error(msg ?? '删除失败')
  350. }
  351. })
  352. }
  353. //变更申请部位 行被点击
  354. const changeNodeItem = ref({})
  355. const tableIndex = ref(-1)
  356. const rowChangeNodeClick = ({ row }) => {
  357. const index = arrIndex(tableData.value, 'id', row.id)
  358. if (!isArray(row.formList)) {
  359. tableData.value[index].formList = []
  360. }
  361. tableIndex.value = index
  362. changeNodeItem.value = row
  363. }
  364. //删除变更申请清单
  365. const tableFormListDel = (row) => {
  366. delMessage(async () => {
  367. const { primaryKeyId } = changeNodeItem.value
  368. const { code, msg } = await mainApi.tableRemove({
  369. projectId: projectId.value,
  370. contractId: contractId.value,
  371. dataId: tableInfo.value.id,
  372. taskId: taskInfo.value.id,
  373. middleMeterInventoryFormId: '',
  374. changeFormId: row.primaryKeyId,
  375. changeNodeId: primaryKeyId,
  376. type: 2,
  377. })
  378. if (code === 200) {
  379. window.$message.success('删除成功')
  380. getDataDetail()
  381. } else {
  382. window.$message.error(msg ?? '删除失败')
  383. }
  384. })
  385. }
  386. //变更清单的添加弹窗
  387. const isChangeShow = ref(false)
  388. const changeNodeInfo = ref({})
  389. const changeShowClick = () => {
  390. const { id, primaryKeyId } = changeNodeItem.value
  391. if (isNullES(id)) {
  392. window.$message.warning('请先选择变更申请部位')
  393. return false
  394. }
  395. //处理数据
  396. const ids = arrToKey(tableData.value[tableIndex.value].formList, 'id')
  397. changeNodeInfo.value = {
  398. ids: ids,
  399. treeId: id ?? '',
  400. primaryKeyIdMeter: primaryKeyId ?? '',
  401. dataId: tableInfo.value.id ?? '',
  402. taskId: taskInfo.value.id ?? '',
  403. }
  404. nextTick(() => {
  405. isChangeShow.value = true
  406. })
  407. }
  408. //确认选择完成
  409. const changeNodeFinish = () => {
  410. getDataDetail()
  411. }
  412. //变更增减的输入框获得焦点
  413. const currentChangeTotal = ref('')
  414. const totalInputFocus = (row) => {
  415. currentChangeTotal.value = row.currentChangeTotal
  416. }
  417. //变更增减的输入框失去焦点
  418. const totalInputBlur = async (row) => {
  419. //如果为空
  420. let val = row.currentChangeTotal
  421. const isMeter = isNumberReg(val)
  422. if (isNullES(val) || !isMeter) {
  423. val = 0
  424. }
  425. if (currentChangeTotal.value === val) {
  426. return false
  427. }
  428. //处理数据
  429. const { error, msg, code } = await mainApi.changeTokenInventoryUpdate({
  430. contractId: contractId.value,
  431. primaryKeyIdInventory: row.primaryKeyId ?? '',
  432. primaryKeyIdMeter: changeNodeItem.value?.primaryKeyId ?? '',
  433. taskId: taskInfo.value.id ?? '',
  434. dataId: tableInfo.value.id ?? '',
  435. changTotal: val,
  436. })
  437. if (!error && code === 200) {
  438. window.$message.success('更新成功')
  439. getDataDetail().then()
  440. } else {
  441. window.$message.error(msg ?? '更新失败')
  442. }
  443. }
  444. //文件上传
  445. const uploadFormProps = {
  446. url: 'filePdfUrl',
  447. name: 'fileName',
  448. }
  449. // 文件上传成功的回调
  450. const uploadFileSuccess = async ({ res }, resolve) => {
  451. const { link, pdfUrl, originalName } = getObjValue(res.data)
  452. if (isNullES(pdfUrl)) {
  453. window.$message.warning('该文件不能生成pdf,请更换文件上传')
  454. resolve()
  455. return
  456. }
  457. resolve({
  458. contractId: contractId.value,
  459. fileName: originalName ?? '',
  460. filePdfUrl: pdfUrl ?? '',
  461. pdfUrl: pdfUrl ?? '',
  462. fileUrl: link ?? '',
  463. taskId: taskInfo.value.id,
  464. })
  465. //发起请求
  466. const dataId = tableInfo.value.id
  467. const { error, code, msg } = await mainApi.taskUploadFile({
  468. projectId: projectId.value,
  469. contractId: contractId.value,
  470. fileList: baseForm.value.fileList,
  471. taskId: taskInfo.value.id,
  472. dataId,
  473. })
  474. if (!error && code === 200) {
  475. window.$message.success('上传成功')
  476. } else {
  477. window.$message.error(msg ?? '上传失败')
  478. }
  479. }
  480. //删除文件
  481. const attachmentUploadDel = ({ file }, resolve) => {
  482. if (!isEdits.value) {
  483. window.$message.error('当前状态不可删除')
  484. resolve(false)
  485. return
  486. }
  487. delMessage(async () => {
  488. const { error, code, msg } = await mainApi.removeFile({
  489. id: file.id,
  490. taskId: taskInfo.value.id,
  491. })
  492. if (!error && code === 200) {
  493. resolve(true)
  494. } else {
  495. window.$message.error(msg ?? '删除失败')
  496. resolve(false)
  497. }
  498. })
  499. }
  500. </script>
  501. <style lang="scss" scoped>
  502. .hc-task-form {
  503. }
  504. </style>