|
|
|
@ -1,10 +1,8 @@ |
|
|
|
|
|
|
|
<script lang='ts' setup> |
|
|
|
import { criteriaForPeopleList } from '@/api/hr/org/type' |
|
|
|
import SvgIcon from '@/components/svgIcon/index.vue' |
|
|
|
import { useAttrs,computed, onMounted, nextTick,ref,watch,onBeforeMount} from 'vue' |
|
|
|
import request from '@/utils/axios/index' |
|
|
|
const attrs = useAttrs() |
|
|
|
|
|
|
|
import { computed,ref,watch,onBeforeMount} from 'vue' |
|
|
|
|
|
|
|
const props = withDefaults( |
|
|
|
defineProps<{ |
|
|
|
modelValue?: string |
|
|
|
@ -12,20 +10,11 @@ const props = withDefaults( |
|
|
|
types?:number |
|
|
|
control?:any |
|
|
|
orgAndManTree?: any; |
|
|
|
data?: any; |
|
|
|
}>(), |
|
|
|
{} |
|
|
|
) |
|
|
|
interface User { |
|
|
|
id: number |
|
|
|
name: string |
|
|
|
number: string |
|
|
|
key: string |
|
|
|
icon: string |
|
|
|
department: string |
|
|
|
role: string |
|
|
|
label: string |
|
|
|
value: string |
|
|
|
} |
|
|
|
|
|
|
|
const emits = defineEmits<{ |
|
|
|
(e: 'update:modelValue', value: string): void |
|
|
|
}>() |
|
|
|
@ -73,7 +62,6 @@ function parseStringToArray(str:string) { |
|
|
|
} |
|
|
|
} |
|
|
|
onBeforeMount(() => { |
|
|
|
checkorgAndManTree() |
|
|
|
setTimeout(()=>{ |
|
|
|
value.value = parseStringToArray(props.modelValue) |
|
|
|
},500 ) |
|
|
|
@ -81,267 +69,79 @@ onBeforeMount(() => { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const keys = computed(()=>{ |
|
|
|
if(attrs.queryBy == 'role'){ |
|
|
|
return attrs.roleRange |
|
|
|
}else{ |
|
|
|
return attrs.orgRange |
|
|
|
} |
|
|
|
const resData = computed(()=>{ |
|
|
|
return checkorgAndManTree1() |
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
// 使用示例 |
|
|
|
const treeData = { |
|
|
|
"id": "102", |
|
|
|
"label": "企管部", |
|
|
|
"parentId": "309", |
|
|
|
"children": [ |
|
|
|
{ |
|
|
|
"id": "284148167597887488", |
|
|
|
"label": "荣潇亭", |
|
|
|
"parentId": "102", |
|
|
|
"children": null, |
|
|
|
"value": "303086", |
|
|
|
"treeAttrs": null, |
|
|
|
"disabled": null, |
|
|
|
"type": null |
|
|
|
}, |
|
|
|
{ |
|
|
|
"id": "272", |
|
|
|
"label": "企管", |
|
|
|
"parentId": "102", |
|
|
|
"children": [ |
|
|
|
{ |
|
|
|
"id": "284148287831805952", |
|
|
|
"label": "吴可楠", |
|
|
|
"parentId": "272", |
|
|
|
"children": null, |
|
|
|
"value": "303122", |
|
|
|
"treeAttrs": null, |
|
|
|
"disabled": null, |
|
|
|
"type": null |
|
|
|
} |
|
|
|
], |
|
|
|
"value": null, |
|
|
|
"treeAttrs": null, |
|
|
|
"disabled": null, |
|
|
|
"type": null |
|
|
|
function checkorgAndManTree1(){ |
|
|
|
let result = [] |
|
|
|
let i = 0 |
|
|
|
props.orgAndManTree.forEach((element : any) => { |
|
|
|
if(element.hasOwnProperty('tree')&&hasNodesInTree(element.tree)){ |
|
|
|
i++ |
|
|
|
} |
|
|
|
], |
|
|
|
"value": null, |
|
|
|
"treeAttrs": null, |
|
|
|
"disabled": null, |
|
|
|
"type": null |
|
|
|
}; |
|
|
|
|
|
|
|
const idList = ["284148167597887488", "284148287831805952"]; |
|
|
|
|
|
|
|
const resData = ref() |
|
|
|
}); |
|
|
|
if(i==props.orgAndManTree.length){ |
|
|
|
props.orgAndManTree.forEach((item : any) => { |
|
|
|
|
|
|
|
const checkorgAndManTree = (()=>{ |
|
|
|
if(props.orgAndManTree&&props.orgAndManTree.children&&props.orgAndManTree.children.length>0){ |
|
|
|
//alert(1) |
|
|
|
let arr = [] |
|
|
|
arr.push(modifyTreeData(props.orgAndManTree,keys.value)) |
|
|
|
if(props.data.name==item.name){ |
|
|
|
console.log(item.tree) |
|
|
|
result = item.tree |
|
|
|
} |
|
|
|
|
|
|
|
resData.value = arr |
|
|
|
}); |
|
|
|
return result |
|
|
|
}else{ |
|
|
|
setTimeout(()=>{ |
|
|
|
checkorgAndManTree() |
|
|
|
checkorgAndManTree1() |
|
|
|
},100) |
|
|
|
} |
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const resultExample = [{ |
|
|
|
"id": "102", |
|
|
|
"label": "企管部", |
|
|
|
"parentId": "309", |
|
|
|
"children": [ |
|
|
|
{ |
|
|
|
"id": "284148167597887488", |
|
|
|
"label": "荣潇亭(303086)", |
|
|
|
"parentId": "102", |
|
|
|
"children": null, |
|
|
|
"value": "303086", |
|
|
|
"treeAttrs": null, |
|
|
|
"disabled": null, |
|
|
|
"type": null, |
|
|
|
"number": "荣潇亭(303086)" |
|
|
|
}, |
|
|
|
{ |
|
|
|
"id": "272", |
|
|
|
"label": "企管", |
|
|
|
"parentId": "102", |
|
|
|
"children": [ |
|
|
|
{ |
|
|
|
"id": "284148287831805952", |
|
|
|
"label": "吴可楠(303122)", |
|
|
|
"parentId": "272", |
|
|
|
"children": null, |
|
|
|
"value": "303122", |
|
|
|
"treeAttrs": null, |
|
|
|
"disabled": null, |
|
|
|
"type": null, |
|
|
|
"number": "吴可楠(303122)" |
|
|
|
} |
|
|
|
], |
|
|
|
"value": null, |
|
|
|
"treeAttrs": null, |
|
|
|
"disabled": null, |
|
|
|
"type": null |
|
|
|
} |
|
|
|
], |
|
|
|
"value": null, |
|
|
|
"treeAttrs": null, |
|
|
|
"disabled": null, |
|
|
|
"type": null |
|
|
|
}] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function modifyTreeData(treeData, idList) { |
|
|
|
// 深拷贝树数据,避免修改原数据 |
|
|
|
const newTreeData = JSON.parse(JSON.stringify(treeData)); |
|
|
|
|
|
|
|
// 确保idList是一个数组 |
|
|
|
const idArray = Array.isArray(idList) ? idList : [idList]; |
|
|
|
if (idArray.length === 0) return Array.isArray(newTreeData) ? [] : null; |
|
|
|
|
|
|
|
// 1. 收集所有节点,记录:id→节点映射、id→父节点id映射(检测多父节点) |
|
|
|
const nodeMap = new Map(); // id → 节点 |
|
|
|
const parentMap = new Map(); // id → 父节点id(确保每个节点只有一个父节点) |
|
|
|
const multiParentIds = new Set(); // 记录有多个父节点的id |
|
|
|
|
|
|
|
function collectNodes(node, parentId) { |
|
|
|
if (!node || typeof node !== 'object' || !node.id) return; // 跳过无效节点 |
|
|
|
|
|
|
|
// 记录节点映射 |
|
|
|
if (!nodeMap.has(node.id)) { |
|
|
|
nodeMap.set(node.id, node); |
|
|
|
} |
|
|
|
|
|
|
|
// 记录父节点(检测多父节点) |
|
|
|
if (parentMap.has(node.id)) { |
|
|
|
// 已存在父节点,且与当前父节点不同 → 多父节点 |
|
|
|
if (parentMap.get(node.id) !== parentId) { |
|
|
|
multiParentIds.add(node.id); |
|
|
|
} |
|
|
|
} else { |
|
|
|
parentMap.set(node.id, parentId); // 首次记录父节点 |
|
|
|
} |
|
|
|
|
|
|
|
// 递归处理子节点,传入当前节点id作为父节点id |
|
|
|
if (node.children && Array.isArray(node.children)) { |
|
|
|
node.children.forEach(child => collectNodes(child, node.id)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 处理根节点(可能是单个节点或数组) |
|
|
|
if (Array.isArray(newTreeData)) { |
|
|
|
newTreeData.forEach(root => collectNodes(root, null)); // 根节点父id为null |
|
|
|
} else { |
|
|
|
collectNodes(newTreeData, null); |
|
|
|
} |
|
|
|
|
|
|
|
// 警告多父节点问题(核心重复原因) |
|
|
|
if (multiParentIds.size > 0) { |
|
|
|
console.warn(`以下节点存在多个父节点,可能导致重复:${Array.from(multiParentIds).join(', ')}`); |
|
|
|
/** |
|
|
|
* 判断树形结构是否存在节点 |
|
|
|
* @param {Array} tree 树形结构数组(最外层为数组,每个节点可能包含children属性) |
|
|
|
* @returns {boolean} 存在节点返回true,否则返回false |
|
|
|
*/ |
|
|
|
function hasNodesInTree(tree) { |
|
|
|
// 边界条件:如果输入不是数组,直接返回false |
|
|
|
if (!Array.isArray(tree)) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
// 2. 收集需要保留的节点ID:目标节点+直系祖先(基于parentMap追溯,确保唯一路径) |
|
|
|
const keepIds = new Set(); |
|
|
|
idArray.forEach(targetId => { |
|
|
|
let currentId = targetId; |
|
|
|
// 从目标节点向上追溯,直到根节点(parentId为null) |
|
|
|
while (currentId !== null && nodeMap.has(currentId)) { |
|
|
|
keepIds.add(currentId); |
|
|
|
currentId = parentMap.get(currentId); // 基于唯一父节点追溯 |
|
|
|
// 递归检查节点及其子节点 |
|
|
|
function checkNode(node) { |
|
|
|
// 节点本身存在(非null/undefined)即算一个节点 |
|
|
|
if (node == null) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
}); |
|
|
|
// 只要当前节点存在,就返回true |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
// 3. 过滤树结构:仅保留keepIds中的节点,且严格校验子节点的parentId是否匹配当前父节点 |
|
|
|
function filterTree(node) { |
|
|
|
if (!node || typeof node !== 'object' || !keepIds.has(node.id)) { |
|
|
|
return null; |
|
|
|
// 遍历根节点数组,只要有一个节点存在,就返回true |
|
|
|
for (const node of tree) { |
|
|
|
if (checkNode(node)) { |
|
|
|
// 即使当前节点没有子节点,自身也算一个节点 |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
// 复制节点(避免修改原引用) |
|
|
|
const filteredNode = { ...node }; |
|
|
|
|
|
|
|
// 处理子节点:仅保留符合条件的子节点(在keepIds中,且parentId等于当前节点id) |
|
|
|
if (filteredNode.children && Array.isArray(filteredNode.children)) { |
|
|
|
// 临时存储符合条件的子节点(去重) |
|
|
|
const validChildren = new Map(); // 用id去重 |
|
|
|
|
|
|
|
filteredNode.children.forEach(child => { |
|
|
|
// 校验:子节点必须在keepIds中,且其父节点id是当前节点id |
|
|
|
if (child && typeof child === 'object' && child.id && |
|
|
|
keepIds.has(child.id) && parentMap.get(child.id) === filteredNode.id) { |
|
|
|
const filteredChild = filterTree(child); |
|
|
|
if (filteredChild) { |
|
|
|
validChildren.set(filteredChild.id, filteredChild); // 用id去重 |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
// 转为数组,保持原数据格式(空数组→null) |
|
|
|
filteredNode.children = Array.from(validChildren.values()); |
|
|
|
if (filteredNode.children.length === 0) { |
|
|
|
filteredNode.children = null; |
|
|
|
} |
|
|
|
} else { |
|
|
|
filteredNode.children = null; |
|
|
|
// 如果当前节点有子节点,递归检查子节点(防止极端情况:当前节点为空但子节点存在) |
|
|
|
if (Array.isArray(node?.children) && hasNodesInTree(node.children)) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
return filteredNode; |
|
|
|
} |
|
|
|
|
|
|
|
// 处理根节点(数组或单个节点) |
|
|
|
let filteredTree; |
|
|
|
if (Array.isArray(newTreeData)) { |
|
|
|
// 根节点必须在keepIds中,且父节点为null |
|
|
|
filteredTree = newTreeData |
|
|
|
.map(root => { |
|
|
|
if (root && keepIds.has(root.id) && parentMap.get(root.id) === null) { |
|
|
|
return filterTree(root); |
|
|
|
} |
|
|
|
return null; |
|
|
|
}) |
|
|
|
.filter(Boolean); |
|
|
|
} else { |
|
|
|
filteredTree = (keepIds.has(newTreeData.id) && parentMap.get(newTreeData.id) === null) |
|
|
|
? filterTree(newTreeData) |
|
|
|
: null; |
|
|
|
} |
|
|
|
|
|
|
|
// 4. 对目标节点修改label和添加number属性 |
|
|
|
function modifyLabels(node) { |
|
|
|
if (!node || typeof node !== 'object') return; |
|
|
|
// 所有层级都没有节点 |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
if (idArray.includes(node.id)) { |
|
|
|
const newLabel = `${node.label}(${node.value || ''})`; |
|
|
|
node.label = newLabel; |
|
|
|
node.number = newLabel; |
|
|
|
} |
|
|
|
|
|
|
|
if (node.children && Array.isArray(node.children)) { |
|
|
|
node.children.forEach(child => modifyLabels(child)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 执行标签修改 |
|
|
|
if (Array.isArray(filteredTree)) { |
|
|
|
filteredTree.forEach(root => modifyLabels(root)); |
|
|
|
} else { |
|
|
|
modifyLabels(filteredTree); |
|
|
|
} |
|
|
|
|
|
|
|
return filteredTree; |
|
|
|
} |
|
|
|
const valPrint = (val:any) => { |
|
|
|
|
|
|
|
if(Array.isArray(val)){ |
|
|
|
@ -364,20 +164,6 @@ const valPrint = (val:any) => { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ::v-deep .el-tree-node__expand-icon { |
|
|
|
|
|
|
|
font-size: 38px; |
|
|
|
|
|
|
|
width: 34px; |
|
|
|
height: 34px; |
|
|
|
line-height: 34px; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
::v-deep .el-tree-node__expand-icon::before { |
|
|
|
font-size: 38px; |
|
|
|
} |
|
|
|
*/ |
|
|
|
|
|
|
|
.el-tree-node__expand-icon { |
|
|
|
color: var(--el-tree-expand-icon-color); |
|
|
|
|