123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501 |
- <!-- 节点划分 -->
- <template>
- <hc-new-dialog v-model="linkModal" is-table widths="1200px" @close="closeModal">
- <template #header>
- <div class="flex justify-between">
- <div class="text-lg">节点划分</div>
- <div class="mr-8 w-100 flex">
- <el-input
- v-model="searchTreeVal"
- clearable
- block
- placeholder="请输入名称关键词检索"
- @keyup="searchTreeKeyUp"
- @clear="searchTreeClick"
- >
- <template #suffix>
- <HcIcon
- name="search-2"
- ui="text-xl iscusor"
- @click="searchTreeClick"
- />
- </template>
- </el-input>
- <el-button type="primary" class="ml-2" @click="searchTreeClick">搜索</el-button>
- </div>
- </div>
- </template>
- <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"
-
- show-checkbox
- is-type
- check-strictly
- :h-props="leftTreeProps"
- :is-color="false"
- :accordion="false"
- :auto-expand-keys="treeAutoExpandKeys"
- @check="leftTreeNodeCheckChange"
- @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="treeLoadingData" class="hc_tree_card_border relative w-full">
- <hc-body scrollbar padding="0px">
- <HcLazyTree
- v-if="!isSearchTree"
- ref="rightTree"
- v-model:loading="isLoading"
- tree-key="id"
- show-checkbox
- is-type
- :is-color="false"
- :default-checked-keys="defaultCheckedKeys"
- :is-auto-check="true"
- :accordion="false"
- :h-props="treeProps"
- @check="addTreeNodeCheckChange"
- @load="rightTreeLoadNode"
- @node-tap="rightElTreeClick"
- >
- <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>
- <HcDataTree
- v-if="isSearchTree"
- :datas="searchTreeData"
- show-checkbox
- is-type
- :auto-expand-keys="treeAutoExpandKeys"
- default-expand-all
- />
- </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" :disabled="isLoading" @click="sureClick(1)">
- <HcIcon name="check" />
- <span>关联并退出</span>
- </el-button>
- <el-button hc-btn type="primary" :loading="sureLoading" :disabled="isLoading" @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 samplingApi from '~api/tentative/material/sampling'
- import queryApi from '~api/data-fill/query'
- import wbsApi from '~api/data-fill/wbs'
- import { getStoreValue } from '~uti/storage'
- const props = defineProps({
- linkModal: {
- type: Boolean,
- default: false,
- },
-
-
- classifyType:{
- type: String,
- default: '1',
- },
- treeItemInfo:{
- type: Object,
- default: () => ({}),
- },
- firstTree: {
- type: Object,
- default: () => ({}),
- },
- autoExpandKeys: {
- type: Array,
- default: () => [],
- },
- })
- //事件
- const emit = defineEmits(['close', 'save'])
- const useAppState = useAppStore()
- const contractId = ref(useAppState.getContractId)
- const projectId = ref(useAppState.getProjectId)
- const treeItemInfo = ref(props.treeItemInfo)
- const classifyType = ref(props.classifyType)
- const firstTree = ref(props.firstTree)
- const treeAutoExpandKeys = ref(props.autoExpandKeys)
- const linkModal = defineModel('modelValue', {
- default: false,
- })
- const closeModal = ()=>{
- linkModal.value = false
- leftPid.value = ''
- allSelectedList.value = []
- halfSelectedList.value = []
- emit('close')
- }
- //获取两棵树的数据
- const treeLoading = ref(true)
- const treeNodeLoading = () => {
- treeLoading.value = false
- }
- const rightTree = ref(null)
- const treeProps = ref({
- label: 'title',
- children: 'children',
- isLeaf: (data) => !data.hasChildren,
- // disabled: (data) => {
- // // 当节点类型为6时才能选择
- // return data.nodeType !== 6
- // },
- })
- const leftTreeProps = ref({
- label: 'title',
- children: 'children',
- isLeaf: (data) =>!data.hasChildren,
- disabled: (data) => {
- // 当节点类型为6时不能能选择
- return data.nodeType === 6
- },
- })
- //监听
- const isLoading = ref(false)
- watch(isLoading, (newVal) => {
- console.log('加载状态变化:', newVal)
- })
- watch(() => [
- props.linkModal,
- props.classifyType,
- props.treeItemInfo,
- props.firstTree,
- props.autoExpandKeys,
- ], ([link, type, treeItemIn, first, keys]) => {
- linkModal.value = link
- classifyType.value = type
- treeItemInfo.value = treeItemIn
- firstTree.value = first
- treeAutoExpandKeys.value = keys
- console.log(keys, 'keys')
-
- }, { immediate: true })
- //选中的节点
- const defaultCheckedKeys = ref([])
- const allSelectedList = ref([])
- const halfSelectedList = ref([])
- const addTreeNodeCheckChange = async (_, { checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys }) => {
- await nextTick()
- //全选数据
- const keys = checkedNodes || []
- console.log('key22222222s', keys)
- const NodesArr = keys
- .filter(node => node.nodeType === 6)
- .map(node => ({
- nodeName: node.title,
- primaryKeyId: node.primaryKeyId,
- }))
- // 更新选中状态
- defaultCheckedKeys.value = checkedNodes.map(node => node.id)
- console.log( defaultCheckedKeys.value, ' defaultCheckedKeys.value')
-
- allSelectedList.value = NodesArr
- //半选数据
- const halfNodes = halfCheckedNodes || []
- const halfArr = halfNodes
- .filter(node => node.nodeType === 6)
- .map(node => ({
- nodeName: node.title,
- primaryKeyId: node.primaryKeyId,
- }))
- halfSelectedList.value = halfArr
- }
- const sureLoading = ref(false)
- const sureClick = async (type) => {
- await nextTick() // 等待下一个 DOM
- const keys = allSelectedList.value || []
- console.log('keys', keys)
-
- if (keys.length <= 0 || leftPid.value.length <= 0) {
- window?.$message?.warning('请先选择节点')
- return
- } else {
- //发起请求
- sureLoading.value = true
-
- const { error, code, msg } = await wbsApi.saveContractTreeNode({
- projectId: projectId.value,
- contractId: contractId.value,
- saveType: 4, //节点划分,多对多
- allSelectedList: allSelectedList.value,
- halfSelectedList: halfSelectedList.value,
- currentNodePrimaryKeyId: leftPid.value,
- isImportTree: 1,
- templateType:useAppState.contractInfo?.templateType,
-
- })
- //判断状态
- sureLoading.value = false
- if (!error && code === 200) {
- window?.$message?.success(msg)
-
- // type=1时关闭弹窗,type=2时保持打开
- if (type === 1) {
- closeModal()
- emit('save')
- } else {
- allSelectedList.value = []
- halfSelectedList.value = []
- leftPid.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,
- dataTime:new Date(),
- })
- resolve(getArrValue(data))
- treeLoading.value = false
- }
- const leftPid = ref('')
- const leftTreeNodeCheckChange = (_, { checkedNodes }) => {
- if (checkedNodes && checkedNodes.length > 0) {
- // 获取所有选中节点的 primaryKeyId 并用逗号拼接
- leftPid.value = checkedNodes.map(node => node.primaryKeyId).filter(Boolean).join(',')
- } else {
- leftPid.value = ''
- }
- }
- //更改节点名称
- 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 rightTreeLoadNode = async ({ node, item, level }, resolve) => {
- let parentId = '0'
- if (level !== 0) {
- parentId = item?.id
- }
- //获取数据
- const { data } = await samplingApi.queryLazyTree({
- wbsId: firstTree.value?.wbsId,
- tenantId: getStoreValue('tenantId') || '',
- projectId: projectId.value,
- parentId,
- wbsType: firstTree.value.wbsType,
- type:1,
- })
- resolve(getArrValue(data))
- // 确保在数据加载完成后,重新设置选中状态
- await nextTick()
- if (defaultCheckedKeys.value.length > 0) {
- rightTree.value?.treeRef.setCheckedKeys(defaultCheckedKeys.value)
- }
-
- }
- const rightObj = ref(null)
- const rightElTreeClick = ({ data }) => {
- rightObj.value = data
- }
- //搜索右边的节点树
- const searchTreeVal = ref('')
- const searchTreeData = ref([])
- const isSearchTree = ref(false)
- //回车
- const treeLoadingData = ref(false)
- const getSearchTreeData = async () => {
- treeLoadingData.value = true
- const { error, code, data } = await wbsApi.getQueryValueByType({
- contractId: contractId.value,
- queryValue: searchTreeVal.value,
- projectId:projectId.value,
- type:1,
- wbsId:firstTree.value?.wbsId,
- })
- //判断状态
- if (!error && code === 200) {
- let treedata = getArrValue(data)
- searchTreeData.value = treedata
- treeLoadingData.value = false
- } else {
- treeLoadingData.value = false
- searchTreeData.value = []
- }
- }
- const searchTreeKeyUp = (e) => {
- if (e.key === 'Enter') {
- searchTreeClick()
- }
- }
- const searchTreeClick = async () => {
- if (searchTreeVal.value) {
-
- isSearchTree.value = true
- //treeLoading.value = true
- getSearchTreeData().then()
- } else {
- isSearchTree.value = false
- }
- }
- </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>
|