91 lines
2.5 KiB
TypeScript
91 lines
2.5 KiB
TypeScript
|
|
import { computed, ref } from 'vue';
|
||
|
|
import { fetchGetUserManagementRelationTree } from '@/service/api';
|
||
|
|
import type { TreeCheckState } from './use-dept-source';
|
||
|
|
|
||
|
|
type ChainNode = Api.SystemManage.UserManagementRelationTreeRespVO;
|
||
|
|
|
||
|
|
export function useChainSource(selectedIds: () => Set<string>, disabledUserIdSet: () => Set<string>) {
|
||
|
|
const tree = ref<ChainNode[]>([]);
|
||
|
|
const loading = ref(false);
|
||
|
|
let loaded = false;
|
||
|
|
|
||
|
|
async function ensureLoaded() {
|
||
|
|
if (loaded) return;
|
||
|
|
loading.value = true;
|
||
|
|
try {
|
||
|
|
const { data } = await fetchGetUserManagementRelationTree({ fromUserIndex: false });
|
||
|
|
tree.value = data ?? [];
|
||
|
|
loaded = true;
|
||
|
|
} finally {
|
||
|
|
loading.value = false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function nodeKey(node: ChainNode): string {
|
||
|
|
return node.id ?? `chain_${node.userId}`;
|
||
|
|
}
|
||
|
|
|
||
|
|
function getNodeUserIds(node: ChainNode): string[] {
|
||
|
|
const ids = new Set<string>([String(node.userId)]);
|
||
|
|
if (node.children) {
|
||
|
|
for (const c of node.children) {
|
||
|
|
for (const id of getNodeUserIds(c)) ids.add(id);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return [...ids];
|
||
|
|
}
|
||
|
|
|
||
|
|
function getNodeCheckState(node: ChainNode): TreeCheckState {
|
||
|
|
const ids = getNodeUserIds(node).filter(id => !disabledUserIdSet().has(id));
|
||
|
|
if (!ids.length) return 'none';
|
||
|
|
const sel = ids.filter(id => selectedIds().has(id)).length;
|
||
|
|
if (sel === 0) return 'none';
|
||
|
|
if (sel === ids.length) return 'all';
|
||
|
|
return 'partial';
|
||
|
|
}
|
||
|
|
|
||
|
|
function findNode(list: ChainNode[], key: string): ChainNode | null {
|
||
|
|
for (const n of list) {
|
||
|
|
if (nodeKey(n) === key) return n;
|
||
|
|
if (n.children) {
|
||
|
|
const r = findNode(n.children, key);
|
||
|
|
if (r) return r;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
function matchKeyword(node: ChainNode, kw: string): boolean {
|
||
|
|
if (!kw) return true;
|
||
|
|
if (node.userNickname.toLowerCase().includes(kw)) return true;
|
||
|
|
if (node.children) return node.children.some(c => matchKeyword(c, kw));
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
function filterByKeyword(kw: string) {
|
||
|
|
const lower = kw.trim().toLowerCase();
|
||
|
|
if (!lower) return tree.value;
|
||
|
|
return tree.value.filter(n => matchKeyword(n, lower));
|
||
|
|
}
|
||
|
|
|
||
|
|
function getMetaText(node: ChainNode): string {
|
||
|
|
const total = getNodeUserIds(node).length;
|
||
|
|
return total > 1 ? `${total} 人` : '';
|
||
|
|
}
|
||
|
|
|
||
|
|
const treeProps = computed(() => ({ children: 'children', label: 'userNickname' }) as const);
|
||
|
|
|
||
|
|
return {
|
||
|
|
tree,
|
||
|
|
loading,
|
||
|
|
treeProps,
|
||
|
|
ensureLoaded,
|
||
|
|
getNodeUserIds,
|
||
|
|
getNodeCheckState,
|
||
|
|
findNode,
|
||
|
|
filterByKeyword,
|
||
|
|
getMetaText,
|
||
|
|
nodeKey
|
||
|
|
};
|
||
|
|
}
|