|
|
|
@ -1,14 +1,12 @@ |
|
|
|
|
|
|
|
<script lang='ts' setup> |
|
|
|
|
|
|
|
import { computed,ref,watch,onBeforeMount} from 'vue' |
|
|
|
import { computed, ref, watch, onBeforeMount } from 'vue' |
|
|
|
|
|
|
|
const props = withDefaults( |
|
|
|
defineProps<{ |
|
|
|
modelValue?: string |
|
|
|
disabled?: boolean |
|
|
|
types?:number |
|
|
|
control?:any |
|
|
|
types?: number |
|
|
|
control?: any |
|
|
|
orgAndManTree?: any; |
|
|
|
data?: any; |
|
|
|
}>(), |
|
|
|
@ -20,150 +18,169 @@ const emits = defineEmits<{ |
|
|
|
}>() |
|
|
|
|
|
|
|
const value = ref([]) |
|
|
|
watch(value,(newValue)=>{ |
|
|
|
if(newValue.length > 0){ |
|
|
|
let str = "" |
|
|
|
const treeData = ref([]) // 存储懒加载的数据 |
|
|
|
const isDataLoaded = ref(false) // 标记数据是否已加载 |
|
|
|
|
|
|
|
watch(value, (newValue) => { |
|
|
|
if (newValue.length > 0) { |
|
|
|
let str = "" |
|
|
|
let userAry = new Array |
|
|
|
|
|
|
|
newValue.forEach(item =>{ |
|
|
|
//console.log(item) |
|
|
|
newValue.forEach(item => { |
|
|
|
userAry.push(item) |
|
|
|
|
|
|
|
}) |
|
|
|
str = userAry.join(',') |
|
|
|
//console.log(str) |
|
|
|
emits('update:modelValue', str) |
|
|
|
// userlist.value = userAry.join(',') |
|
|
|
// |
|
|
|
}else{ |
|
|
|
} else { |
|
|
|
let str = "" |
|
|
|
//console.log(str) |
|
|
|
emits('update:modelValue', str) |
|
|
|
} |
|
|
|
},{ deep: true }) |
|
|
|
|
|
|
|
|
|
|
|
}, { deep: true }) |
|
|
|
|
|
|
|
function parseStringToArray(str:string) { |
|
|
|
function parseStringToArray(str: string) { |
|
|
|
try { |
|
|
|
// 尝试解析JSON格式字符串 |
|
|
|
const result = JSON.parse(str); |
|
|
|
// 验证解析结果是否为数组 |
|
|
|
if (Array.isArray(result)) { |
|
|
|
return result; |
|
|
|
} else { |
|
|
|
//console.error("解析结果不是数组"); |
|
|
|
return []; |
|
|
|
} |
|
|
|
} catch (error) { |
|
|
|
//console.error("字符串格式错误,无法解析为数组:", error.message); |
|
|
|
return []; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
onBeforeMount(() => { |
|
|
|
setTimeout(()=>{ |
|
|
|
setTimeout(() => { |
|
|
|
value.value = parseStringToArray(props.modelValue) |
|
|
|
},500 ) |
|
|
|
}, 500) |
|
|
|
}) |
|
|
|
|
|
|
|
// 加载完整数据的函数 |
|
|
|
const loadFullData = async () => { |
|
|
|
if (isDataLoaded.value) return treeData.value; |
|
|
|
|
|
|
|
try { |
|
|
|
const result = checkorgAndManTree1(); |
|
|
|
treeData.value = result; |
|
|
|
isDataLoaded.value = true; |
|
|
|
return result; |
|
|
|
} catch (error) { |
|
|
|
console.error('加载组织数据失败:', error); |
|
|
|
return []; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 点击树选择器时的处理 |
|
|
|
const handleTreeSelectClick = async () => { |
|
|
|
if (!isDataLoaded.value) { |
|
|
|
await loadFullData(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
const resData = computed(()=>{ |
|
|
|
return checkorgAndManTree1() |
|
|
|
// 下拉框显示状态变化时的处理 |
|
|
|
const handleVisibleChange = async (visible: boolean) => { |
|
|
|
if (visible && !isDataLoaded.value) { |
|
|
|
await loadFullData(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
const resData = computed(() => { |
|
|
|
return treeData.value; |
|
|
|
}) |
|
|
|
|
|
|
|
function checkorgAndManTree1(){ |
|
|
|
function checkorgAndManTree1() { |
|
|
|
let result = [] |
|
|
|
let i = 0 |
|
|
|
props.orgAndManTree.forEach((element : any) => { |
|
|
|
if(element.hasOwnProperty('tree')&&hasNodesInTree(element.tree)){ |
|
|
|
props.orgAndManTree.forEach((element: any) => { |
|
|
|
if (element.hasOwnProperty('tree') && hasNodesInTree(element.tree)) { |
|
|
|
i++ |
|
|
|
} |
|
|
|
}); |
|
|
|
if(i==props.orgAndManTree.length){ |
|
|
|
props.orgAndManTree.forEach((item : any) => { |
|
|
|
|
|
|
|
if(props.data.name==item.name){ |
|
|
|
if (i == props.orgAndManTree.length) { |
|
|
|
props.orgAndManTree.forEach((item: any) => { |
|
|
|
if (props.data.name == item.name) { |
|
|
|
console.log(item.tree) |
|
|
|
result = item.tree |
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
return result |
|
|
|
}else{ |
|
|
|
setTimeout(()=>{ |
|
|
|
} else { |
|
|
|
setTimeout(() => { |
|
|
|
checkorgAndManTree1() |
|
|
|
},100) |
|
|
|
}, 100) |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* 判断树形结构是否存在节点 |
|
|
|
* @param {Array} tree 树形结构数组(最外层为数组,每个节点可能包含children属性) |
|
|
|
* @returns {boolean} 存在节点返回true,否则返回false |
|
|
|
*/ |
|
|
|
function hasNodesInTree(tree) { |
|
|
|
// 边界条件:如果输入不是数组,直接返回false |
|
|
|
if (!Array.isArray(tree)) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
// 递归检查节点及其子节点 |
|
|
|
function checkNode(node) { |
|
|
|
// 节点本身存在(非null/undefined)即算一个节点 |
|
|
|
if (node == null) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
// 只要当前节点存在,就返回true |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
// 遍历根节点数组,只要有一个节点存在,就返回true |
|
|
|
for (const node of tree) { |
|
|
|
if (checkNode(node)) { |
|
|
|
// 即使当前节点没有子节点,自身也算一个节点 |
|
|
|
return true; |
|
|
|
} |
|
|
|
// 如果当前节点有子节点,递归检查子节点(防止极端情况:当前节点为空但子节点存在) |
|
|
|
if (Array.isArray(node?.children) && hasNodesInTree(node.children)) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 所有层级都没有节点 |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const valPrint = (val:any) => { |
|
|
|
|
|
|
|
if(Array.isArray(val)){ |
|
|
|
const valPrint = (val: any) => { |
|
|
|
if (Array.isArray(val)) { |
|
|
|
return val.join("、") |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
</script> |
|
|
|
|
|
|
|
<template> |
|
|
|
<div></div> |
|
|
|
|
|
|
|
<el-tree-select v-if="props.types!=3" node-key="number" v-model="value" :data="resData" multiple :render-after-expand="false" |
|
|
|
show-checkbox clearable collapse-tags collapse-tags-tooltip :max-collapse-tags="1" filterable /> |
|
|
|
<el-text v-else class="wordColor">{{valPrint(value)}}</el-text> |
|
|
|
<div class="tree-select-wrapper" v-if="props.types != 3"> |
|
|
|
<el-tree-select |
|
|
|
node-key="number" |
|
|
|
v-model="value" |
|
|
|
:data="resData" |
|
|
|
multiple |
|
|
|
:render-after-expand="false" |
|
|
|
show-checkbox |
|
|
|
clearable |
|
|
|
collapse-tags |
|
|
|
collapse-tags-tooltip |
|
|
|
:max-collapse-tags="1" |
|
|
|
filterable |
|
|
|
@click="handleTreeSelectClick" |
|
|
|
@visible-change="handleVisibleChange" |
|
|
|
:disabled="props.disabled" |
|
|
|
:popper-append-to-body="false" |
|
|
|
/> |
|
|
|
</div> |
|
|
|
<el-text v-else class="wordColor">{{ valPrint(value) }}</el-text> |
|
|
|
</template> |
|
|
|
<style lang='scss' > |
|
|
|
.wordColor{ |
|
|
|
color:#000000; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
<style lang='scss'> |
|
|
|
.tree-select-wrapper { |
|
|
|
position: relative; |
|
|
|
min-height: 40px; |
|
|
|
width: 100%; |
|
|
|
} |
|
|
|
|
|
|
|
.wordColor { |
|
|
|
color: #000000; |
|
|
|
} |
|
|
|
|
|
|
|
.el-tree-node__expand-icon { |
|
|
|
color: var(--el-tree-expand-icon-color); |
|
|
|
|