row-data.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  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(tableData, (val) => {
  220. if (val) {
  221. //计算变更后金额
  222. let sum1 = tableData.value.reduce((accumulator, current) => {
  223. if (current.changeTotal && current.currentPrice) {
  224. return accumulator + (current.changeTotal * current.currentPrice)
  225. }
  226. return accumulator
  227. }, 0)
  228. formModel.value.changeMoney = sum1
  229. }
  230. }, { deep: true })*/
  231. watch(isShow, (val) => {
  232. if (val) {
  233. // getNodeType()
  234. getStakeype()
  235. }
  236. })
  237. //弹窗表单
  238. const formRef = ref(null)
  239. // const formModel = ref({})
  240. const formRules = ref({})
  241. //列表
  242. const addNodeLoading = ref(false)
  243. const tableColumn = ref([
  244. { key: 'formNumber', name: '清单编号' },
  245. { key: 'formName', name: '清单名称' },
  246. { key: 'currentPrice', name: '单价(元)' },
  247. { key: 'contractTotal', name: '合同数量' },
  248. { key: 'changeTotal', name: '合同变更后数量' },
  249. { key: 'poseNum', name: '已分解量' },
  250. { key: 'residueNum', name: '分解剩余量' },
  251. { key: 'buildPictureTotal', name: '施工图数量' },
  252. { key: 'changeBuildPictureTotal', name: '施工图变更后数量' },
  253. { key: 'action', name: '操作', width: 80, align: 'center' },
  254. ])
  255. //计算数据
  256. const changeBuildPictureTotal = (row) => {
  257. //如果为空
  258. let buildPictureTotal = row.buildPictureTotal
  259. const isMeter = isNumberReg(buildPictureTotal)
  260. if (isNullES(buildPictureTotal) || !isMeter) {
  261. buildPictureTotal = 0
  262. }
  263. //计算相关数量和金额
  264. nextTick(() => {
  265. //更新值
  266. row.buildPictureTotal = buildPictureTotal
  267. row.changeBuildPictureTotal = buildPictureTotal
  268. //计算数量
  269. // poseNum 已分解量, otherPoseNum 其他节点分解量, buildPictureTotal 施工图数量
  270. // poseNum = otherPoseNum + buildPictureTotal
  271. row.poseNum = (BigNumber(row.otherPoseNum).plus(buildPictureTotal)).toString()
  272. // residueNum 分解剩余量, changeTotal 变更后合同数量
  273. // residueNum = changeTotal - poseNum
  274. row.residueNum = (BigNumber(row.changeTotal).minus(row.poseNum)).toString()
  275. // buildPictureMoney 施工图金额
  276. // buildPictureMoney = buildPictureTotal * currentPrice(单价)
  277. row.buildPictureMoney = (BigNumber(buildPictureTotal).multipliedBy(row.currentPrice)).toString()
  278. // changeBuildPictureMoney 变更后施工图金额, changeBuildPictureTotal 变更后施工图数量
  279. // changeBuildPictureMoney = changeBuildPictureTotal * currentPrice(单价)
  280. row.changeBuildPictureMoney = (BigNumber(row.changeBuildPictureTotal).multipliedBy(row.currentPrice)).toString()
  281. //计算表单上的总金额
  282. let buildPictureMoney = 0, changeMoney = 0
  283. for (let i = 0; i < tableData.value.length; i++) {
  284. const item = tableData.value[i]
  285. buildPictureMoney = (BigNumber(buildPictureMoney).plus(item.buildPictureMoney)).toString()
  286. changeMoney = (BigNumber(changeMoney).plus(item.changeBuildPictureMoney)).toString()
  287. }
  288. formModel.value.buildPictureMoney = buildPictureMoney
  289. formModel.value.changeMoney = changeMoney
  290. })
  291. }
  292. const modalSave = async () => {
  293. isCanSave.value = isArrIndex(tableData.value, 'isCanSave', true)
  294. if (isCanSave.value) {
  295. window.$message.warning('累计分解量 > 合同变更后量,不允许修改')
  296. return
  297. }
  298. addNodeLoading.value = true
  299. const { error, code, msg } = await unitApi.updateForm({
  300. ...formModel.value,
  301. })
  302. //判断状态
  303. addNodeLoading.value = false
  304. if (!error && code === 200) {
  305. window?.$message?.success(msg)
  306. }
  307. emit('finish')
  308. }
  309. const closeDialog = () => {
  310. emit('close')
  311. isCanSave.value = false
  312. }
  313. const addCheckListShow = ref(false)
  314. const addCheckFinish = async (val) => {
  315. addCheckListShow.value = false
  316. // emit('getDetail', { id: ids.value })
  317. await getTreeNodeDetail({ id: ids.value })
  318. for (let i = 0; i < nowTableData.value.length; i++) {
  319. for (let index = 0; index < tableData.value.length; index++) {
  320. const element = nowTableData.value[i]
  321. const element1 = tableData.value[index]
  322. if (element.id === element1.id) {
  323. nowTableData.value[i] = tableData.value[index]
  324. }
  325. }
  326. }
  327. tableData.value = nowTableData.value
  328. }
  329. const nowTableData = ref([])
  330. const getTreeNodeDetail = async ({ id }) => {
  331. const { error, code, data } = await unitApi.getNodeDetail({ id })
  332. if (!error && code === 200) {
  333. curTreeData.value = getObjValue(data)
  334. nowTableData.value = curTreeData.value['decompositionList']
  335. } else {
  336. nowTableData.value = []
  337. }
  338. }
  339. //删除
  340. const delRow = async (row, index) => {
  341. delMessageV2(async (action, instance, done) => {
  342. if (action === 'confirm') {
  343. instance.confirmButtonLoading = true
  344. await removeCon(row.id, index)
  345. instance.confirmButtonLoading = false
  346. done()
  347. } else {
  348. done()
  349. }
  350. })
  351. }
  352. //禁止删除
  353. const delNoRow = () => {
  354. window.$messageBox({
  355. title: '提示',
  356. message: '该清单已被引用,不允许删除',
  357. type: 'warning',
  358. })
  359. }
  360. const removeCon = async (id, index) => {
  361. const { error, code } = await unitApi.removeInfo({
  362. formIds: id,
  363. meterId: ids.value,
  364. })
  365. if (!error && code === 200) {
  366. window?.$message?.success('删除成功')
  367. tableData.value.splice(index, 1)
  368. }
  369. }
  370. </script>