feat: 实现阶段二实体体系——AI预处理真实化+实体CRUD+审核归一化

- 新增 entities 数据表(含迁移)、Entity 类型、DAO 层完整 CRUD
- AI 预处理管道接入真实模型(generateText),输出结构化 JSON(摘要+规范化内容+候选实体)
- 模板接口重构为 {systemPrompt, buildUserPrompt, parseOutput},general/meeting 模板真实化
- 新增 5 个实体路由端点 + 实体管理前端页面(列表/详情/编辑弹窗)
- 审核面板增强:展示 AI 预处理结构化结果+候选实体归一化面板(合并/新建/选择/放弃)
- 素材通过时根据用户确认的候选实体写入 entities 表
- 工作台菜单新增"实体"入口
- 新增 entities DAO 测试(16)、processor 测试(11)、路由测试(8),服务端 367 测试全部通过
- TypeScript 0 错误
This commit is contained in:
2026-06-08 18:49:30 +08:00
parent 034496e946
commit 12edf0b545
36 changed files with 2109 additions and 62 deletions

View File

@@ -55,10 +55,77 @@ export interface CreateProviderRequest {
type: ProviderType;
}
// ==========================================
// 在此定义你的业务类型
// 前后端共享的类型都放在这个文件中
// ==========================================
export interface ApproveMaterialRequest {
entityConfirmations?: EntityConfirmation[];
}
export interface CandidateEntity {
context: string;
matchedEntityId: null | string;
name: string;
type: EntityType;
}
export interface CreateEntityRequest {
aliases?: string[];
description?: string;
name: string;
type: EntityType;
}
export interface Entity {
aliases: string[];
createdAt: string;
description: string;
id: string;
name: string;
projectId: string;
type: EntityType;
updatedAt: string;
}
export interface EntityConfirmation {
action: "create" | "discard" | "merge" | "select";
candidateIndex: number;
targetEntityId?: string;
}
export interface EntityListResponse {
items: Entity[];
page: number;
pageSize: number;
total: number;
}
export interface EntityResponse {
entity: Entity;
}
export const ENTITY_TYPES = [
"person",
"organization",
"system",
"feature",
"requirement",
"issue",
"term",
"other",
] as const;
export type EntityType = (typeof ENTITY_TYPES)[number];
export interface ProcessingResult {
candidateEntities: CandidateEntity[];
normalizedContent: string;
summary: string;
}
export interface UpdateEntityRequest {
aliases?: string[];
description?: string;
name?: string;
type?: EntityType;
}
export interface ListSortParams {
sortBy?: string;