row-data.vue 15 KB

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