fix(data): 清理旧数据并保护服务端写入
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import { pinyin } from 'pinyin-pro';
|
||||
|
||||
export interface Department {
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -9,6 +11,7 @@ export interface Department {
|
||||
export interface Member {
|
||||
id: string;
|
||||
name: string;
|
||||
username?: string;
|
||||
departmentId: string;
|
||||
roleId: string;
|
||||
phone: string;
|
||||
@@ -65,3 +68,62 @@ export function maskPhone(phone: string): string {
|
||||
if (!phone || phone.length < 7) return phone;
|
||||
return phone.slice(0, 3) + '****' + phone.slice(7);
|
||||
}
|
||||
|
||||
export function normalizeUsername(username: string | undefined | null): string {
|
||||
return (username ?? '').trim().replace(/\s+/g, '').toLowerCase();
|
||||
}
|
||||
|
||||
function nameToUsernameBase(name: string): string {
|
||||
const raw = name.trim();
|
||||
if (!raw) return 'USER';
|
||||
const letters = pinyin(raw, { toneType: 'none', type: 'array' })
|
||||
.join('')
|
||||
.replace(/[^a-zA-Z0-9]/g, '')
|
||||
.toLowerCase();
|
||||
return letters || 'USER';
|
||||
}
|
||||
|
||||
function duplicateSuffix(attempt: number): string {
|
||||
return attempt === 1 ? '1' : `${'0'.repeat(attempt - 1)}1`;
|
||||
}
|
||||
|
||||
function uniqueUsernameFromBase(base: string, existingUsernames: Iterable<string>): string {
|
||||
const normalizedBase = normalizeUsername(base) || 'USER';
|
||||
const used = new Set(Array.from(existingUsernames, normalizeUsername).filter(Boolean));
|
||||
if (!used.has(normalizedBase)) return normalizedBase;
|
||||
|
||||
for (let attempt = 1; attempt < 1000; attempt += 1) {
|
||||
const candidate = `${normalizedBase}${duplicateSuffix(attempt)}`;
|
||||
if (!used.has(candidate)) return candidate;
|
||||
}
|
||||
|
||||
return `${normalizedBase}${Date.now()}`;
|
||||
}
|
||||
|
||||
export function generateUsernameFromName(
|
||||
name: string,
|
||||
existingUsernames: Iterable<string>,
|
||||
currentUsername?: string,
|
||||
): string {
|
||||
const normalizedCurrent = normalizeUsername(currentUsername);
|
||||
if (normalizedCurrent) return normalizedCurrent;
|
||||
return uniqueUsernameFromBase(nameToUsernameBase(name), existingUsernames);
|
||||
}
|
||||
|
||||
export function ensureMemberUsernames(members: Member[]): { members: Member[]; changed: boolean } {
|
||||
const used = new Set<string>();
|
||||
let changed = false;
|
||||
const normalizedMembers = members.map((member) => {
|
||||
const requested = normalizeUsername(member.username);
|
||||
const username = requested
|
||||
? uniqueUsernameFromBase(requested, used)
|
||||
: generateUsernameFromName(member.name, used);
|
||||
|
||||
used.add(username);
|
||||
if (member.username === username) return member;
|
||||
changed = true;
|
||||
return { ...member, username };
|
||||
});
|
||||
|
||||
return { members: normalizedMembers, changed };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user