Browse Source

选择组织支持多选,支持设定数据范围

yunpan
liwenxuan 2 months ago
parent
commit
5fd462c7bf
  1. 358
      src/components/lowCode/assistant/org.vue

358
src/components/lowCode/assistant/org.vue

@ -5,6 +5,7 @@
--> -->
<script lang='ts' setup> <script lang='ts' setup>
import { getOrgTreeList } from '@/api/hr/org/index' import { getOrgTreeList } from '@/api/hr/org/index'
import { computed } from 'vue';
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
data: FormList data: FormList
@ -12,7 +13,7 @@ const props = withDefaults(
numrun?: number numrun?: number
modelValue?: any // modelValue?: any //
tProp?: string // form-itemprop tProp?: string // form-itemprop
types?:number types?: number
}>(), }>(),
{} {}
) )
@ -20,7 +21,7 @@ const emits = defineEmits<{
(e: 'update:modelValue', numVal: any): void (e: 'update:modelValue', numVal: any): void
}>() }>()
const value = computed({ /* const value = computed({
get: () => { get: () => {
if (props.modelValue != "" && props.modelValue != undefined){ if (props.modelValue != "" && props.modelValue != undefined){
return props.modelValue*1 return props.modelValue*1
@ -29,13 +30,244 @@ const value = computed({
} }
}, },
set: (newVal: any) => { set: (newVal: any) => {
console.log(newVal)
emits('update:modelValue', newVal) emits('update:modelValue', newVal)
},
}); */
const value = computed({
get: () => {
if (props.modelValue != "" && props.modelValue != undefined) {
if (hasComma(props.modelValue) || multiple) {
return commaStringToNumberArray(props.modelValue)
} else {
return props.modelValue * 1;
}
} else {
return props.modelValue;
}
},
set: (newVal: any) => {
//console.log(newVal)
if (isArray(newVal)) {
let str = arrayToCommaString(newVal)
//console.log(2)
//console.log(str)
emits("update:modelValue", str);
} else {
//console.log(1)
//console.log(newVal)
emits("update:modelValue", newVal);
}
}, },
}); });
function hasComma(str: any) {
//
if (typeof str !== 'string') {
return false
}
// 使indexOf
// truefalse
return str.indexOf(',') !== -1;
}
function commaStringToNumberArray(str: string) {
//
if (typeof str !== 'string') {
throw new Error('输入必须是字符串');
}
//
if (str.trim() === '') {
return [];
}
//
return str.split(',').map(item => {
//
const trimmed = item.trim();
//
const number = Number(trimmed);
//
if (isNaN(number)) {
throw new Error(`无法将 "${trimmed}" 转换为有效数字`);
}
return number;
});
}
function isArray(variable: any) {
// 使
if (typeof Array.isArray === 'function') {
return Array.isArray(variable);
} else {
//
return Object.prototype.toString.call(variable) === '[object Array]';
}
}
function arrayToCommaString(numbers: any[]) {
//
if (!Array.isArray(numbers)) {
throw new Error('输入必须是一个数组');
}
// 使join
return numbers.join(',');
}
/**
* 过滤组织架构树仅保留顶层目标ID节点其所有祖先节点和子孙节点
* 顶层目标ID目标数组中无其他ID是其祖先的ID子节点ID会被自动忽略
* @param {Array} originalTree - 原始组织架构树形结构顶层为数组
* @param {Array<number>} targetIds - 目标节点ID数组可能包含子节点ID
* @returns {Array} 过滤后的组织架构树
*/
function filterOrganizationTree(originalTree: orgInfo[], targetIds: any) {
// 1. ID便/
const nodeMap = new Map();
buildNodeMap(originalTree, nodeMap);
// 2. IDIDIDID
const topTargetIds = filterChildTargetIds(targetIds, nodeMap);
if (topTargetIds.length === 0) {
console.warn("警告:所有目标ID无效或均为其他目标ID的子节点,返回空树");
return [];
}
// 3. IDID + ID + ID
const keepIds = collectKeepIds(topTargetIds, nodeMap);
// 4.
const filteredTree = filterTreeNodes(originalTree, keepIds);
return filteredTree;
}
/**
* 辅助函数1遍历树形结构构建节点ID节点映射表
* @param {Array} nodes - 当前层级的节点数组顶层/子节点数组
* @param {Map} nodeMap - 待构建的节点映射表
*/
function buildNodeMap(nodes: any[], nodeMap: Map<any, any>) {
if (!nodes || !Array.isArray(nodes)) return;
nodes.forEach(node => {
nodeMap.set(node.id, node);
// childnull
buildNodeMap(Array.isArray(node.child) ? node.child : [], nodeMap);
});
}
/**
* 辅助函数2预处理目标ID数组过滤掉是其他目标ID子节点的ID
* @param {Array<number>} targetIds - 原始目标ID数组
* @param {Map} nodeMap - 节点映射表
* @returns {Array<number>} 仅包含顶层目标ID的数组无父节点在目标数组内
*/
function filterChildTargetIds(targetIds: any[], nodeMap: Map<any, any>) {
if (!targetIds || !Array.isArray(targetIds)) return [];
// ID
const validTargetIds = targetIds.filter(id => nodeMap.has(id));
if (validTargetIds.length <= 1) return validTargetIds; // 1ID
// IDIDID
return validTargetIds.filter(currentId => {
let parentId = nodeMap.get(currentId).superior;
// ID
while (parentId !== undefined && nodeMap.has(parentId)) {
if (validTargetIds.includes(parentId)) {
console.log(`提示:ID ${currentId} 是目标ID ${parentId} 的子节点,已忽略`);
return false; // ID
}
parentId = nodeMap.get(parentId).superior; //
}
return true; // ID
});
}
/**
* 辅助函数3收集所有需保留的节点ID顶层目标ID + 所有祖先ID + 所有子孙ID
* @param {Array<number>} topTargetIds - 预处理后的顶层目标ID数组
* @param {Map} nodeMap - 节点映射表
* @returns {Set<number>} 需保留的节点ID集合去重
*/
function collectKeepIds(topTargetIds: any[], nodeMap: Map<any, any>) {
const keepIds = new Set();
topTargetIds.forEach((targetId: unknown) => {
const targetNode = nodeMap.get(targetId);
// 1.
keepIds.add(targetId);
// 2.
let parentId = targetNode.superior;
while (parentId !== undefined && nodeMap.has(parentId)) {
keepIds.add(parentId);
parentId = nodeMap.get(parentId).superior;
}
// 3. ...
collectDescendants(targetNode.child, nodeMap, keepIds);
});
return keepIds;
}
/**
* 辅助函数4递归收集某个节点的所有子孙节点ID
* @param {Array} childNodes - 当前节点的子节点数组
* @param {Map} nodeMap - 节点映射表
* @param {Set<number>} keepIds - 需保留的ID集合
*/
function collectDescendants(childNodes: any[], nodeMap: any, keepIds: Set<unknown>) {
if (!Array.isArray(childNodes)) return;
childNodes.forEach(childNode => {
keepIds.add(childNode.id);
collectDescendants(childNode.child, nodeMap, keepIds); //
});
}
/**
* 辅助函数5递归过滤树形节点仅保留在keepIds中的节点
* @param {Array} nodes - 当前层级的节点数组
* @param {Set<number>} keepIds - 需保留的节点ID集合
* @returns {Array} 过滤后的节点数组
*/
function filterTreeNodes(nodes: any[], keepIds: Set<unknown>) {
if (!Array.isArray(nodes) || !keepIds) return [];
return nodes.reduce((filtered, node) => {
if (keepIds.has(node.id)) {
//
const clonedNode = { ...node };
clonedNode.child = filterTreeNodes(Array.isArray(clonedNode.child) ? clonedNode.child : [], keepIds);
filtered.push(clonedNode);
}
return filtered;
}, []);
}
const multiple = props.data.control.multiple == '1'
const orgTreeList = ref<orgInfo[]>(); const orgTreeList = ref<orgInfo[]>();
const orgTreeLoading = ref(false); // const orgTreeLoading = ref(false); //
const orgTreeProps ={ const orgTreeProps = {
children: 'child', children: 'child',
label: 'name', label: 'name',
} // } //
@ -44,12 +276,34 @@ const orgTreeProps ={
@ 时间: 2024-12-05 16:23:01 @ 时间: 2024-12-05 16:23:01
@ 功能: 获取行政组织 @ 功能: 获取行政组织
*/ */
function haveOrgTreeInfo(){ function haveOrgTreeInfo() {
orgTreeLoading.value = true; orgTreeLoading.value = true;
getOrgTreeList({"orgid": 309}) getOrgTreeList({ "orgid": 309 })
.then(({ data })=>{ .then(({ data }) => {
orgTreeList.value = data
}).finally(()=>{orgTreeLoading.value = false;})
//liwenxuan 250916 start
// IDIDididid
const targetIds = props.data.control.range
//console.log(targetIds)
if (targetIds && targetIds.length > 0) {
//
const filteredTree = filterOrganizationTree(data, targetIds);
orgTreeList.value = filteredTree
} else {
orgTreeList.value = data;
}
//liwenxuan 250916 end
//orgTreeList.value = data
}).finally(() => { orgTreeLoading.value = false; })
} }
onBeforeMount(() => { onBeforeMount(() => {
haveOrgTreeInfo(); haveOrgTreeInfo();
@ -62,26 +316,26 @@ interface TreeNodeInfo {
label: string; label: string;
} }
function treeData(node: orgInfo[],title: TreeNodeInfo[]){ function treeData(node: orgInfo[], title: TreeNodeInfo[]) {
// let title = new Array // let title = new Array
if(Array.isArray(node)){ if (Array.isArray(node)) {
node.forEach((item:TreeNode) => { node.forEach((item: TreeNode) => {
if(Array.isArray(title)){ if (Array.isArray(title)) {
title.push({ title.push({
value:item.id, value: item.id,
label:item.name label: item.name
}); });
}else{ } else {
title =[{ title = [{
value:item.id, value: item.id,
label:item.name label: item.name
}]; }];
} }
if (item.child) { if (item.child) {
if(Array.isArray(item.child)){ if (Array.isArray(item.child)) {
treeData(item.child,title) treeData(item.child, title)
// for (const child of item.children) { // for (const child of item.children) {
// treeData(child,title) // treeData(child,title)
// } // }
@ -93,13 +347,38 @@ function treeData(node: orgInfo[],title: TreeNodeInfo[]){
return title; return title;
} }
/** /**
@ 作者: 秦东 @ 作者: 秦东
@ 时间: 2025-06-10 11:13:06 @ 时间: 2025-06-10 11:13:06
@ 功能: 输出结果 @ 功能: 输出结果
*/ */
const valPrint = (val:any,orgList:orgInfo[]) => { const valPrint = (val: any, orgList: orgInfo[]) => {
let titlaAry = new Array let titlaAry = new Array
if(isArray(val)){
val.forEach((ele: any) => {
if (ele != "" && ele != undefined) {
let orgAry = treeData(orgList)
//console.log(val, "=======>orgList------------>", orgAry)
if (Array.isArray(orgAry)) {
//alert(1)
orgAry.forEach((item: orgInfo) => {
//console.log(item.value)
if (item.value == ele) {
titlaAry.push(item.label)
}
})
}
}
});
}else{
//console.log(orgList)
//
// console.log(val,"=======>orgList------------>",orgList) // console.log(val,"=======>orgList------------>",orgList)
// if(Array.isArray(orgList)){ // if(Array.isArray(orgList)){
// console.log(val,"=======>orgList-------2----->",orgList) // console.log(val,"=======>orgList-------2----->",orgList)
@ -111,36 +390,49 @@ const valPrint = (val:any,orgList:orgInfo[]) => {
// } // }
// }) // })
// } // }
if(val != "" && val != undefined){ if (val != "" && val != undefined) {
let orgAry = treeData(orgList) let orgAry = treeData(orgList)
console.log(val,"=======>orgList------------>",orgAry) console.log(val, "=======>orgList------------>", orgAry)
if(Array.isArray(orgAry)){ if (Array.isArray(orgAry)) {
orgAry.forEach((item:orgInfo) => { //alert(1)
if(item.value == val){ orgAry.forEach((item: orgInfo) => {
console.log(item.value)
if (item.value == val) {
titlaAry.push(item.label) titlaAry.push(item.label)
} }
}) })
} }
} }
}
return titlaAry.join("、") return titlaAry.join("、")
} }
</script> </script>
<template> <template><div></div>
<el-tree-select <el-tree-select
v-if="props.types!=3" v-if="props.types != 3"
v-bind="$props" v-bind="$props"
v-model="value" v-model="value"
v-loading="orgTreeLoading"
node-key="id" node-key="id"
:props="orgTreeProps" :props="orgTreeProps"
:data="orgTreeList" :data="orgTreeList"
check-strictly
:render-after-expand="false" :render-after-expand="false"
:show-checkbox="multiple"
:multiple="multiple"
:check-strictly="!multiple"
collapse-tags
collapse-tags-tooltip
:max-collapse-tags="2"
/> />
<el-text v-else class="wordColor">{{valPrint(value,orgTreeList)}}</el-text> <el-text v-else class="wordColor">{{ valPrint(value, orgTreeList) }}</el-text>
</template> </template>
<style lang='scss' scoped> <style lang='scss' scoped>
.wordColor{ .wordColor {
color:#000000; color: #000000;
} }
</style> </style>
Loading…
Cancel
Save