row-data.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. <template>
  2. <hc-new-dialog
  3. v-model="isShow" widths="90%" :is-table="isTable" :padding="false" title="合同计量单元修改"
  4. :loading="addNodeLoading" @save="modalSave" @close="closeDialog"
  5. >
  6. <hc-body scrollbar :contents="!isTable">
  7. <el-form ref="formRef" label-position="left" label-width="auto" :model="formModel" :rules="formRules">
  8. <el-row :gutter="20">
  9. <el-col :span="6">
  10. <el-form-item label="工程名称:">
  11. <el-input v-model="formModel.nodeName" />
  12. </el-form-item>
  13. </el-col>
  14. <el-col :span="6">
  15. <el-form-item label="工程编号:">
  16. <el-input v-model="formModel.nodeCode" />
  17. </el-form-item>
  18. </el-col>
  19. <el-col :span="6">
  20. <el-form-item label="节点类型:">
  21. <el-select v-model="formModel.nodeType" block>
  22. <el-option
  23. v-for="item in nodeOptions" :key="item.id" :label="item.dictValue"
  24. :value="item.dictKey"
  25. />
  26. </el-select>
  27. </el-form-item>
  28. </el-col>
  29. <el-col :span="6">
  30. <el-form-item label="工程类型:">
  31. <el-input v-model="formModel.engineeringTypeName" disabled />
  32. </el-form-item>
  33. </el-col>
  34. <el-col :span="6">
  35. <el-form-item label="桩号类型:">
  36. <el-select v-model="formModel.stakeType" block placeholder=" ">
  37. <el-option
  38. v-for="item in stakeOptions" :key="item.id" :label="item.dictValue"
  39. :value="item.dictKey"
  40. />
  41. </el-select>
  42. </el-form-item>
  43. </el-col>
  44. <el-col :span="6">
  45. <el-form-item label="起始桩号:">
  46. <el-input v-model="formModel.startStake" />
  47. </el-form-item>
  48. </el-col>
  49. <el-col :span="6">
  50. <el-form-item label="结束桩号:">
  51. <el-input v-model="formModel.endStake" />
  52. </el-form-item>
  53. </el-col>
  54. <el-col :span="6">
  55. <el-form-item label="是否增补:">
  56. <!-- <el-select v-model="formModel.isSupplement" disabled block placeholder=" ">
  57. <el-option label="是" :value="1" />
  58. <el-option label="否" :value="0" />
  59. </el-select> -->
  60. <el-input v-model="formModel.isSupplementNmae" disabled />
  61. </el-form-item>
  62. </el-col>
  63. <el-col :span="6">
  64. <el-form-item label="施工图金额:">
  65. <el-input v-model="formModel.buildPictureMoney" disabled class="w-100">
  66. <template #suffix>元</template>
  67. </el-input>
  68. </el-form-item>
  69. </el-col>
  70. <el-col :span="6">
  71. <el-form-item label="变更后金额:">
  72. <el-input v-model="formModel.changeMoney" disabled class="w-100">
  73. <template #suffix>元</template>
  74. </el-input>
  75. </el-form-item>
  76. </el-col>
  77. <el-col :span="6">
  78. <el-form-item label="合同图号:">
  79. <el-input v-model="formModel.contractPicture" />
  80. </el-form-item>
  81. </el-col>
  82. <el-col :span="6">
  83. <el-form-item label="变更合同图号:">
  84. <el-input v-model="formModel.changePicture" />
  85. </el-form-item>
  86. </el-col>
  87. <el-col v-if="isTable" :span="6">
  88. <el-form-item label="未关联质保资料中期最高支付比列(%):">
  89. <el-input
  90. v-model="formModel.upPayRatio"
  91. />
  92. </el-form-item>
  93. </el-col>
  94. <el-col :span="isTable ? 18 : 24">
  95. <el-form-item label="备注:">
  96. <el-input
  97. v-model="formModel.remarks" :autosize="{ minRows: 4, maxRows: 8 }"
  98. type="textarea"
  99. />
  100. </el-form-item>
  101. </el-col>
  102. </el-row>
  103. </el-form>
  104. <template v-if="isTable">
  105. <el-divider border-style="dashed" content-position="left">分解清单列表</el-divider>
  106. <hc-title>
  107. <span class="text-sm text-orange">温馨提示:累计分解量 > 合同变更后量,整行文字红色</span>
  108. <template #extra>
  109. <el-button hc-btn type="primary" @click="addCheckListShow = true">添加</el-button>
  110. </template>
  111. </hc-title>
  112. <div style="height: 400px;">
  113. <hc-table
  114. :column="tableColumn" :datas="tableData" is-new :index-style="{ width: 60 }"
  115. :row-style="tableRowStyle" :is-stripe="false"
  116. >
  117. <template #buildPictureTotal="{ row }">
  118. <hc-table-input v-model="row.buildPictureTotal" :disabled="row.citeStatus === 1" @change="changeBuildPictureTotal(row)" />
  119. </template>
  120. <template #upPayRatio="{ row }">
  121. <hc-table-input v-model="row.upPayRatio" :disabled="row.citeStatus === 1" />
  122. </template>
  123. <template #action="{ row, index }">
  124. <el-link v-if="row.citeStatus === 1" type="info" @click="delNoRow(row)">删除</el-link>
  125. <el-link v-else type="danger" @click="delRow(row, index)">删除</el-link>
  126. </template>
  127. </hc-table>
  128. </div>
  129. <div class="mt-4 text-orange">
  130. 温馨提示:进行过变更的分解清单不允许修改编辑,分解清单编辑后,请重新下达零号变更台账
  131. </div>
  132. </template>
  133. </hc-body>
  134. </hc-new-dialog>
  135. <!-- 添加合同工程清单 -->
  136. <AddCheckList v-model="addCheckListShow" :ids="curTreeData.id" @finish="addCheckFinish" />
  137. </template>
  138. <script setup>
  139. import { nextTick, ref, watch } from 'vue'
  140. import { isNumberReg } from '~uti/tools'
  141. import AddCheckList from './addCheckList.vue'
  142. import unitApi from '~api/project/debit/contract/unit.js'
  143. import { getDictionary } from '~api/other'
  144. import { getArrValue, getObjValue, isArrIndex, isNullES } from 'js-fast-way'
  145. import { delMessageV2 } from '~com/message/index.js'
  146. import BigNumber from 'bignumber.js'
  147. const props = defineProps({
  148. ids: {
  149. type: [String, Number],
  150. default: '',
  151. },
  152. isTable: {
  153. type: Boolean,
  154. default: false,
  155. },
  156. curTreeData: {
  157. default: () => ({}),
  158. },
  159. })
  160. //事件
  161. const emit = defineEmits(['finish', 'close', 'getDetail'])
  162. //双向绑定
  163. // eslint-disable-next-line no-undef
  164. const isShow = defineModel('modelValue', {
  165. default: false,
  166. })
  167. const ids = ref(props.ids)
  168. const curTreeData = ref(props.curTreeData)
  169. const isTable = ref(props.isTable)
  170. const formModel = ref({})
  171. const tableData = ref([])
  172. //设置某一行的样式
  173. const isCanSave = ref(false)
  174. const tableRowStyle = ({ row }) => {
  175. let residueNum = new BigNumber(row.residueNum) //a
  176. let contract = new BigNumber('0') //b
  177. //a 大于 b = 1,a 等于 b = 0,a 小于 b = -1, a 或 b 的值异常时 = null
  178. const isCompared = residueNum.comparedTo(contract)
  179. if (isCompared === -1 || isCompared === null) {
  180. row.isCanSave = true
  181. return '--el-table-tr-bg-color: #fe0000; --el-table-row-hover-bg-color: #fe0000; color: white;'
  182. } else {
  183. row.isCanSave = false
  184. }
  185. }
  186. //获节点类型
  187. const nodeOptions = ref([])
  188. const getNodeType = async (id) => {
  189. const { data } = await unitApi.getNodeTypeListUpdate({
  190. id,
  191. })
  192. nodeOptions.value = getArrValue(data)
  193. nodeOptions.value.forEach((ele) => {
  194. ele.dictKey = Number(ele.dictKey)
  195. })
  196. }
  197. //获取桩号类型
  198. const stakeOptions = ref([])
  199. const getStakeype = async () => {
  200. const { data } = await getDictionary({
  201. code: 'meter_stake_type',
  202. })
  203. stakeOptions.value = getArrValue(data)
  204. stakeOptions.value.forEach((ele) => {
  205. ele.dictKey = Number(ele.dictKey)
  206. })
  207. }
  208. //监听
  209. watch(() => [
  210. props.ids,
  211. props.isTable,
  212. ], ([Ids, tabs]) => {
  213. ids.value = Ids
  214. isTable.value = tabs
  215. }, { immediate: true })
  216. //监听
  217. watch(() => props.curTreeData, (cur) => {
  218. curTreeData.value = cur
  219. formModel.value = cur
  220. formModel.value .isSupplementNmae = cur.isSupplement === 1 ? '是' : '否'
  221. // tableData.value = cur.decompositionList
  222. if (cur.id) {
  223. getNodeType(cur.id)
  224. }
  225. }, {
  226. immediate: true,
  227. deep: true,
  228. })
  229. watch(() => props.ids, (id) => {
  230. tableData.value = getArrValue(props.curTreeData.decompositionList)
  231. }, {
  232. immediate: true,
  233. deep: true,
  234. })
  235. /*watch(tableData, (val) => {
  236. if (val) {
  237. //计算变更后金额
  238. let sum1 = tableData.value.reduce((accumulator, current) => {
  239. if (current.changeTotal && current.currentPrice) {
  240. return accumulator + (current.changeTotal * current.currentPrice)
  241. }
  242. return accumulator
  243. }, 0)
  244. formModel.value.changeMoney = sum1
  245. }
  246. }, { deep: true })*/
  247. watch(isShow, (val) => {
  248. if (val) {
  249. // getNodeType()
  250. getStakeype()
  251. tableData.value = getArrValue(props.curTreeData.decompositionList)
  252. }
  253. })
  254. //弹窗表单
  255. const formRef = ref(null)
  256. // const formModel = ref({})
  257. const formRules = ref({})
  258. //列表
  259. const addNodeLoading = ref(false)
  260. const tableColumn = ref([
  261. { key: 'formNumber', name: '清单编号' },
  262. { key: 'formName', name: '清单名称' },
  263. { key: 'currentPrice', name: '单价(元)' },
  264. { key: 'contractTotal', name: '合同数量' },
  265. { key: 'changeTotal', name: '合同变更后数量' },
  266. { key: 'poseNum', name: '已分解量' },
  267. { key: 'residueNum', name: '分解剩余量' },
  268. { key: 'buildPictureTotal', name: '施工图数量' },
  269. { key: 'changeBuildPictureTotal', name: '施工图变更后数量' },
  270. { key: 'upPayRatio', name: '资料未齐全的最高支付比例(%)' },
  271. { key: 'action', name: '操作', width: 80, align: 'center' },
  272. ])
  273. //计算数据
  274. const changeBuildPictureTotal = (row) => {
  275. //如果为空
  276. let buildPictureTotal = row.buildPictureTotal
  277. const isMeter = isNumberReg(buildPictureTotal)
  278. if (isNullES(buildPictureTotal) || !isMeter) {
  279. buildPictureTotal = 0
  280. }
  281. //计算相关数量和金额
  282. nextTick(() => {
  283. //更新值
  284. row.buildPictureTotal = buildPictureTotal
  285. row.changeBuildPictureTotal = buildPictureTotal
  286. //计算数量
  287. // poseNum 已分解量, otherPoseNum 其他节点分解量, buildPictureTotal 施工图数量
  288. // poseNum = otherPoseNum + buildPictureTotal
  289. row.poseNum = (BigNumber(row.otherPoseNum).plus(buildPictureTotal)).toString()
  290. // residueNum 分解剩余量, changeTotal 变更后合同数量
  291. // residueNum = changeTotal - poseNum
  292. row.residueNum = (BigNumber(row.changeTotal).minus(row.poseNum)).toString()
  293. // buildPictureMoney 施工图金额
  294. // buildPictureMoney = buildPictureTotal * currentPrice(单价)
  295. row.buildPictureMoney = (BigNumber(buildPictureTotal).multipliedBy(row.currentPrice)).toString()
  296. // changeBuildPictureMoney 变更后施工图金额, changeBuildPictureTotal 变更后施工图数量
  297. // changeBuildPictureMoney = changeBuildPictureTotal * currentPrice(单价)
  298. row.changeBuildPictureMoney = (BigNumber(row.changeBuildPictureTotal).multipliedBy(row.currentPrice)).toString()
  299. //计算表单上的总金额
  300. let buildPictureMoney = 0, changeMoney = 0
  301. for (let i = 0; i < tableData.value.length; i++) {
  302. const item = tableData.value[i]
  303. buildPictureMoney = (BigNumber(buildPictureMoney).plus(item.buildPictureMoney)).toString()
  304. changeMoney = (BigNumber(changeMoney).plus(item.changeBuildPictureMoney)).toString()
  305. }
  306. formModel.value.buildPictureMoney = buildPictureMoney
  307. formModel.value.changeMoney = changeMoney
  308. })
  309. }
  310. const modalSave = async () => {
  311. isCanSave.value = isArrIndex(tableData.value, 'isCanSave', true)
  312. // if (isCanSave.value) {
  313. // window.$message.warning('累计分解量 > 合同变更后量,不允许修改')
  314. // return
  315. // }
  316. addNodeLoading.value = true
  317. formModel.value.decompositionList = tableData.value
  318. const { error, code, msg } = await unitApi.updateForm({
  319. ...formModel.value,
  320. })
  321. //判断状态
  322. addNodeLoading.value = false
  323. if (!error && code === 200) {
  324. window?.$message?.success(msg)
  325. }
  326. emit('finish')
  327. }
  328. const closeDialog = () => {
  329. emit('close')
  330. isCanSave.value = false
  331. }
  332. const addCheckListShow = ref(false)
  333. const addCheckFinish = async (val) => {
  334. addCheckListShow.value = false
  335. // emit('getDetail', { id: ids.value })
  336. await getTreeNodeDetail({ id: ids.value })
  337. for (let i = 0; i < nowTableData.value.length; i++) {
  338. for (let index = 0; index < tableData.value.length; index++) {
  339. const element = nowTableData.value[i]
  340. const element1 = tableData.value[index]
  341. if (element.id === element1.id) {
  342. nowTableData.value[i] = tableData.value[index]
  343. }
  344. }
  345. }
  346. tableData.value = nowTableData.value
  347. }
  348. const nowTableData = ref([])
  349. const getTreeNodeDetail = async ({ id }) => {
  350. const { error, code, data } = await unitApi.getNodeDetail({ id })
  351. if (!error && code === 200) {
  352. curTreeData.value = getObjValue(data)
  353. nowTableData.value = curTreeData.value['decompositionList']
  354. } else {
  355. nowTableData.value = []
  356. }
  357. }
  358. //删除
  359. const delRow = async (row, index) => {
  360. delMessageV2(async (action, instance, done) => {
  361. if (action === 'confirm') {
  362. instance.confirmButtonLoading = true
  363. await removeCon(row.id, index)
  364. instance.confirmButtonLoading = false
  365. done()
  366. } else {
  367. done()
  368. }
  369. })
  370. }
  371. //禁止删除
  372. const delNoRow = () => {
  373. window.$messageBox({
  374. title: '提示',
  375. message: '该清单已被引用,不允许删除',
  376. type: 'warning',
  377. })
  378. }
  379. const removeCon = async (id, index) => {
  380. const { error, code } = await unitApi.removeInfo({
  381. formIds: id,
  382. meterId: ids.value,
  383. })
  384. if (!error && code === 200) {
  385. window?.$message?.success('删除成功')
  386. tableData.value.splice(index, 1)
  387. }
  388. }
  389. </script>