tree-form.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. <template>
  2. <hc-new-dialog v-model="isShow" is-table widths="95%" :title="title" :loading="addNodeLoading" @save="modalSave" @close="closeAddModal">
  3. <div class="relative h-full flex">
  4. <div :id="`hc_tree_card_${uuid}`">
  5. <hc-new-card scrollbar>
  6. <template #header>
  7. <div class="text-sm text-orange">↓ 选择部位【点击新增】</div>
  8. </template>
  9. <div v-if="title === '合同计量单元新增'" class="tree-list">
  10. <div v-for="(item, index) in treeDataList" :key="index" class="item" @click="treeListClick(item)">
  11. <HcIcon name="box-3" fill />
  12. <span class="ml-1">{{ item.nodeName }}</span>
  13. </div>
  14. </div>
  15. <div v-else>
  16. <HcDataTree
  17. ref="leftTree"
  18. tree-key="id"
  19. show-checkbox
  20. :datas="leftTreeData"
  21. :h-props="lefttreeProps"
  22. :default-expand-all="defaultExpandAll"
  23. :check-strictly="checkStrictly"
  24. :default-checked-keys="defaultCheckedKeys"
  25. @node-tap="nodeElTreeClick"
  26. @check="treeNodeCheck"
  27. />
  28. </div>
  29. </hc-new-card>
  30. </div>
  31. <div :id="`hc_table_card_${uuid}`" class="flex-1">
  32. <hc-new-card scrollbar title="合同计量单元">
  33. <hc-table :is-index="false" :column="tableColumn" :datas="tableData" is-new :index-style="{ width: 60 }">
  34. <template #nodeName="{ row }">
  35. <hc-table-input v-model="row.nodeName" />
  36. </template>
  37. <template #startStake="{ row }">
  38. <hc-table-input v-model="row.startStake" />
  39. </template>
  40. <template #endStake="{ row }">
  41. <hc-table-input v-model="row.endStake" />
  42. </template>
  43. <template #contractPicture="{ row }">
  44. <hc-table-input v-model="row.contractPicture" />
  45. </template>
  46. <template #isAddChildNode="{ row, index }">
  47. <el-radio-group v-model="row.isAddChildNode" @change="changeIsAdd($event, row, index)">
  48. <el-radio :value="1">是</el-radio>
  49. <el-radio :value="0" class="ml-2">否</el-radio>
  50. </el-radio-group>
  51. </template>
  52. <template #action="{ index }">
  53. <el-link type="danger" @click="delRowClick(index)">删除</el-link>
  54. </template>
  55. </hc-table>
  56. </hc-new-card>
  57. </div>
  58. </div>
  59. </hc-new-dialog>
  60. </template>
  61. <script setup>
  62. import { nextTick, ref, watch } from 'vue'
  63. import { arrToId, getArrValue, getRandom, isArrItem } from 'js-fast-way'
  64. import unitApi from '~api/project/debit/contract/unit.js'
  65. import { useAppStore } from '~src/store'
  66. const props = defineProps({
  67. ids: {
  68. type: [String, Number],
  69. default: '',
  70. },
  71. menuType:{
  72. type: [String, Number],
  73. default: '',
  74. },
  75. templateId:{
  76. type: [String, Number],
  77. default: '',
  78. },
  79. title:{
  80. type: [String],
  81. default: '合同计量单元新增',
  82. },
  83. parentData:{
  84. type:Object,
  85. default: () => ({}),
  86. },
  87. isTable: {
  88. type: Boolean,
  89. default: false,
  90. },
  91. })
  92. //事件
  93. const emit = defineEmits(['finish', 'close'])
  94. const useAppState = useAppStore()
  95. const projectId = ref(useAppState.getProjectId || '')
  96. const contractId = ref(useAppState.getContractId || '')
  97. const menuType = ref(props.menuType)
  98. const ids = ref(props.ids)
  99. const templateId = ref(props.templateId)
  100. const title = ref(props.title)
  101. const parentData = ref(props.parentData)
  102. const isTable = ref(props.isTable)
  103. const uuid = getRandom(4)
  104. //双向绑定
  105. // eslint-disable-next-line no-undef
  106. const isShow = defineModel('modelValue', {
  107. default: false,
  108. })
  109. const getTreeDataList = async ()=>{
  110. const { error, code, data } = await unitApi.getLeftList({
  111. id:ids.value,
  112. })
  113. if (!error && code === 200) {
  114. treeDataList.value = getArrValue(data)
  115. } else {
  116. treeDataList.value = []
  117. }
  118. }
  119. //表格数据
  120. const tableColumn = ref([
  121. { key: 'nodeName', name: '名称' },
  122. { key: 'startStake', name: '开始桩号' },
  123. { key: 'endStake', name: '结束桩号' },
  124. { key: 'contractPicture', name: '合同图号' },
  125. { key: 'isAddChildNode', name: '是否划分子节点', width: 120, align: 'center' },
  126. { key: 'action', name: '操作', width: 80, align: 'center' },
  127. ])
  128. const leftTreeData = ref([])
  129. const treeLoading = ref(false)
  130. const getLeftTreeData = async (id) => {
  131. treeLoading.value = true
  132. const { error, code, data } = await unitApi.getCurrentNodeTree({
  133. id,
  134. contractId:contractId.value,
  135. })
  136. treeLoading.value = false
  137. if (!error && code === 200) {
  138. leftTreeData.value = getArrValue(data)
  139. } else {
  140. leftTreeData.value = []
  141. }
  142. }
  143. //监听
  144. watch(() => [
  145. props.ids,
  146. props.menuType,
  147. props.templateId,
  148. props.title,
  149. props.parentData,
  150. props.isTable,
  151. ], ([Ids, Type, Tem, til, parent, tab]) => {
  152. ids.value = Ids
  153. menuType.value = Type
  154. templateId.value = Tem
  155. title.value = til
  156. parentData.value = parent
  157. isTable.value = tab
  158. if (title.value === '合同计量单元复制') {
  159. tableColumn.value = [
  160. { key: 'nodeName', name: '名称' },
  161. { key: 'startStake', name: '开始桩号' },
  162. { key: 'endStake', name: '结束桩号' },
  163. { key: 'contractPicture', name: '合同图号' },
  164. { key: 'isAddChildNode', name: '是否划分子节点', width: 120, align: 'center' },
  165. ]
  166. } else {
  167. tableColumn.value = [
  168. { key: 'nodeName', name: '名称' },
  169. { key: 'startStake', name: '开始桩号' },
  170. { key: 'endStake', name: '结束桩号' },
  171. { key: 'contractPicture', name: '合同图号' },
  172. { key: 'isAddChildNode', name: '是否划分子节点', width: 120, align: 'center' },
  173. { key: 'action', name: '操作', width: 80, align: 'center' },
  174. ]
  175. }
  176. getTreeDataList()
  177. if (isShow.value) {
  178. getLeftTreeData(ids.value)
  179. checkStrictly.value = false
  180. }
  181. }, { immediate: true })
  182. //监听
  183. watch(isShow, (val) => {
  184. if (val) {
  185. setSplitRef()
  186. }
  187. })
  188. //初始化设置拖动分割线
  189. const setSplitRef = () => {
  190. //配置参考: https://split.js.org/#/?direction=vertical&snapOffset=0
  191. nextTick(() => {
  192. window.$split(['#hc_tree_card_' + uuid, '#hc_table_card_' + uuid], {
  193. sizes: [20, 80],
  194. snapOffset: 0,
  195. minSize: [50, 500],
  196. })
  197. })
  198. }
  199. const treeDataList = ref([])
  200. const treeListClick = (item) => {
  201. tableData.value.push({
  202. nodeName: item.nodeName,
  203. startStake: '',
  204. endStake: '',
  205. contractPicture: '',
  206. isAddChildNode: 1,
  207. leftNodeId:item.id,
  208. })
  209. }
  210. const tableData = ref([])
  211. //删除
  212. const delRowClick = (index) => {
  213. tableData.value.splice(index, 1)
  214. }
  215. const addNodeLoading = ref(false)
  216. const modalSave = async () => {
  217. if (tableData.value.length === 0) {
  218. window.$message.warning('请选择部位点击新增')
  219. return
  220. }
  221. if (title.value === '合同计量单元新增') {
  222. const { error, code, msg } = await unitApi.addNode({
  223. contractId:contractId.value,
  224. projectId:projectId.value,
  225. contractNodeId:ids.value,
  226. requestType:menuType.value === 'add' ? 1 : 2, //请求类型 1=节点新增 2=增补单元新增
  227. templateId: templateId.value,
  228. dataList:tableData.value,
  229. })
  230. //判断状态
  231. addNodeLoading.value = false
  232. if (!error && code === 200) {
  233. window?.$message?.success(msg)
  234. tableData.value = []
  235. } else {
  236. window.$message.error(msg)
  237. }
  238. emit('finish')
  239. } else {
  240. console.log(tableData.value, 'tableData.value')
  241. const { error, code, msg } = await unitApi.copyNode({
  242. contractId:contractId.value,
  243. id:ids.value,
  244. vo2s:tableData.value,
  245. })
  246. //判断状态
  247. addNodeLoading.value = false
  248. if (!error && code === 200) {
  249. window?.$message?.success(msg)
  250. tableData.value = []
  251. } else {
  252. window.$message.error(msg)
  253. }
  254. emit('finish')
  255. }
  256. }
  257. const closeAddModal = ()=>{
  258. tableData.value = []
  259. }
  260. const lefttreeProps = {
  261. label: 'nodeName',
  262. children: 'children',
  263. isLeaf: 'notExsitChild',
  264. }
  265. const nodeElTreeClick = (data)=>{
  266. }
  267. const treeNodeCheck = (_, { checkedNodes, checkedKeys }) => {
  268. console.log(checkedNodes, 'checkedNodes')
  269. tableData.value = []
  270. checkedNodes.forEach((item)=>{
  271. tableData.value.push(
  272. { nodeName: item.nodeName,
  273. startStake: '',
  274. endStake: '',
  275. contractPicture: '',
  276. isAddChildNode: item.isAddChildNode,
  277. id:item.id,
  278. parentId:item.parentId,
  279. isParent:item?.children ? true : false,
  280. },
  281. )
  282. })
  283. if (checkedNodes.length > 0 ) {
  284. console.log(parentData.value, 'parentData')
  285. tableData.value.unshift(
  286. { nodeName: parentData.value.nodeName,
  287. startStake: '',
  288. endStake: '',
  289. contractPicture: '',
  290. isAddChildNode: parentData.value.isAddChildNode || 1,
  291. id:parentData.value.id,
  292. parentId:parentData.value.parentId,
  293. isParent:isTable.value ? false : true,
  294. },
  295. )
  296. let alarr = tableData.value
  297. // 使用reduce方法进行去重
  298. const uniqueArray = alarr.reduce((acc, current) => {
  299. // 检查当前对象的某个字段是否已存在于累积数组中
  300. const x = acc.find(item => item.id === current.id)
  301. // 如果不存在,则将其添加到累积数组中
  302. if (!x) {
  303. return acc.concat([current])
  304. } else {
  305. return acc
  306. }
  307. }, [])
  308. tableData.value = uniqueArray
  309. }
  310. }
  311. const checkStrictly = ref(false)
  312. const defaultCheckedKeys = ref([])
  313. const defaultExpandAll = ref(true)
  314. const changeIsAdd = (val, row, index)=>{
  315. const { isParent } = row
  316. if (isParent && val === 0) {
  317. let rowTreeData = leftTree.value.treeRef.getNode(row.id)
  318. let delKeys = arrToId(rowTreeData.data.children).split(',')
  319. nextTick(()=>{
  320. delKeys.forEach((ele)=>{
  321. leftTree.value.treeRef.setChecked(ele, false, true)
  322. let checkKeys = leftTree.value.treeRef.getCheckedKeys()
  323. let arr = []
  324. tableData.value.forEach((ele)=>{
  325. checkKeys.forEach((ele1)=>{
  326. if (ele.id === ele1) {
  327. arr.push(ele)
  328. }
  329. })
  330. })
  331. tableData.value = arr
  332. if (checkKeys.length > 0) {
  333. tableData.value.unshift(
  334. { nodeName: parentData.value.nodeName,
  335. startStake: '',
  336. endStake: '',
  337. contractPicture: '',
  338. isAddChildNode:0,
  339. id:parentData.value.id,
  340. parentId:parentData.value.parentId,
  341. isParent:isTable.value ? false : true,
  342. },
  343. )
  344. }
  345. })
  346. })
  347. }
  348. }
  349. const leftTree = ref(null)
  350. </script>
  351. <style lang="scss" scoped>
  352. .tree-list {
  353. position: relative;
  354. .item {
  355. position: relative;
  356. height: 24px;
  357. display: flex;
  358. align-items: center;
  359. white-space: nowrap;
  360. cursor: pointer;
  361. transition: color .2s;
  362. &:hover {
  363. color: var(--el-color-primary);
  364. }
  365. }
  366. }
  367. </style>