自定义APP自定义App数据通讯
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

406 lines
11 KiB

<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()
const props = withDefaults(
defineProps<{
modelValue?: string
disabled?: boolean
types?:number
control?:any
orgAndManTree?: 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
}>()
const value = ref([])
watch(value,(newValue)=>{
if(newValue.length > 0){
let str = ""
let userAry = new Array
newValue.forEach(item =>{
//console.log(item)
userAry.push(item)
})
str = userAry.join(',')
//console.log(str)
emits('update:modelValue', str)
// userlist.value = userAry.join(',')
//
}else{
let str = ""
//console.log(str)
emits('update:modelValue', str)
}
},{ deep: true })
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(() => {
checkorgAndManTree()
setTimeout(()=>{
value.value = parseStringToArray(props.modelValue)
},500 )
})
const keys = computed(()=>{
if(attrs.queryBy == 'role'){
return attrs.roleRange
}else{
return attrs.orgRange
}
})
// 使用示例
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
}
],
"value": null,
"treeAttrs": null,
"disabled": null,
"type": null
};
const idList = ["284148167597887488", "284148287831805952"];
const resData = ref()
const checkorgAndManTree = (()=>{
if(props.orgAndManTree&&props.orgAndManTree.children&&props.orgAndManTree.children.length>0){
//alert(1)
let arr = []
arr.push(modifyTreeData(props.orgAndManTree,keys.value))
resData.value = arr
}else{
setTimeout(()=>{
checkorgAndManTree()
},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(', ')}`);
}
// 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); // 基于唯一父节点追溯
}
});
// 3. 过滤树结构:仅保留keepIds中的节点,且严格校验子节点的parentId是否匹配当前父节点
function filterTree(node) {
if (!node || typeof node !== 'object' || !keepIds.has(node.id)) {
return null;
}
// 复制节点(避免修改原引用)
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;
}
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;
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)){
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>
</template>
<style lang='scss' >
.wordColor{
color:#000000;
}
/* ::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);
cursor: pointer;
font-size: 18px;
transform: rotate(0deg);
transition: transform var(--el-transition-duration) ease-in-out;
}
.el-tree {
--el-tree-node-content-height: 30px;
--el-tree-node-hover-bg-color: var(--el-fill-color-light);
--el-tree-text-color: var(--el-text-color-regular);
--el-tree-expand-icon-color: var(--el-text-color-placeholder);
background: var(--el-fill-color-blank);
color: var(--el-tree-text-color);
cursor: default;
font-size: var(--el-font-size-base);
position: relative;
}
.el-tree-select__popper .el-tree-node__expand-icon {
margin-left: 7px;
margin-right: 7px;
}
</style>