|
|
@@ -0,0 +1,317 @@
|
|
|
+<!-- 节点划分 -->
|
|
|
+<template>
|
|
|
+ <hc-new-dialog v-model="linkModal" is-table title="节点划分" widths="1200px" @close="closeModal">
|
|
|
+ <div class="link-data-box">
|
|
|
+ <div class="link-data-left">
|
|
|
+ <div class="relative h-full flex">
|
|
|
+ <div v-loading="treeLoading" class="hc_tree_card_border relative w-full">
|
|
|
+ <hc-body scrollbar padding="0px">
|
|
|
+ <HcLazyTree
|
|
|
+ ref="leftTree"
|
|
|
+ tree-key="id"
|
|
|
+ show-checkbox
|
|
|
+ is-type
|
|
|
+ :is-color="false"
|
|
|
+ @check="treeNodeCheck"
|
|
|
+ @load="treeLoadNode"
|
|
|
+ @node-loading="treeNodeLoading"
|
|
|
+ />
|
|
|
+ </hc-body>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="link-data-icon">
|
|
|
+ <HcIcon type="primary" name="links" style="font-size: 22px;" />
|
|
|
+ </div>
|
|
|
+ <div class="link-data-right">
|
|
|
+ <div class="relative h-full flex">
|
|
|
+ <div v-loading="treeLoading" class="hc_tree_card_border relative w-full">
|
|
|
+ <hc-body scrollbar padding="0px">
|
|
|
+ <HcLazyTree
|
|
|
+ ref="rightTree"
|
|
|
+ tree-key="id"
|
|
|
+ show-checkbox
|
|
|
+ is-type
|
|
|
+ :is-color="false"
|
|
|
+ @check="treeNodeCheckRight"
|
|
|
+ @load="treeLoadNode"
|
|
|
+ >
|
|
|
+ <template #name="{ node, data }">
|
|
|
+ <div class="custom-tree-node">
|
|
|
+ <div class="label" @dblclick="ElTreeDblClick(data)">
|
|
|
+ <el-input v-if="data.isInputName" v-model="data.title" size="small" @blur="ElTreeBtnClick(data)" @keyup="keyUpEvent($event, data)">
|
|
|
+ <template #append>
|
|
|
+ <el-button plain size="small" type="primary" @click="ElTreeBtnClick(data)">
|
|
|
+ <HcIcon name="check" />
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </el-input>
|
|
|
+ <span v-else>{{ data.title }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </HcLazyTree>
|
|
|
+ </hc-body>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <template #footer>
|
|
|
+ <div class="dialog-footer">
|
|
|
+ <el-button hc-btn style="border: 1px solid var(--el-button-border-color);" @click="closeModal">
|
|
|
+ <HcIcon name="close" />
|
|
|
+ <span>取消</span>
|
|
|
+ </el-button>
|
|
|
+ <el-button hc-btn type="primary" :loading="sureLoading" @click="sureClick(1)">
|
|
|
+ <HcIcon name="check" />
|
|
|
+ <span>关联并退出</span>
|
|
|
+ </el-button>
|
|
|
+ <el-button hc-btn type="primary" :loading="sureLoading" @click="sureClick(2)">
|
|
|
+ <HcIcon name="check" />
|
|
|
+ <span>关联并继续</span>
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </hc-new-dialog>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { nextTick, ref, watch } from 'vue'
|
|
|
+import { getArrValue, getObjValue } from 'js-fast-way'
|
|
|
+import { useAppStore } from '~src/store'
|
|
|
+
|
|
|
+
|
|
|
+import queryApi from '~api/data-fill/query'
|
|
|
+const props = defineProps({
|
|
|
+ linkModal: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false,
|
|
|
+ },
|
|
|
+ isCheckId:{
|
|
|
+ type: Number,
|
|
|
+ default: 1,
|
|
|
+ },
|
|
|
+ checkIds:{
|
|
|
+ type: [Number, String],
|
|
|
+ default: '',
|
|
|
+ },
|
|
|
+ rightTreeCheck:{
|
|
|
+ type: Array,
|
|
|
+ default: () => ([]),
|
|
|
+ },
|
|
|
+ classifyType:{
|
|
|
+ type: String,
|
|
|
+ default: 1,
|
|
|
+ },
|
|
|
+
|
|
|
+})
|
|
|
+//事件
|
|
|
+const emit = defineEmits(['close', 'save'])
|
|
|
+const useAppState = useAppStore()
|
|
|
+const contractId = ref(useAppState.getContractId)
|
|
|
+const projectId = ref(useAppState.getProjectId)
|
|
|
+const isCheckId = ref(props.isCheckId)
|
|
|
+
|
|
|
+const classifyType = ref(props.classifyType)
|
|
|
+
|
|
|
+const linkModal = defineModel('modelValue', {
|
|
|
+ default: false,
|
|
|
+})
|
|
|
+const closeModal = ()=>{
|
|
|
+ linkModal.value = false
|
|
|
+ emit('close')
|
|
|
+}
|
|
|
+//获取两棵树的数据
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+const treeLoading = ref(true)
|
|
|
+const treeNodeLoading = () => {
|
|
|
+ treeLoading.value = false
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+const defaultCheckedKeys = ref([])
|
|
|
+const rightKeys = ref([])
|
|
|
+
|
|
|
+ const meterIds = ref('')
|
|
|
+const wbsIds = ref('')
|
|
|
+const rightTree = ref(null)
|
|
|
+
|
|
|
+//监听
|
|
|
+watch(() => [
|
|
|
+props.linkModal,
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+props.classifyType,
|
|
|
+], ([link, type]) => {
|
|
|
+ linkModal.value = link
|
|
|
+ classifyType.value = type
|
|
|
+}, { immediate: true })
|
|
|
+
|
|
|
+
|
|
|
+const sureLoading = ref(false)
|
|
|
+const sureClick = async (type)=>{
|
|
|
+
|
|
|
+ if (!meterIds.value || !wbsIds.value) {
|
|
|
+ window.$message.warning('请先选择需要关联的节点')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ sureLoading.value = true
|
|
|
+ const { error, code, data, msg } = await unitApi.LinkMeterTreeAndWbsTree({
|
|
|
+ projectId:projectId.value,
|
|
|
+ contractId:contractId.value,
|
|
|
+ meterIds:meterIds.value,
|
|
|
+ wbsIds:wbsIds.value,
|
|
|
+
|
|
|
+ })
|
|
|
+ sureLoading.value = false
|
|
|
+ if (!error && code === 200) {
|
|
|
+ window.$message.success(msg)
|
|
|
+ if (type === 1) {
|
|
|
+ linkModal.value = false
|
|
|
+ emit('save')
|
|
|
+ } else {
|
|
|
+ if (isCheckId.value === 1) {
|
|
|
+ nextTick(()=>{
|
|
|
+
|
|
|
+ defaultCheckedKeys.value = []
|
|
|
+ rightKeys.value = []
|
|
|
+ wbsIds.value = ''
|
|
|
+ meterIds.value = ''
|
|
|
+ leftTree.value.treeRef.setCheckedKeys([])
|
|
|
+ rightTree.value.treeRef.setCheckedKeys([])
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const leftTree = ref(null)
|
|
|
+const treeLoadNode = async ({ node, item, level }, resolve) => {
|
|
|
+ let contractIdRelation = '',
|
|
|
+ parentId = '',
|
|
|
+ primaryKeyId = ''
|
|
|
+ if (level !== 0) {
|
|
|
+ const nodeData = getObjValue(item)
|
|
|
+ contractIdRelation = nodeData?.contractIdRelation || ''
|
|
|
+ parentId = contractIdRelation ? nodeData?.primaryKeyId : nodeData?.id
|
|
|
+ primaryKeyId = nodeData?.id || ''
|
|
|
+ }
|
|
|
+ //获取数据
|
|
|
+ const { data } = await queryApi.queryWbsTreeData({
|
|
|
+ contractId: contractId.value || '',
|
|
|
+ contractIdRelation,
|
|
|
+ primaryKeyId,
|
|
|
+ parentId,
|
|
|
+ classifyType: classifyType.value,
|
|
|
+ tableOwner: classifyType.value,
|
|
|
+ })
|
|
|
+ resolve(getArrValue(data))
|
|
|
+ treeLoading.value = false
|
|
|
+}
|
|
|
+//更改节点名称
|
|
|
+const ElTreeDblClick = (item) => {
|
|
|
+ item.isInputName = true
|
|
|
+}
|
|
|
+//回车
|
|
|
+const keyUpEvent = (e, item) => {
|
|
|
+ if (e.key === 'Enter') {
|
|
|
+ ElTreeBtnClick(item)
|
|
|
+ }
|
|
|
+}
|
|
|
+//更改节点名称完成
|
|
|
+const ElTreeBtnClick = (item) => {
|
|
|
+ if (!item?.title) {
|
|
|
+ window?.$message?.warning('节点名称不能为空')
|
|
|
+ } else {
|
|
|
+ item.isInputName = false
|
|
|
+ // ElTreeCheckedKeys()
|
|
|
+ }
|
|
|
+}
|
|
|
+const treeNodeCheck = (_, { checkedNodes }) => {
|
|
|
+ console.log(checkedNodes, 'checkedNodes')
|
|
|
+ let arr = []
|
|
|
+ checkedNodes.forEach(ele => {
|
|
|
+ if (!ele.hasChild) {
|
|
|
+ arr.push(ele.id)
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ meterIds.value = arr.join(',')
|
|
|
+}
|
|
|
+
|
|
|
+const treeNodeCheckRight = (_, { checkedNodes }) => {
|
|
|
+ let arr = []
|
|
|
+ checkedNodes.forEach(ele => {
|
|
|
+ if (!ele.hasChild) {
|
|
|
+ arr.push(ele.pkeyId)
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ wbsIds.value = arr.join(',')
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang='scss' scoped>
|
|
|
+.title-box{
|
|
|
+ position: relative;
|
|
|
+ display: flex;
|
|
|
+
|
|
|
+ // padding: 40px;
|
|
|
+ font-weight: 400;
|
|
|
+ font-size: 18px;
|
|
|
+ width: 100%;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ margin-top: 10px;
|
|
|
+
|
|
|
+ .title-box-left{
|
|
|
+ width: 50%;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+ .title-box-right{
|
|
|
+ width: 50%;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+}
|
|
|
+.link-data-box{
|
|
|
+ position: relative;
|
|
|
+ display: flex;
|
|
|
+ height: calc(100% - 45px);
|
|
|
+ align-items: center;
|
|
|
+ // border: 1px solid rgb(187, 187, 187);
|
|
|
+ padding: 0px 40px 0px 40px;
|
|
|
+ .link-data-left{
|
|
|
+ width: 50%;
|
|
|
+ position: relative;
|
|
|
+ height: 100%;
|
|
|
+ background: #ffffff;
|
|
|
+ border: 1px solid #273044;
|
|
|
+ }
|
|
|
+ .link-data-icon{
|
|
|
+ display: inline-block;
|
|
|
+ vertical-align: middle;
|
|
|
+ padding: 0 16px;
|
|
|
+ }
|
|
|
+ .link-data-right{
|
|
|
+ width: 50%;
|
|
|
+ position: relative;
|
|
|
+ height: 100%;
|
|
|
+ background: #ffffff;
|
|
|
+ border: 1px solid #273044;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|
|
|
+
|
|
|
+<style lang="scss">
|
|
|
+.link-data-right .el-tree.hc-tree-node-v2 .data-custom-tree-node .label, .hc-tree-node .data-custom-tree-node .label{
|
|
|
+ display: flex;
|
|
|
+}
|
|
|
+</style>
|