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 type="list" :src="baseForm.fileList" :h-props="uploadFormProps" is-del @upload="attachmentUpload" @change="attachmentUploadChange" @del="attachmentUploadDel" />
  177. </el-form-item>
  178. </el-form>
  179. </hc-card-item>
  180. <!-- 变更申请清单 -->
  181. <ChangeRequest v-model="isChangeShow" :info="changeNodeInfo" @finish="changeNodeFinish" />
  182. <!-- 文件上传组件 -->
  183. <hc-upload-file ref="uploadFileRef" :options="uploadFileOptions" @success="uploadFileSuccess" />
  184. </div>
  185. </template>
  186. <script setup>
  187. import { nextTick, onMounted, ref, watch } from 'vue'
  188. import { useAppStore } from '~src/store'
  189. import ChangeRequest from './changeRequest.vue'
  190. import { delMessage, getDictionaryData, isNumberReg } from '~uti/tools'
  191. import { arrIndex, arrToKey, getArrValue, getObjVal, getObjValue, isArray, isNullES } from 'js-fast-way'
  192. import { getHeader } from 'hc-vue3-ui'
  193. import mainApi from '~api/tasks/hc-data'
  194. const props = defineProps({
  195. isEdit: {
  196. type: Boolean,
  197. default: true,
  198. },
  199. info: {
  200. type: Object,
  201. default: () => ({}),
  202. },
  203. table: {
  204. type: Object,
  205. default: () => ({}),
  206. },
  207. })
  208. const useAppState = useAppStore()
  209. const projectId = ref(useAppState.getProjectId || '')
  210. const contractId = ref(useAppState.getContractId || '')
  211. //监听可否编辑
  212. const isEdits = ref(props.isEdit)
  213. watch(() => props.isEdit, (val) => {
  214. isEdits.value = val
  215. }, { immediate: true, deep: true })
  216. //监听数据
  217. watch(() => [
  218. props.table,
  219. props.info,
  220. ], ([table, row]) => {
  221. setTaskInfo(table, row)
  222. }, { deep: true })
  223. //渲染完成
  224. onMounted(() => {
  225. setTaskInfo(props.table, props.info)
  226. })
  227. //设置任务信息
  228. const taskInfo = ref({})
  229. const tableInfo = ref({})
  230. const setTaskInfo = (table, row) => {
  231. tableInfo.value = table
  232. taskInfo.value = row
  233. if (getObjVal(table) && getObjVal(row)) {
  234. getMeterChangeClassify()
  235. getMeterChangeType()
  236. getDataDetail()
  237. }
  238. }
  239. //计量变更归类
  240. const classifyData = ref([])
  241. const getMeterChangeClassify = async () => {
  242. classifyData.value = await getDictionaryData('meter_change_classify')
  243. }
  244. //计量变更类型
  245. const typeData = ref([])
  246. const getMeterChangeType = async () => {
  247. typeData.value = await getDictionaryData('meter_change_type')
  248. }
  249. //获取任务数据信息详情
  250. const isLoading = ref(false)
  251. const getDataDetail = async () => {
  252. const id = taskInfo.value.id
  253. const dataId = tableInfo.value.id
  254. const { data } = await mainApi.getDataDetail({ id, dataId })
  255. //转换数据
  256. const { changeTokenFormVO, attachmentFormTask } = getObjValue(data)
  257. const res = getObjValue(changeTokenFormVO)
  258. baseForm.value = res //表单信息
  259. baseForm.value.fileList = getArrValue(attachmentFormTask) //附件列表
  260. const nodeList = getArrValue(res.nodeList)
  261. tableData.value = nodeList //部位列表
  262. if (nodeList.length > 0) {
  263. rowChangeNodeClick({ row: nodeList[0] })
  264. tableRef1.value?.tableRef?.setCurrentRow(nodeList[0])
  265. changeNodeItem.value = nodeList[0]
  266. tableIndex.value = 0
  267. }
  268. }
  269. //基础表单
  270. const baseFormRef = ref(null)
  271. const baseForm = ref({ fileList: [], pictureUrl: '' })
  272. const baseFormRules = {}
  273. //基础表单的输入框获得焦点
  274. const currentBaseForm = ref('')
  275. const currentInputFocus = (key) => {
  276. currentBaseForm.value = baseForm.value[key]
  277. }
  278. //基础表单的输入框失去焦点
  279. const currentInputBlur = async (key) => {
  280. if (currentBaseForm.value === baseForm.value[key]) {
  281. return false
  282. }
  283. //处理数据
  284. let form = {
  285. id: baseForm.value.id,
  286. taskId: taskInfo.value.id,
  287. }
  288. form[key] = baseForm.value[key]
  289. const { error, msg, code } = await mainApi.changeTokenFromUpdate(form)
  290. if (!error && code === 200) {
  291. window.$message.success('更新成功')
  292. } else {
  293. window.$message.error(msg ?? '更新失败')
  294. }
  295. }
  296. //清单表格
  297. const tableRef1 = ref(null)
  298. const tableColumn = ref([
  299. { key: 'nodeName', name: '工程名称' },
  300. { key: 'nodeUrl', name: '节点路径' },
  301. { key: 'contractPicture', name: '合同图号' },
  302. { key: 'changeMoney', name: '变更后金额(元)' },
  303. { key: 'isSupplementName', name: '是否增补' },
  304. { key: 'action', name: '操作', width: 80, align: 'center' },
  305. ])
  306. const tableData = ref([])
  307. //合同图号的输入框获得焦点
  308. const currentPicture = ref('')
  309. const meterInputFocus = (row) => {
  310. currentPicture.value = row.contractPicture
  311. }
  312. //合同图号的输入框失去焦点
  313. const meterInputBlur = async (row) => {
  314. if (currentPicture.value === row.contractPicture) {
  315. return false
  316. }
  317. //处理数据
  318. const { error, msg, code } = await mainApi.changeTokenMeterUpdate({
  319. primaryKeyId: row.primaryKeyId,
  320. taskId: taskInfo.value.id,
  321. contractPicture: row.contractPicture
  322. })
  323. if (!error && code === 200) {
  324. window.$message.success('更新成功')
  325. } else {
  326. window.$message.error(msg ?? '更新失败')
  327. }
  328. }
  329. //删除变更申请部位
  330. const delChangeNode = (row) => {
  331. delMessage(async () => {
  332. const { code, msg } = await mainApi.remove({
  333. projectId: projectId.value,
  334. contractId: contractId.value,
  335. dataId: tableInfo.value.id,
  336. taskId: taskInfo.value.id,
  337. primaryKeyId: row.primaryKeyId,
  338. type: 1
  339. })
  340. if (code === 200) {
  341. window.$message.success('删除成功')
  342. getDataDetail()
  343. } else {
  344. window.$message.error(msg ?? '删除失败')
  345. }
  346. })
  347. }
  348. //变更申请部位 行被点击
  349. const changeNodeItem = ref({})
  350. const tableIndex = ref(-1)
  351. const rowChangeNodeClick = ({ row }) => {
  352. const index = arrIndex(tableData.value, 'id', row.id)
  353. if (!isArray(row.formList)) {
  354. tableData.value[index].formList = []
  355. }
  356. tableIndex.value = index
  357. changeNodeItem.value = row
  358. }
  359. //删除变更申请清单
  360. const tableFormListDel = (row) => {
  361. delMessage(async () => {
  362. const { code, msg } = await mainApi.remove({
  363. projectId: projectId.value,
  364. contractId: contractId.value,
  365. dataId: tableInfo.value.id,
  366. taskId: taskInfo.value.id,
  367. primaryKeyId: row.primaryKeyId,
  368. type: 1
  369. })
  370. if (code === 200) {
  371. window.$message.success('删除成功')
  372. getDataDetail()
  373. } else {
  374. window.$message.error(msg ?? '删除失败')
  375. }
  376. })
  377. }
  378. //变更清单的添加弹窗
  379. const isChangeShow = ref(false)
  380. const changeNodeInfo = ref({})
  381. const changeShowClick = () => {
  382. const {id, primaryKeyId} = changeNodeItem.value
  383. if (isNullES(id)) {
  384. window.$message.warning('请先选择变更申请部位')
  385. return false
  386. }
  387. //处理数据
  388. const ids = arrToKey(tableData.value[tableIndex.value].formList, 'id')
  389. changeNodeInfo.value = {
  390. ids: ids,
  391. treeId: id ?? '',
  392. primaryKeyIdMeter: primaryKeyId ?? '',
  393. dataId: tableInfo.value.id ?? '',
  394. taskId: taskInfo.value.id ?? '',
  395. }
  396. nextTick(() => {
  397. isChangeShow.value = true
  398. })
  399. }
  400. //确认选择完成
  401. const changeNodeFinish = () => {
  402. getDataDetail()
  403. }
  404. //变更增减的输入框获得焦点
  405. const currentChangeTotal = ref('')
  406. const totalInputFocus = (row) => {
  407. currentChangeTotal.value = row.currentChangeTotal
  408. }
  409. //变更增减的输入框失去焦点
  410. const totalInputBlur = async (row) => {
  411. //如果为空
  412. let val = row.currentChangeTotal
  413. const isMeter = isNumberReg(val)
  414. if (isNullES(val) || !isMeter) {
  415. val = 0
  416. }
  417. if (currentChangeTotal.value === val) {
  418. return false
  419. }
  420. //处理数据
  421. const { error, msg, code } = await mainApi.changeTokenInventoryUpdate({
  422. contractId: contractId.value,
  423. primaryKeyIdInventory: row.primaryKeyId ?? '',
  424. primaryKeyIdMeter: changeNodeItem.value?.primaryKeyId ?? '',
  425. taskId: taskInfo.value.id ?? '',
  426. dataId: tableInfo.value.id ?? '',
  427. changTotal: val
  428. })
  429. if (!error && code === 200) {
  430. window.$message.success('更新成功')
  431. } else {
  432. window.$message.error(msg ?? '更新失败')
  433. }
  434. }
  435. //文件上传
  436. const uploadFileRef = ref(null)
  437. const uploadFileOptions = ref({
  438. headers: getHeader(),
  439. multiple: false,
  440. })
  441. const uploadFormProps = {
  442. url: 'fileUrl',
  443. name: 'fileName',
  444. }
  445. const attachmentUpload = () => {
  446. if (isEdits.value || tableInfo.status !== 2) {
  447. uploadFileRef.value?.selectFile()
  448. } else {
  449. window.$message.error('当前状态不可上传')
  450. }
  451. }
  452. const attachmentUploadChange = (a, b, fileList) => {
  453. baseForm.value.fileList = getArrValue(fileList)
  454. }
  455. // 文件上传成功的回调
  456. const uploadFileSuccess = async ({ resData }) => {
  457. baseForm.value.fileList.push({
  458. contractId: contractId.value,
  459. fileName: resData.originalName ?? '',
  460. filePdfUrl: resData.pdfUrl ?? '',
  461. fileUrl: resData.link ?? '',
  462. taskId: taskInfo.value.id,
  463. })
  464. uploadFileRef.value?.setModalShow(false)
  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. return
  485. }
  486. delMessage(async () => {
  487. const { error, code, msg } = await mainApi.removeFile({
  488. id: file.id,
  489. taskId: taskInfo.value.id
  490. })
  491. if (!error && code === 200) {
  492. resolve(true)
  493. } else {
  494. window.$message.error(msg ?? '删除失败')
  495. resolve(false)
  496. }
  497. })
  498. }
  499. </script>
  500. <style lang="scss" scoped>
  501. .hc-task-form {
  502. }
  503. </style>