import type { Role } from './stage'; export interface VersionMember { name: string; role: Role; } export interface VersionMemberCandidate { id: string; name: string; departmentName?: string; } export const DEFAULT_VERSION_MEMBER_ROLE: Role = 'frontend'; export function inferVersionMemberRole( member: Partial, defaultRole: Role = DEFAULT_VERSION_MEMBER_ROLE, ): Role { const departmentName = member.departmentName?.toLowerCase() ?? ''; if (!departmentName) return defaultRole; if (departmentName.includes('产品') || departmentName.includes('product')) return 'product'; if (departmentName.includes('设计') || departmentName.includes('ui') || departmentName.includes('ux')) return 'ui'; if (departmentName.includes('测试') || departmentName.includes('质量') || departmentName.includes('qa')) return 'testing'; if (departmentName.includes('后端') || departmentName.includes('backend') || departmentName.includes('server')) return 'backend'; if (departmentName.includes('前端') || departmentName.includes('frontend') || departmentName.includes('web') || departmentName.includes('client')) return 'frontend'; return defaultRole; } export function filterVersionMemberCandidates( allMembers: VersionMemberCandidate[], currentMembers: VersionMember[], query: string, ): VersionMemberCandidate[] { const existingNames = new Set(currentMembers.map((member) => member.name)); const normalizedQuery = query.trim().toLowerCase(); return allMembers.filter((member) => { if (existingNames.has(member.name)) return false; if (!normalizedQuery) return true; return member.name.toLowerCase().includes(normalizedQuery); }); } export function addVersionMembers( currentMembers: VersionMember[], selectedNames: Iterable, allMembers: VersionMemberCandidate[], defaultRole: Role = DEFAULT_VERSION_MEMBER_ROLE, ): VersionMember[] { const existingNames = new Set(currentMembers.map((member) => member.name)); const selectedNameSet = new Set(selectedNames); const additions = allMembers .filter((member) => selectedNameSet.has(member.name) && !existingNames.has(member.name)) .map((member) => ({ name: member.name, role: inferVersionMemberRole(member, defaultRole) })); return [...currentMembers, ...additions]; } export function isVersionMemberName(currentUserName: string | undefined, versionMembers: VersionMember[]): boolean { const name = currentUserName?.trim(); if (!name) return false; return versionMembers.some((member) => member.name === name); } export function canWriteVersionWork(input: { role?: { permissions?: string[] } | null; permission: string; currentUserName?: string; versionMembers: VersionMember[]; readOnly?: boolean; }): boolean { if (input.readOnly) return false; const permissions = input.role?.permissions ?? []; if (permissions.includes('*')) return true; if (!permissions.includes(input.permission)) return false; return isVersionMemberName(input.currentUserName, input.versionMembers); }