row-data.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  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="top" :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="节点类型:" prop="nodeType">
  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 v-if="isTable" :span="6">
  95. <el-form-item label="是否允许自动计量:">
  96. <el-select v-model="formModel.isAutoMeter" block :disabled="formModel.isMeter === 1">
  97. <el-option label="是" :value="1" />
  98. <el-option label="否" :value="0" />
  99. </el-select>
  100. </el-form-item>
  101. </el-col>
  102. <el-col v-if="isTable" :span="6">
  103. <el-form-item label="是否为混凝土节点:">
  104. <el-select v-model="formModel.isConcreteNode" block :disabled="formModel.isMeter === 1">
  105. <el-option label="是" :value="1" />
  106. <el-option label="否" :value="0" />
  107. </el-select>
  108. <!-- <el-input
  109. v-model="formModel.isConcreteNode"
  110. /> -->
  111. </el-form-item>
  112. </el-col>
  113. <el-col v-if="isTable && formModel.isConcreteNode === 1" :span="6">
  114. <el-form-item label="7d强度支付比例:" prop="sevenRatio">
  115. <el-input v-model="formModel.sevenRatio" disabled @input="checkNegative">
  116. <template #append>%</template>
  117. </el-input>
  118. </el-form-item>
  119. </el-col>
  120. <el-col v-if="isTable && formModel.isConcreteNode === 1" :span="6">
  121. <el-form-item label="28d强度支付比例:" prop="twentyEightRatio">
  122. <el-input v-model="formModel.twentyEightRatio" disabled @input="checkNegative">
  123. <template #append>%</template>
  124. </el-input>
  125. </el-form-item>
  126. </el-col>
  127. <el-col v-if="isTable" :span="12">
  128. <el-form-item label="计算式配置:">
  129. <el-input
  130. v-model="formModel.calculateFormula" :autosize="{ minRows: 4, maxRows: 8 }"
  131. type="textarea"
  132. />
  133. </el-form-item>
  134. </el-col>
  135. <el-col :span="12">
  136. <el-form-item label="备注:">
  137. <el-input
  138. v-model="formModel.remarks" :autosize="{ minRows: 4, maxRows: 8 }"
  139. type="textarea"
  140. />
  141. </el-form-item>
  142. </el-col>
  143. </el-row>
  144. </el-form>
  145. <template v-if="isTable">
  146. <el-divider border-style="dashed" content-position="left">分解清单列表</el-divider>
  147. <hc-title>
  148. <span class="text-sm text-orange">温馨提示:累计分解量 > 合同变更后量,整行文字红色</span>
  149. <template #extra>
  150. <el-button hc-btn type="primary" @click="addCheckListShow = true">添加</el-button>
  151. </template>
  152. </hc-title>
  153. <div style="height: 400px;">
  154. <hc-table
  155. :column="tableColumn" :datas="tableData" is-new :index-style="{ width: 60 }"
  156. :row-style="tableRowStyle" :is-stripe="false" :is-current-row="false"
  157. >
  158. <template #buildPictureTotal="{ row }">
  159. <hc-table-input v-model="row.buildPictureTotal" :disabled="row.citeStatus === 1" @change="changeBuildPictureTotal(row)" />
  160. </template>
  161. <template #upPayRatio="{ row }">
  162. <hc-table-input v-model="row.upPayRatio" :disabled="row.citeStatus === 1 || formModel.isAutoMeter == 1" />
  163. </template>
  164. <template #action="{ row, index }">
  165. <el-link v-if="row.citeStatus === 1" type="info" @click="delNoRow(row)">删除</el-link>
  166. <el-link v-else type="danger" @click="delRow(row, index)">删除</el-link>
  167. </template>
  168. </hc-table>
  169. </div>
  170. <div class="mt-4 text-orange">
  171. 温馨提示:进行过变更的分解清单不允许修改编辑,分解清单编辑后,请重新下达零号变更台账
  172. </div>
  173. </template>
  174. </hc-body>
  175. </hc-new-dialog>
  176. <!-- 添加合同工程清单 -->
  177. <AddCheckList v-model="addCheckListShow" :ids="curTreeData.id" @finish="addCheckFinish" />
  178. </template>
  179. <script setup>
  180. import { nextTick, ref, watch } from 'vue'
  181. import { isNumberReg } from '~uti/tools'
  182. import AddCheckList from './addCheckList.vue'
  183. import unitApi from '~api/project/debit/contract/unit.js'
  184. import { getDictionaryBiz } from '~api/other'
  185. import { getDictionary } from '~api/other'
  186. import { formValidate, getArrValue, getObjValue, isArrIndex, isNullES } from 'js-fast-way'
  187. import { HcDelMsg } from 'hc-vue3-ui'
  188. import BigNumber from 'bignumber.js'
  189. const props = defineProps({
  190. ids: {
  191. type: [String, Number],
  192. default: '',
  193. },
  194. isTable: {
  195. type: Boolean,
  196. default: false,
  197. },
  198. curTreeData: {
  199. default: () => ({}),
  200. },
  201. })
  202. //事件
  203. const emit = defineEmits(['finish', 'close', 'getDetail'])
  204. //双向绑定
  205. // eslint-disable-next-line no-undef
  206. const isShow = defineModel('modelValue', {
  207. default: false,
  208. })
  209. const ids = ref(props.ids)
  210. const curTreeData = ref(props.curTreeData)
  211. const isTable = ref(props.isTable)
  212. const formModel = ref({})
  213. const tableData = ref([])
  214. //设置某一行的样式
  215. const isCanSave = ref(false)
  216. const tableRowStyle = ({ row }) => {
  217. let residueNum = new BigNumber(row.residueNum) //a
  218. let contract = new BigNumber('0') //b
  219. //a 大于 b = 1,a 等于 b = 0,a 小于 b = -1, a 或 b 的值异常时 = null
  220. const isCompared = residueNum.comparedTo(contract)
  221. if (isCompared === -1 || isCompared === null) {
  222. row.isCanSave = true
  223. return '--el-table-tr-bg-color: #fe0000; --el-table-row-hover-bg-color: #fe0000; color: white;'
  224. } else {
  225. row.isCanSave = false
  226. }
  227. }
  228. //获节点类型
  229. const nodeOptions = ref([])
  230. const getNodeType = async () => {
  231. const { data } = await getDictionaryBiz({
  232. code: 'meter_unit_type',
  233. })
  234. nodeOptions.value = getArrValue(data)
  235. nodeOptions.value.forEach((ele) => {
  236. ele.dictKey = Number(ele.dictKey)
  237. })
  238. }
  239. //获取桩号类型
  240. const stakeOptions = ref([])
  241. const getStakeype = async () => {
  242. const { data } = await getDictionary({
  243. code: 'meter_stake_type',
  244. })
  245. stakeOptions.value = getArrValue(data)
  246. stakeOptions.value.forEach((ele) => {
  247. ele.dictKey = Number(ele.dictKey)
  248. })
  249. }
  250. //监听
  251. watch(() => [
  252. props.ids,
  253. props.isTable,
  254. ], ([Ids, tabs]) => {
  255. ids.value = Ids
  256. isTable.value = tabs
  257. }, { immediate: true })
  258. //监听
  259. watch(() => props.curTreeData, (cur) => {
  260. curTreeData.value = cur
  261. formModel.value = cur
  262. formModel.value .isSupplementNmae = cur.isSupplement === 1 ? '是' : '否'
  263. // tableData.value = cur.decompositionList
  264. if (cur.id) {
  265. // getNodeType(cur.id)
  266. }
  267. }, {
  268. immediate: true,
  269. deep: true,
  270. })
  271. watch(() => props.ids, (id) => {
  272. tableData.value = getArrValue(props.curTreeData.decompositionList)
  273. }, {
  274. immediate: true,
  275. deep: true,
  276. })
  277. /*watch(tableData, (val) => {
  278. if (val) {
  279. //计算变更后金额
  280. let sum1 = tableData.value.reduce((accumulator, current) => {
  281. if (current.changeTotal && current.currentPrice) {
  282. return accumulator + (current.changeTotal * current.currentPrice)
  283. }
  284. return accumulator
  285. }, 0)
  286. formModel.value.changeMoney = sum1
  287. }
  288. }, { deep: true })*/
  289. watch(isShow, (val) => {
  290. if (val) {
  291. getNodeType(curTreeData.value.id)
  292. getStakeype()
  293. tableData.value = getArrValue(props.curTreeData.decompositionList)
  294. }
  295. })
  296. //弹窗表单
  297. const formRef = ref(null)
  298. // const formModel = ref({})
  299. const formRules = ref({
  300. nodeType:{
  301. required: true,
  302. trigger: 'change',
  303. message: '请选择节点类型',
  304. },
  305. })
  306. const checkNegative = ()=>{
  307. if (formModel.value.sevenRatio < 0) {
  308. formModel.value.sevenRatio = 0
  309. }
  310. if (formModel.value.twentyEightRatio < 0) {
  311. formModel.value.twentyEightRatio = 0
  312. }
  313. }
  314. //列表
  315. const addNodeLoading = ref(false)
  316. const tableColumn = ref([
  317. { key: 'formNumber', name: '清单编号' },
  318. { key: 'formName', name: '清单名称' },
  319. { key: 'currentPrice', name: '单价(元)' },
  320. { key: 'contractTotal', name: '合同数量' },
  321. { key: 'changeTotal', name: '合同变更后数量' },
  322. { key: 'poseNum', name: '已分解量' },
  323. { key: 'residueNum', name: '分解剩余量' },
  324. { key: 'buildPictureTotal', name: '施工图数量' },
  325. { key: 'changeBuildPictureTotal', name: '施工图变更后数量' },
  326. { key: 'upPayRatio', name: '资料未齐全的最高支付比例(%)' },
  327. { key: 'action', name: '操作', width: 80, align: 'center' },
  328. ])
  329. //计算数据
  330. const changeBuildPictureTotal = (row) => {
  331. if (row.citeStatus === 1) return
  332. //如果为空
  333. let buildPictureTotal = row.buildPictureTotal
  334. const isMeter = isNumberReg(buildPictureTotal)
  335. if (isNullES(buildPictureTotal) || !isMeter) {
  336. buildPictureTotal = 0
  337. }
  338. //计算相关数量和金额
  339. nextTick(() => {
  340. //更新值
  341. row.buildPictureTotal = buildPictureTotal
  342. row.changeBuildPictureTotal = buildPictureTotal
  343. //计算数量
  344. // poseNum 已分解量, otherPoseNum 其他节点分解量, buildPictureTotal 施工图数量
  345. // poseNum = otherPoseNum + buildPictureTotal
  346. row.poseNum = (BigNumber(row.otherPoseNum).plus(buildPictureTotal)).toString()
  347. // residueNum 分解剩余量, changeTotal 变更后合同数量
  348. // residueNum = changeTotal - poseNum
  349. row.residueNum = (BigNumber(row.changeTotal).minus(row.poseNum)).toString()
  350. console.log('residueNum:', row.residueNum)
  351. // buildPictureMoney 施工图金额
  352. // buildPictureMoney = buildPictureTotal * currentPrice(单价)
  353. row.buildPictureMoney = (BigNumber(buildPictureTotal).multipliedBy(row.currentPrice)).toString()
  354. // changeBuildPictureMoney 变更后施工图金额, changeBuildPictureTotal 变更后施工图数量
  355. // changeBuildPictureMoney = changeBuildPictureTotal * currentPrice(单价)
  356. row.changeBuildPictureMoney = (BigNumber(row.changeBuildPictureTotal).multipliedBy(row.currentPrice)).toString()
  357. //计算表单上的总金额
  358. let buildPictureMoney = 0, changeMoney = 0
  359. for (let i = 0; i < tableData.value.length; i++) {
  360. const item = tableData.value[i]
  361. buildPictureMoney = (BigNumber(buildPictureMoney).plus(item.buildPictureMoney)).toString()
  362. changeMoney = (BigNumber(changeMoney).plus(item.changeBuildPictureMoney)).toString()
  363. }
  364. formModel.value.buildPictureMoney = buildPictureMoney
  365. formModel.value.changeMoney = changeMoney
  366. })
  367. }
  368. const modalSave = async () => {
  369. const isValidate = await formValidate(formRef.value)
  370. if (!isValidate) return false
  371. isCanSave.value = isArrIndex(tableData.value, 'isCanSave', true)
  372. // if (isCanSave.value) {
  373. // window.$message.warning('累计分解量 > 合同变更后量,不允许修改')
  374. // return
  375. // }
  376. addNodeLoading.value = true
  377. formModel.value.decompositionList = tableData.value
  378. const { error, code, msg } = await unitApi.updateForm({
  379. ...formModel.value,
  380. })
  381. //判断状态
  382. addNodeLoading.value = false
  383. if (!error && code === 200) {
  384. window?.$message?.success(msg)
  385. emit('finish')
  386. }
  387. }
  388. const closeDialog = () => {
  389. emit('close')
  390. isCanSave.value = false
  391. }
  392. const addCheckListShow = ref(false)
  393. const addCheckFinish = async (val) => {
  394. addCheckListShow.value = false
  395. // emit('getDetail', { id: ids.value })
  396. await getTreeNodeDetail({ id: ids.value })
  397. for (let i = 0; i < nowTableData.value.length; i++) {
  398. for (let index = 0; index < tableData.value.length; index++) {
  399. const element = nowTableData.value[i]
  400. const element1 = tableData.value[index]
  401. if (element.id === element1.id) {
  402. nowTableData.value[i] = tableData.value[index]
  403. }
  404. }
  405. }
  406. tableData.value = nowTableData.value
  407. }
  408. const nowTableData = ref([])
  409. const getTreeNodeDetail = async ({ id }) => {
  410. const { error, code, data } = await unitApi.getNodeDetail({ id })
  411. if (!error && code === 200) {
  412. curTreeData.value = getObjValue(data)
  413. nowTableData.value = curTreeData.value['decompositionList']
  414. } else {
  415. nowTableData.value = []
  416. }
  417. }
  418. //删除
  419. const delRow = (row, index) => {
  420. HcDelMsg( async ( resolve) => {
  421. await removeCon(row.id, index)
  422. resolve() //关闭弹窗的回调
  423. })
  424. }
  425. //禁止删除
  426. const delNoRow = () => {
  427. window.$messageBox({
  428. title: '提示',
  429. message: '该清单已被引用,不允许删除',
  430. type: 'warning',
  431. })
  432. }
  433. const removeCon = async (id, index) => {
  434. const { error, code } = await unitApi.removeInfo({
  435. formIds: id,
  436. meterId: ids.value,
  437. })
  438. if (!error && code === 200) {
  439. window?.$message?.success('删除成功')
  440. tableData.value.splice(index, 1)
  441. }
  442. }
  443. </script>
  444. <style>
  445. .el-icon-percentage {
  446. margin-left: 5px; /* 调整图标与输入框的间距 */
  447. font-size: 20px; /* 调整图标大小 */
  448. color: #999; /* 调整图标颜色 */
  449. }
  450. </style>