fix(ai): 自动追加AI任务类型
This commit is contained in:
@@ -61,6 +61,33 @@ function slugifyCategoryName(name: string, index: number): string {
|
||||
);
|
||||
}
|
||||
|
||||
function normalizeCategoryNameForMatch(name: string): string {
|
||||
return name.trim().toLowerCase().replace(/\s+/g, '');
|
||||
}
|
||||
|
||||
function hashCategoryName(name: string): string {
|
||||
let hash = 0;
|
||||
for (let i = 0; i < name.length; i++) {
|
||||
hash = (hash * 31 + name.charCodeAt(i)) | 0;
|
||||
}
|
||||
return Math.abs(hash).toString(36);
|
||||
}
|
||||
|
||||
function uniqueCategoryCode(base: string, categories: TaskCategory[]): string {
|
||||
if (!categories.some((category) => category.code === base)) return base;
|
||||
let suffix = 2;
|
||||
while (categories.some((category) => category.code === `${base}_${suffix}`)) suffix++;
|
||||
return `${base}_${suffix}`;
|
||||
}
|
||||
|
||||
function uniqueAiCategoryId(name: string, categories: TaskCategory[]): string {
|
||||
const base = `cat-ai-${hashCategoryName(name)}-${categories.length + 1}`;
|
||||
if (!categories.some((category) => category.id === base)) return base;
|
||||
let suffix = 2;
|
||||
while (categories.some((category) => category.id === `${base}-${suffix}`)) suffix++;
|
||||
return `${base}-${suffix}`;
|
||||
}
|
||||
|
||||
export function normalizeTaskCategory(category: Partial<TaskCategory> | undefined, index = 0): TaskCategory {
|
||||
const preset = PRESET_CATEGORIES.find((c) => c.id === category?.id);
|
||||
const name = category?.name || preset?.name || `分类 ${index + 1}`;
|
||||
@@ -103,3 +130,43 @@ export function getDefaultCategoryByGroup(categories: TaskCategory[], group: Cat
|
||||
export function resolveCategoryIdFromCode(categories: TaskCategory[], code: string | undefined, fallbackGroup: CategoryGroup): string {
|
||||
return findCategoryByCode(categories, code)?.id ?? getDefaultCategoryByGroup(categories, fallbackGroup).id;
|
||||
}
|
||||
|
||||
export function ensureTaskCategoryByName(
|
||||
categories: TaskCategory[],
|
||||
name: string | undefined,
|
||||
group: CategoryGroup,
|
||||
): { categories: TaskCategory[]; category: TaskCategory; created: boolean } {
|
||||
const normalizedCategories = normalizeTaskCategories(categories);
|
||||
const trimmedName = name?.trim() ?? '';
|
||||
if (!trimmedName) {
|
||||
return {
|
||||
categories: normalizedCategories,
|
||||
category: getDefaultCategoryByGroup(normalizedCategories, group),
|
||||
created: false,
|
||||
};
|
||||
}
|
||||
|
||||
const targetKey = normalizeCategoryNameForMatch(trimmedName);
|
||||
const existing = normalizedCategories.find(
|
||||
(category) => category.group === group && normalizeCategoryNameForMatch(category.name) === targetKey,
|
||||
);
|
||||
if (existing) {
|
||||
return { categories: normalizedCategories, category: existing, created: false };
|
||||
}
|
||||
|
||||
const codeBase = slugifyCategoryName(trimmedName, normalizedCategories.length);
|
||||
const category: TaskCategory = {
|
||||
id: uniqueAiCategoryId(trimmedName, normalizedCategories),
|
||||
code: uniqueCategoryCode(codeBase, normalizedCategories),
|
||||
name: trimmedName,
|
||||
group,
|
||||
sortOrder: Math.max(0, ...normalizedCategories.map((item) => item.sortOrder)) + 1,
|
||||
isSystem: false,
|
||||
};
|
||||
|
||||
return {
|
||||
categories: [...normalizedCategories, category],
|
||||
category,
|
||||
created: true,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user