divisionDialog.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. <!-- 节点划分 -->
  2. <template>
  3. <hc-new-dialog v-model="linkModal" is-table title="节点划分" widths="1200px" @close="closeModal">
  4. <div class="link-data-box">
  5. <div class="link-data-left">
  6. <div class="relative h-full flex">
  7. <div v-loading="treeLoading" class="hc_tree_card_border relative w-full">
  8. <hc-body scrollbar padding="0px">
  9. <HcLazyTree
  10. ref="leftTree"
  11. tree-key="id"
  12. show-checkbox
  13. is-type
  14. check-strictly
  15. :is-color="false"
  16. @check="leftTreeNodeCheckChange"
  17. @load="treeLoadNode"
  18. @node-loading="treeNodeLoading"
  19. />
  20. </hc-body>
  21. </div>
  22. </div>
  23. </div>
  24. <div class="link-data-icon">
  25. <HcIcon type="primary" name="links" style="font-size: 22px;" />
  26. </div>
  27. <div class="link-data-right">
  28. <div class="relative h-full flex">
  29. <div v-loading="treeLoading" class="hc_tree_card_border relative w-full">
  30. <hc-body scrollbar padding="0px">
  31. <HcLazyTree
  32. ref="rightTree"
  33. tree-key="id"
  34. show-checkbox
  35. is-type
  36. :is-color="false"
  37. @check="addTreeNodeCheckChange"
  38. @load="rightTreeLoadNode"
  39. @node-tap="rightElTreeClick"
  40. >
  41. <template #name="{ node, data }">
  42. <div class="custom-tree-node">
  43. <div class="label" @dblclick="ElTreeDblClick(data)">
  44. <el-input v-if="data.isInputName" v-model="data.title" size="small" @blur="ElTreeBtnClick(data)" @keyup="keyUpEvent($event, data)">
  45. <template #append>
  46. <el-button plain size="small" type="primary" @click="ElTreeBtnClick(data)">
  47. <HcIcon name="check" />
  48. </el-button>
  49. </template>
  50. </el-input>
  51. <span v-else>{{ data.title }}</span>
  52. </div>
  53. </div>
  54. </template>
  55. </HcLazyTree>
  56. </hc-body>
  57. </div>
  58. </div>
  59. </div>
  60. </div>
  61. <template #footer>
  62. <div class="dialog-footer">
  63. <el-button hc-btn style="border: 1px solid var(--el-button-border-color);" @click="closeModal">
  64. <HcIcon name="close" />
  65. <span>取消</span>
  66. </el-button>
  67. <el-button hc-btn type="primary" :loading="sureLoading" @click="sureClick(1)">
  68. <HcIcon name="check" />
  69. <span>关联并退出</span>
  70. </el-button>
  71. <el-button hc-btn type="primary" :loading="sureLoading" @click="sureClick(2)">
  72. <HcIcon name="check" />
  73. <span>关联并继续</span>
  74. </el-button>
  75. </div>
  76. </template>
  77. </hc-new-dialog>
  78. </template>
  79. <script setup>
  80. import { nextTick, ref, watch } from 'vue'
  81. import { getArrValue, getObjValue } from 'js-fast-way'
  82. import { useAppStore } from '~src/store'
  83. import samplingApi from '~api/tentative/material/sampling'
  84. import queryApi from '~api/data-fill/query'
  85. import wbsApi from '~api/data-fill/wbs'
  86. import { getStoreValue } from '~uti/storage'
  87. const props = defineProps({
  88. linkModal: {
  89. type: Boolean,
  90. default: false,
  91. },
  92. classifyType:{
  93. type: String,
  94. default: 1,
  95. },
  96. treeItemInfo:{
  97. type: Object,
  98. default: () => ({}),
  99. },
  100. firstTree: {
  101. type: Object,
  102. default: () => ({}),
  103. },
  104. })
  105. //事件
  106. const emit = defineEmits(['close', 'save'])
  107. const useAppState = useAppStore()
  108. const contractId = ref(useAppState.getContractId)
  109. const projectId = ref(useAppState.getProjectId)
  110. const treeItemInfo = ref(props.treeItemInfo)
  111. const classifyType = ref(props.classifyType)
  112. const firstTree = ref(props.firstTree)
  113. const linkModal = defineModel('modelValue', {
  114. default: false,
  115. })
  116. const closeModal = ()=>{
  117. linkModal.value = false
  118. leftPid.value = ''
  119. emit('close')
  120. }
  121. //获取两棵树的数据
  122. const treeLoading = ref(true)
  123. const treeNodeLoading = () => {
  124. treeLoading.value = false
  125. }
  126. const meterIds = ref('')
  127. const rightTree = ref(null)
  128. //监听
  129. watch(() => [
  130. props.linkModal,
  131. props.classifyType,
  132. props.treeItemInfo,
  133. props.firstTree,
  134. ], ([link, type, treeItemIn, first]) => {
  135. linkModal.value = link
  136. classifyType.value = type
  137. treeItemInfo.value = treeItemIn
  138. firstTree.value = first
  139. }, { immediate: true })
  140. //选中的节点
  141. const allSelectedList = ref([])
  142. const halfSelectedList = ref([])
  143. const addTreeNodeCheckChange = (_, { checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys }) => {
  144. console.log(checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys, 'nodes')
  145. let NodesArr = [],
  146. halfArr = []
  147. //全选数据
  148. const keys = checkedNodes || []
  149. console.log(keys, 'keys')
  150. for (let i = 0; i < keys.length; i++) {
  151. NodesArr.push({
  152. nodeName: keys[i].title,
  153. primaryKeyId: keys[i].primaryKeyId,
  154. })
  155. }
  156. allSelectedList.value = NodesArr
  157. console.log(allSelectedList.value, ' allSelectedList.value')
  158. //半选数据
  159. const halfNodes = halfCheckedNodes || []
  160. for (let i = 0; i < halfNodes.length; i++) {
  161. halfArr.push({
  162. nodeName: halfNodes[i].title,
  163. primaryKeyId: halfNodes[i].primaryKeyId,
  164. })
  165. }
  166. halfSelectedList.value = halfArr
  167. console.log(halfSelectedList.value, ' halfSelectedList.value')
  168. }
  169. const sureLoading = ref(false)
  170. const sureClick = async (type) => {
  171. const keys = allSelectedList.value || []
  172. if (keys.length <= 0 || leftPid.value.length <= 0) {
  173. window?.$message?.warning('请先选择节点')
  174. } else {
  175. //发起请求
  176. sureLoading.value = true
  177. const { error, code, msg } = await wbsApi.saveContractTreeNode({
  178. projectId: projectId.value,
  179. contractId: contractId.value,
  180. saveType: 2, //仅当前节点
  181. allSelectedList: allSelectedList.value,
  182. halfSelectedList: halfSelectedList.value,
  183. currentNodePrimaryKeyId: leftPid.value,
  184. isImportTree: 1,
  185. })
  186. //判断状态
  187. sureLoading.value = false
  188. if (!error && code === 200) {
  189. window?.$message?.success(msg)
  190. // type=1时关闭弹窗,type=2时保持打开
  191. if (type === 1) {
  192. closeModal()
  193. emit('save')
  194. }
  195. }
  196. }
  197. }
  198. const leftTree = ref(null)
  199. const treeLoadNode = async ({ node, item, level }, resolve) => {
  200. let contractIdRelation = '',
  201. parentId = '',
  202. primaryKeyId = ''
  203. if (level !== 0) {
  204. const nodeData = getObjValue(item)
  205. contractIdRelation = nodeData?.contractIdRelation || ''
  206. parentId = contractIdRelation ? nodeData?.primaryKeyId : nodeData?.id
  207. primaryKeyId = nodeData?.id || ''
  208. }
  209. //获取数据
  210. const { data } = await queryApi.queryWbsTreeData({
  211. contractId: contractId.value || '',
  212. contractIdRelation,
  213. primaryKeyId,
  214. parentId,
  215. classifyType: classifyType.value,
  216. tableOwner: classifyType.value,
  217. dataTime:new Date(),
  218. })
  219. resolve(getArrValue(data))
  220. treeLoading.value = false
  221. }
  222. const leftPid = ref('')
  223. const leftTreeNodeCheckChange = (_, { checkedNodes }) => {
  224. if (checkedNodes && checkedNodes.length > 0) {
  225. const lastCheckedNode = checkedNodes[checkedNodes.length - 1]
  226. leftPid.value = lastCheckedNode.primaryKeyId
  227. nextTick(() => {
  228. leftTree.value?.treeRef.setCheckedKeys([lastCheckedNode.id])
  229. })
  230. } else {
  231. leftPid.value = ''
  232. }
  233. }
  234. //更改节点名称
  235. const ElTreeDblClick = (item) => {
  236. item.isInputName = true
  237. }
  238. //回车
  239. const keyUpEvent = (e, item) => {
  240. if (e.key === 'Enter') {
  241. ElTreeBtnClick(item)
  242. }
  243. }
  244. //更改节点名称完成
  245. const ElTreeBtnClick = (item) => {
  246. if (!item?.title) {
  247. window?.$message?.warning('节点名称不能为空')
  248. } else {
  249. item.isInputName = false
  250. // ElTreeCheckedKeys()
  251. }
  252. }
  253. const rightTreeLoadNode = async ({ node, item, level }, resolve) => {
  254. let parentId = '0'
  255. if (level !== 0) {
  256. parentId = item?.id
  257. }
  258. //获取数据
  259. const { data } = await samplingApi.queryLazyTree({
  260. wbsId: firstTree.value?.wbsId,
  261. tenantId: getStoreValue('tenantId') || '',
  262. projectId: projectId.value,
  263. parentId,
  264. wbsType: firstTree.value.wbsType,
  265. })
  266. resolve(getArrValue(data))
  267. }
  268. const rightObj = ref(null)
  269. const rightElTreeClick = ({ data }) => {
  270. rightObj.value = data
  271. }
  272. </script>
  273. <style lang='scss' scoped>
  274. .title-box{
  275. position: relative;
  276. display: flex;
  277. // padding: 40px;
  278. font-weight: 400;
  279. font-size: 18px;
  280. width: 100%;
  281. margin-bottom: 10px;
  282. margin-top: 10px;
  283. .title-box-left{
  284. width: 50%;
  285. text-align: center;
  286. }
  287. .title-box-right{
  288. width: 50%;
  289. text-align: center;
  290. }
  291. }
  292. .link-data-box{
  293. position: relative;
  294. display: flex;
  295. height: calc(100% - 45px);
  296. align-items: center;
  297. // border: 1px solid rgb(187, 187, 187);
  298. padding: 0px 40px 0px 40px;
  299. .link-data-left{
  300. width: 50%;
  301. position: relative;
  302. height: 100%;
  303. background: #ffffff;
  304. border: 1px solid #273044;
  305. }
  306. .link-data-icon{
  307. display: inline-block;
  308. vertical-align: middle;
  309. padding: 0 16px;
  310. }
  311. .link-data-right{
  312. width: 50%;
  313. position: relative;
  314. height: 100%;
  315. background: #ffffff;
  316. border: 1px solid #273044;
  317. }
  318. }
  319. </style>
  320. <style lang="scss">
  321. .link-data-right .el-tree.hc-tree-node-v2 .data-custom-tree-node .label, .hc-tree-node .data-custom-tree-node .label{
  322. display: flex;
  323. }
  324. </style>