refactor(components): 更新标签组件类型定义和数据处理逻辑

- 修改 Tag 接口定义,将 id 和 color 字段改为可选类型
- 更新 onAddTag 回调函数参数类型,从对象改为字符串
- 在 AddTagPopover 组件中添加 useCallback 优化数据获取逻辑
- 调整标签去重逻辑,支持 id 或 name 任一字段匹配
- 更新 DetailHeader 组件的数据类型定义和泛型约束
- 添加 parseMetadata 工具函数用于解析元数据
- 实现 isAnnotationItem 函数判断注释类型数据
- 优化知识库详情页的标签处理和数据类型转换
This commit is contained in:
2026-02-02 22:15:16 +08:00
parent cac53d7aac
commit e71116d117
3 changed files with 79 additions and 45 deletions

View File

@@ -22,44 +22,51 @@ interface OperationItem {
danger?: boolean;
}
interface TagConfig {
showAdd: boolean;
tags: { id: number; name: string; color: string }[];
onFetchTags?: () => Promise<{
data: { id: number; name: string; color: string }[];
}>;
onAddTag?: (tag: { id: number; name: string; color: string }) => void;
onCreateAndTag?: (tagName: string) => void;
}
interface DetailHeaderProps<T> {
data: T;
statistics: StatisticItem[];
operations: OperationItem[];
tagConfig?: TagConfig;
}
function DetailHeader<T>({
data = {} as T,
statistics,
operations,
tagConfig,
}: DetailHeaderProps<T>): React.ReactNode {
interface TagConfig {
showAdd: boolean;
tags: { id?: string | number; name: string; color?: string }[];
onFetchTags?: () => Promise<{ id?: string | number; name: string; color?: string }[]>;
onAddTag?: (tagName: string) => void;
onCreateAndTag?: (tagName: string) => void;
}
interface DetailHeaderData {
name?: string;
description?: string;
status?: { color?: string; icon?: React.ReactNode; label?: string };
tags?: { id?: string | number; name?: string }[];
icon?: React.ReactNode;
iconColor?: string;
}
interface DetailHeaderProps<T extends DetailHeaderData> {
data: T;
statistics: StatisticItem[];
operations: OperationItem[];
tagConfig?: TagConfig;
}
function DetailHeader<T extends DetailHeaderData>({
data = {} as T,
statistics,
operations,
tagConfig,
}: DetailHeaderProps<T>): React.ReactNode {
return (
<Card>
<div className="flex items-start justify-between">
<div className="flex items-start gap-4 flex-1">
<div
className={`w-16 h-16 text-white rounded-lg flex-center shadow-lg ${
(data as any)?.iconColor
? ""
: "bg-gradient-to-br from-sky-300 to-blue-500 text-white"
}`}
style={(data as any)?.iconColor ? { backgroundColor: (data as any).iconColor } : undefined}
>
{<div className="w-[2.8rem] h-[2.8rem] text-gray-50">{(data as any)?.icon}</div> || (
<Database className="w-8 h-8 text-white" />
)}
</div>
data?.iconColor
? ""
: "bg-gradient-to-br from-sky-300 to-blue-500 text-white"
}`}
style={data?.iconColor ? { backgroundColor: data.iconColor } : undefined}
>
{<div className="w-[2.8rem] h-[2.8rem] text-gray-50">{data?.icon}</div> || (
<Database className="w-8 h-8 text-white" />
)}
</div>
<div className="flex-1">
<div className="flex items-center gap-3 mb-2">
<h1 className="text-lg font-bold text-gray-900">{data?.name}</h1>