码桶
发现社区成员的开源项目
slug-generator.ts2.6 KB
// 靓号规则:
// 1. 禁止出现数字 '4'
// 2. 全局唯一
// 3. 优先使用连号/豹子号/重复规律号,如 123-123-123, 111-111-111, 888-888-888 等
const ALLOWED_DIGITS = ['0', '1', '2', '3', '5', '6', '7', '8', '9'];
// 预定义优质靓号池 (不含 4)
const PREFERRED_PATTERNS = [
'888-888-888',
'666-666-666',
'999-999-999',
'123-123-123',
'555-555-555',
'333-333-333',
'111-111-111',
'777-777-777',
'520-520-520',
'135-135-135',
'168-168-168',
'888-666-999',
'168-666-168',
'123-567-890',
'666-888-666',
'888-999-888',
'112-233-556',
'888-888-666',
'666-666-888',
'999-888-666',
'888-555-888',
];
// 规则辅助:判断是否包含4
export function containsFour(slug: string): boolean {
return slug.includes('4');
}
// 动态生成符合格式无4的随机靓号 xxx-xxx-xxx
export function generateRandomNiceSlug(): string {
const getRandomGroup = (len: number = 3) => {
let res = '';
for (let i = 0; i < len; i++) {
const idx = Math.floor(Math.random() * ALLOWED_DIGITS.length);
res += ALLOWED_DIGITS[idx];
}
return res;
};
// 随机挑选模式:连号组、重复组、或三段式
const randType = Math.random();
if (randType < 0.3) {
// 豹子重复组 (如 888-555-888)
const d1 = ALLOWED_DIGITS[Math.floor(Math.random() * ALLOWED_DIGITS.length)];
const d2 = ALLOWED_DIGITS[Math.floor(Math.random() * ALLOWED_DIGITS.length)];
return `${d1}${d1}${d1}-${d2}${d2}${d2}-${d1}${d1}${d1}`;
} else if (randType < 0.6) {
// AB-AB-AB 组 (如 12-12-12-12 或 18-18-18)
const g = getRandomGroup(2);
return `${g}${g[0]}-${g}${g[1]}-${g}${g[0]}`;
}
return `${getRandomGroup()}-${getRandomGroup()}-${getRandomGroup()}`;
}
export async function generateUniqueNiceSlug(existingSlugsCheck: (slug: string) => Promise<boolean>): Promise<string> {
// 1. 尝试优质靓号池
for (const preferred of PREFERRED_PATTERNS) {
if (!containsFour(preferred)) {
const exists = await existingSlugsCheck(preferred);
if (!exists) {
return preferred;
}
}
}
// 2. 尝试生成重复型/规则型靓号
for (let i = 0; i < 100; i++) {
const candidate = generateRandomNiceSlug();
if (!containsFour(candidate)) {
const exists = await existingSlugsCheck(candidate);
if (!exists) {
return candidate;
}
}
}
// 3. 兜底逻辑
let fallback = `${Date.now()}`.replace(/4/g, '5').slice(-9);
let formatted = `${fallback.slice(0, 3)}-${fallback.slice(3, 6)}-${fallback.slice(6, 9)}`;
return formatted;
}