flnxi-Wu/lib/departments.ts
WuYongJie f646b71813
Some checks failed
CI Check / check (push) Has been cancelled
chore: 初始化本地仓库并同步最近改动
2025-11-18 17:50:16 +08:00

89 lines
2.4 KiB
TypeScript

const departmentCollator = new Intl.Collator('zh-Hans-CN-u-co-pinyin', {
numeric: true,
sensitivity: 'base',
})
export const sortDepartmentNames = (names: string[]): string[] => {
return [...names].sort((a, b) => departmentCollator.compare(a, b))
}
const normalizeName = (name?: string | null) => (name || '').trim()
export const buildDepartmentDescendants = (rawDepartments: Array<{ name: string }> | string[]) => {
const names =
Array.isArray(rawDepartments) && typeof rawDepartments[0] === 'string'
? (rawDepartments as string[])
: (rawDepartments as Array<{ name: string }>).map((dept) => dept.name)
const cleanedNames = names.map(normalizeName).filter(Boolean)
const childrenMap = new Map<string, string[]>()
const ensureNode = (name: string) => {
if (!childrenMap.has(name)) {
childrenMap.set(name, [])
}
}
cleanedNames.forEach((name) => ensureNode(name))
cleanedNames.forEach((name) => {
const lastDashIndex = name.lastIndexOf('-')
if (lastDashIndex > 0) {
const parent = name.substring(0, lastDashIndex)
ensureNode(parent)
childrenMap.get(parent)!.push(name)
}
})
childrenMap.forEach((children) =>
children.sort((a, b) => departmentCollator.compare(a, b))
)
const descendantMap = new Map<string, Set<string>>()
const visit = (name: string): Set<string> => {
if (descendantMap.has(name)) {
return descendantMap.get(name)!
}
const descendants = new Set<string>([name])
const children = childrenMap.get(name) || []
children.forEach((child) => {
visit(child).forEach((desc) => descendants.add(desc))
})
descendantMap.set(name, descendants)
return descendants
}
childrenMap.forEach((_children, name) => visit(name))
return descendantMap
}
export const isDepartmentWithinScope = (
scope: string | null | undefined,
target: string | null | undefined,
descendantMap?: Map<string, Set<string>>
): boolean => {
const normalizedScope = normalizeName(scope)
const normalizedTarget = normalizeName(target)
if (!normalizedScope || !normalizedTarget) {
return false
}
if (normalizedScope === normalizedTarget) {
return true
}
const scopedDescendants = descendantMap?.get(normalizedScope)
if (scopedDescendants?.has(normalizedTarget)) {
return true
}
return normalizedTarget.startsWith(`${normalizedScope}-`)
}
export const getDepartmentCollator = () => departmentCollator