Browse Source

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

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

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

@ -5,22 +5,23 @@
-->
<script lang='ts' setup>
import { getOrgTreeList } from '@/api/hr/org/index'
import { computed } from 'vue';
const props = withDefaults(
defineProps<{
defineProps<{
data: FormList
tablekey: any
numrun?: number
modelValue?: any //
tProp?: string // form-itemprop
types?:number
}>(),
{}
types?: number
}>(),
{}
)
const emits = defineEmits<{
(e: 'update:modelValue', numVal: any): void
(e: 'update:modelValue', numVal: any): void
}>()
const value = computed({
/* const value = computed({
get: () => {
if (props.modelValue != "" && props.modelValue != undefined){
return props.modelValue*1
@ -29,27 +30,280 @@ const value = computed({
}
},
set: (newVal: any) => {
console.log(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);
}
},
});
const orgTreeList = ref<orgInfo[]>();
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 orgTreeLoading = ref(false); //
const orgTreeProps ={
children: 'child',
label: 'name',
const orgTreeProps = {
children: 'child',
label: 'name',
} //
/**
@ 作者: 秦东
@ 时间: 2024-12-05 16:23:01
@ 功能: 获取行政组织
*/
function haveOrgTreeInfo(){
function haveOrgTreeInfo() {
orgTreeLoading.value = true;
getOrgTreeList({"orgid": 309})
.then(({ data })=>{
orgTreeList.value = data
}).finally(()=>{orgTreeLoading.value = false;})
getOrgTreeList({ "orgid": 309 })
.then(({ data }) => {
//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(() => {
haveOrgTreeInfo();
@ -58,30 +312,30 @@ onBeforeMount(() => {
interface TreeNodeInfo {
value: number;
label: string;
value: number;
label: string;
}
function treeData(node: orgInfo[],title: TreeNodeInfo[]){
function treeData(node: orgInfo[], title: TreeNodeInfo[]) {
// let title = new Array
if(Array.isArray(node)){
node.forEach((item:TreeNode) => {
if(Array.isArray(title)){
if (Array.isArray(node)) {
node.forEach((item: TreeNode) => {
if (Array.isArray(title)) {
title.push({
value:item.id,
label:item.name
value: item.id,
label: item.name
});
}else{
title =[{
value:item.id,
label:item.name
} else {
title = [{
value: item.id,
label: item.name
}];
}
if (item.child) {
if(Array.isArray(item.child)){
treeData(item.child,title)
if (Array.isArray(item.child)) {
treeData(item.child, title)
// for (const child of item.children) {
// treeData(child,title)
// }
@ -89,58 +343,96 @@ function treeData(node: orgInfo[],title: TreeNodeInfo[]){
}
})
}
return title;
}
/**
@ 作者: 秦东
@ 时间: 2025-06-10 11:13:06
@ 功能: 输出结果
*/
const valPrint = (val:any,orgList:orgInfo[]) => {
const valPrint = (val: any, orgList: orgInfo[]) => {
let titlaAry = new Array
// console.log(val,"=======>orgList------------>",orgList)
// if(Array.isArray(orgList)){
// console.log(val,"=======>orgList-------2----->",orgList)
// orgList.forEach((item: any) => {
// console.log(val,"=======>orgList-----3------->",item.id)
// if(item.id==val){
// console.log(val,"=======>orgList----1-------->",orgList)
// title = item.name
// }
// })
// }
if(val != "" && val != undefined){
let orgAry = treeData(orgList)
console.log(val,"=======>orgList------------>",orgAry)
if(Array.isArray(orgAry)){
orgAry.forEach((item:orgInfo) => {
if(item.value == val){
titlaAry.push(item.label)
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)
// if(Array.isArray(orgList)){
// console.log(val,"=======>orgList-------2----->",orgList)
// orgList.forEach((item: any) => {
// console.log(val,"=======>orgList-----3------->",item.id)
// if(item.id==val){
// console.log(val,"=======>orgList----1-------->",orgList)
// title = item.name
// }
// })
// }
if (val != "" && val != 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 == val) {
titlaAry.push(item.label)
}
})
}
}
}
return titlaAry.join("、")
}
</script>
<template>
<el-tree-select
v-if="props.types!=3"
v-bind="$props"
v-model="value"
v-loading="orgTreeLoading"
<template><div></div>
<el-tree-select
v-if="props.types != 3"
v-bind="$props"
v-model="value"
node-key="id"
:props="orgTreeProps"
:data="orgTreeList"
check-strictly
:render-after-expand="false"
:data="orgTreeList"
: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>
<style lang='scss' scoped>
.wordColor{
color:#000000;
<style lang='scss' scoped>
.wordColor {
color: #000000;
}
</style>
Loading…
Cancel
Save