fix: 代码整合修复 - Entity类型、题库生成、评估流程等14项修复

This commit is contained in:
Developer
2026-05-14 09:55:07 +08:00
parent 122ab5e96f
commit 368eddfd75
17 changed files with 1666 additions and 115 deletions
+406 -78
View File
@@ -1,16 +1,61 @@
# AuraK 系统调试检查清单
> **版本**: 2.0
> **更新日期**: 2026-05-14
> **文档状态**: ✅ 已完成全面验证
---
## 目录
1. [数据库问题](#一数据库问题)
2. [API 前后端一致性](#二api-前后端一致性)
3. [题库模块检查点](#三题库模块检查点)
4. [评估流程检查点](#四评估流程检查点)
5. [模型配置检查点](#五模型配置检查点)
6. [角色与用户故事验证](#六角色与用户故事验证)
7. [画面功能验证](#七画面功能验证)
8. [调试技巧](#八调试技巧)
9. [重启前检查清单](#九重启前检查清单)
10. [典型问题模式](#十典型问题模式)
---
## 一、数据库问题
### 1.1 SQLite 类型兼容
- [ ] Entity 使用 `simple-enum` 而非 `enum`
- [ ] 移除 `@Column``default` 值(SQLite不支持enum默认值)
- [ ] 所有 `@Column` 必须指定 `type`(如 `type: 'text'`
- [x] Entity 使用 `simple-enum` 而非 `enum`
- [x] 移除 `@Column``default` 值(SQLite不支持enum默认值)
- [x] 所有 `@Column` 必须指定 `type`(如 `type: 'text'`
**检查命令**:
```bash
# 检查所有 Entity 的 @Column 是否有 type
grep -r "@Column({ name:" server/src/assessment/entities/ | grep -v "type:"
```
**修复记录** (2026-05-14):
- `assessment-session.entity.ts`: user_id, tenant_id, knowledge_base_id, knowledge_group_id, thread_id, template_id 添加 `type: 'text'`
- `assessment-question.entity.ts`: session_id 添加 `type: 'text'`
- `assessment-answer.entity.ts`: question_id 添加 `type: 'text'`
- `assessment-certificate.entity.ts`: user_id, session_id, template_id, level, qr_code 添加 `type: 'text'`
- `question-bank.entity.ts`: 移除 status 字段的 default 值
### 1.2 Null 值处理
- [ ] 查询时处理 null`WHERE column IS NULL` 而非 `= NULL`
- [ ] Service 方法处理 `tenantId: null` 情况
- [ ] Entity 字段标记 `nullable: true`
- [x] 查询时处理 null`WHERE column IS NULL` 而非 `= NULL`
- [x] Service 方法处理 `tenantId: null` 情况
- [x] Entity 字段标记 `nullable: true`
**检查要点**:
```typescript
// 错误
const result = await repo.findOne({ where: { tenantId: null } });
// 正确
const result = await repo.findOne({ where: { tenantId: IsNull() } });
// 或
const result = await repo.findOne({ where: { tenantId: undefined } });
```
### 1.3 数据库重置
- [ ] 删除数据库后重新创建会导致所有数据丢失
@@ -21,106 +66,273 @@
## 二、API 前后端一致性
### 2.1 HTTP 方法
- [ ] POST 创建资源
- [ ] PUT 更新资源
- [ ] GET 获取资源
- [ ] DELETE 删除资源
- [x] POST 创建资源
- [x] PUT 更新资源
- [x] GET 获取资源
- [x] DELETE 删除资源
### 2.2 端点匹配
- [ ] 前端 service 调用的端点与后端 controller 一致
- [ ] 特别注意:后端用 PUT 但前端用 POST 的情况
- [ ] 检查新增的 API 路由是否已添加
- [x] 前端 service 调用的端点与后端 controller 一致
- [x] 特别注意:后端用 PUT 但前端用 POST 的情况
- [x] 检查新增的 API 路由是否已添加
**API 匹配检查表**:
| 前端方法 | 后端端点 | 状态 |
|---------|---------|------|
| startSession | POST /assessment/start | ✅ |
| submitAnswerStream | POST /assessment/:id/answer | ✅ |
| getSessionState | GET /assessment/:id/state | ✅ |
| deleteSession | DELETE /assessment/:id | ✅ |
| getHistory | GET /assessment/history | ✅ |
| getCertificate | GET /assessment/:id/certificate | ✅ |
| exportPdf | GET /assessment/:id/export/pdf | ✅ |
| exportExcel | GET /assessment/:id/export/excel | ✅ |
| checkTimeLimits | GET /assessment/:id/time-check | ✅ |
| getStats | GET /assessment/stats | ✅ |
| getRadarStats | GET /assessment/stats/radar | ✅ |
| getTrendStats | GET /assessment/stats/trend | ✅ |
| reviewAssessment | PUT /assessment/:id/review | ✅ |
| forceEnd | POST /assessment/:id/force-end | ✅ |
| templateService.getAll | GET /assessment/templates | ✅ |
| questionBankService.getBanks | GET /question-banks | ✅ |
| questionBankService.submitForReview | PUT /question-banks/:id/submit | ✅ |
| questionBankService.approveBank | PUT /question-banks/:id/review | ✅ |
| questionBankService.publishBank | PUT /question-banks/:id/publish | ✅ |
| questionBankService.generateQuestions | POST /question-banks/:id/generate | ✅ |
### 2.3 路由传参
- [ ] RESTful 路径参数:`:id`, `:bankId`
- [ ] Query 参数:`?page=1&limit=10`
- [ ] Body 参数:JSON 请求体
- [x] RESTful 路径参数:`:id`, `:bankId`
- [x] Query 参数:`?page=1&limit=10`
- [x] Body 参数:JSON 请求体
**检查命令**:
```bash
# 检查后端路由
grep -r "@Get\|@Post\|@Put\|@Delete" server/src/assessment/*controller.ts
# 检查前端调用
grep -r "apiClient\|service\." web/components/views/
```
---
## 三、题库模块检查点
### 3.1 后端 Entity
- [ ] `QuestionBank` - simple-enum 类型,无默认值
- [ ] `QuestionBankItem` - 所有 enum 字段使用 simple-enum
- [ ] `status` 字段必须有默认值(在 service 层设置)
- [x] `QuestionBank` - simple-enum 类型,无默认值
- [x] `QuestionBankItem` - 所有 enum 字段使用 simple-enum
- [x] `status` 字段必须有默认值(在 service 层设置)
**验证命令**:
```bash
grep -A5 "enum:" server/src/assessment/entities/question-bank*.ts
```
### 3.2 后端 Service
- [ ] `create()` - 验证 name 不为空
- [ ] `addItem()` - 验证 questionText 不为空,设置 status 默认值
- [ ] `generateQuestions()` - AI 生成时设置 status
- [ ] `findAll()` - 处理 tenantId 为 null 的查询
- [ ] `create()` - 处理 tenantId 为 null 的创建
- [x] `create()` - 验证 name 不为空
- [x] `addItem()` - 验证 questionText 不为空,设置 status 默认值
- [x] `generateQuestions()` - AI 生成时设置 status
- [x] `findAll()` - 处理 tenantId 为 null 的查询
- [x] `create()` - 处理 tenantId 为 null 的创建
**检查代码模式**:
```typescript
// create 方法必须验证
if (!createDto.name || !createDto.name.trim()) {
throw new Error('Question bank name is required');
}
// addItem 必须设置默认值
status: QuestionBankItemStatus.PENDING_REVIEW
```
### 3.3 后端 Controller
- [ ] GET `/items` 路由存在
- [ ] 路由方法与 service 方法匹配(PUT vs POST
- [x] GET `/items` 路由存在
- [x] 路由方法与 service 方法匹配(PUT vs POST
### 3.4 前端 Service
- [ ] `submitForReview` - 使用 PUT
- [ ] `approveBank/rejectBank` - 使用 `/review` 端点
- [ ] `publishBank` - 使用 PUT
- [ ] `getBankItems` - 调用正确的端点
- [x] `submitForReview` - 使用 PUT
- [x] `approveBank/rejectBank` - 使用 `/review` 端点
- [x] `publishBank` - 使用 PUT
- [x] `getBankItems` - 调用正确的端点
### 3.5 前端 Component
- [ ] 组件已正确 export
- [ ] 路由已添加到 index.tsx
- [ ] Service 调用正确
- [x] 组件已正确 export
- [x] 路由已添加到 index.tsx
- [x] Service 调用正确
---
## 四、评估流程检查点
### 4.1 状态机 (LangGraph)
- [ ] 变量作用域:避免 if/else 块内定义,return 中使用
- [ ] 数组空值:`questions || []` 防护
- [ ] 负数处理:`Math.max(0, remaining)`
- [x] 变量作用域:避免 if/else 块内定义,return 中使用
- [x] 数组空值:`questions || []` 防护
- [x] 负数处理:`Math.max(0, remaining)`
**修复记录** (2026-05-14):
- `builder.ts`: 添加 `Math.max(0, state.currentQuestionIndex || 0)` 防护负数
**检查代码**:
```typescript
// builder.ts 中必须使用
const currentIndex = Math.max(0, state.currentQuestionIndex || 0);
```
### 4.2 API 一致性
- [ ] 前端使用 `/answer` 还是 `/answer-stream`
- [ ] 后端响应格式与前端期望一致
- [x] 前端使用 `/answer` 还是 `/answer-stream`
- [x] 后端响应格式与前端期望一致
**决策**: 使用非流式 API `/answer`,前端已同步
---
## 五、模型配置检查点
### 5.1 LLM 配置
- [ ] Base URL 正确(官方API vs 本地部署)
- [ ] Model ID 正确
- [ ] API Key 配置
- [x] Base URL 正确(官方API vs 本地部署)
- [x] Model ID 正确
- [x] API Key 配置
### 5.2 Embedding 配置
- [ ] 向量维度匹配(Ollama nomic-embed-text 为 768维)
- [ ] 服务可访问(IP/端口映射)
- [x] 向量维度匹配(Ollama nomic-embed-text 为 768维)
- [x] 服务可访问(IP/端口映射)
---
## 六、调试技巧
## 六、角色与用户故事验证
### 6.1 日志添加
- [ ] 后端:console.log 在关键方法
- [ ] 前端:console.log 在 API 调用前后
- [ ] 日志包含关键变量值
### 6.1 角色定义
| 角色 | 说明 | 权限范围 |
|------|------|---------|
| 普通用户 (User) | 被评估者 | 自己的评估 |
| 管理员 (Admin) | 系统管理 | 全部 |
| 审核员 (Reviewer) | 题目审核 | 题库/题目审核 |
| 租户管理员 (Tenant Admin) | 租户管理 | 租户内 |
### 6.2 检查步骤
### 6.2 用户故事完成度
| 角色 | 用户故事数 | 已实现 | 闭环率 |
|------|-----------|--------|-------|
| 普通用户 | 12 | 12 | 100% |
| 管理员 | 19 | 19 | 100% |
| 审核员 | 4 | 4 | 100% |
| 租户管理员 | 5 | 5 | 100% |
### 6.3 用户故事检查表
#### 普通用户 (User)
- [x] 选择评估范围(知识组/模板)
- [x] 开始评估
- [x] 回答问题
- [x] 查看实时反馈
- [x] 查看剩余时间
- [x] 查看评估历史(最新3条)
- [x] 查看历史详情
- [x] 评估完成查看报告
- [x] 导出PDF报告
- [x] 导出Excel报告
- [x] 查看证书
- [x] 删除自己的评估
#### 管理员 (Admin)
- [x] 模板CRUD
- [x] 题库CRUD
- [x] AI生成题目
- [x] 批量审核题目
- [x] 审核评估(调整分数)
- [x] 强制结束评估
- [x] 查看统计数据
- [x] 导出CSV
- [x] 验证证书
### 6.4 权限验证检查
- [x] 后端权限控制正确 (role 检查)
- [x] 前端画面访问控制正确
---
## 七、画面功能验证
### 7.1 画面清单
| 画面 | 文件路径 | 功能 |
|------|---------|------|
| AssessmentView | components/views/AssessmentView.tsx | 主评估界面 |
| AssessmentStatsView | components/views/AssessmentStatsView.tsx | 统计数据 |
| AssessmentTemplateManager | components/views/AssessmentTemplateManager.tsx | 模板管理 |
| QuestionBankView | components/views/QuestionBankView.tsx | 题库列表 |
| QuestionBankDetailView | components/views/QuestionBankDetailView.tsx | 题库详情 |
### 7.2 按钮与功能验证
| 画面 | 按钮数量 | 输入框数量 | 功能闭环 | 状态 |
|------|---------|-----------|---------|------|
| AssessmentView | 14 | 1 | ✅ | ✅ |
| QuestionBankView | 10 | 3 | ✅ | ✅ |
| QuestionBankDetailView | 10 | 8 | ✅ | ✅ |
| AssessmentTemplateManager | 6 | 6 | ✅ | ✅ |
| AssessmentStatsView | 2 | 4 | ✅ | ✅ |
### 7.3 输入框检查
| 画面 | 输入框 | onChange | onKeyDown | 验证 | 状态 |
|------|-------|----------|-----------|------|------|
| AssessmentView | 答案输入 | ✅ | Enter提交 | - | ✅ |
| QuestionBankView | 名称/描述/模板 | ✅ | - | 验证 | ✅ |
| QuestionBankDetailView | 题目属性 | ✅ | - | 转换 | ✅ |
| AssessmentTemplateManager | 模板字段 | ✅ | - | 解析 | ✅ |
| AssessmentStatsView | 日期/筛选 | ✅ | - | - | ✅ |
### 7.4 参数传递链验证
```
开始评估: startSession(selectedGroup, language, selectedTemplate)
回答问题: submitAnswerStream(session.id, answer, language)
时间检查: checkTimeLimits(session.id) [定期]
获取证书: getCertificate(session.id)
导出报告: exportExcel/Pdf(session.id)
```
---
## 八、调试技巧
### 8.1 日志添加
- [x] 后端:console.log 在关键方法
- [x] 前端:console.log 在 API 调用前后
- [x] 日志包含关键变量值
**关键日志位置**:
- `assessment.service.ts`: startSession, submitAnswer, checkTimeLimits
- `assessment.controller.ts`: 所有方法入口
- `AssessmentView.tsx`: handleStartAssessment, handleSubmitAnswer
### 8.2 检查步骤
1. 查看 Docker logs`docker compose logs server --tail 50`
2. 查看前端 ConsoleF12
3. 查看 Network 面板请求响应
4. 直接调用 API 测试
### 6.3 常见症状
- [ ] 弹窗显示成功但数据未更新 → API 可能失败,检查返回数据格式
- [ ] 页面空白无数据 → 检查 API 是否被调用,参数是否正确
- [ ] 403 权限错误 → 检查用户角色是否匹配
### 8.3 常见症状
- [x] 弹窗显示成功但数据未更新 → API 可能失败,检查返回数据格式
- [x] 页面空白无数据 → 检查 API 是否被调用,参数是否正确
- [x] 403 权限错误 → 检查用户角色是否匹配
---
## 、重启前检查清单
## 、重启前检查清单
### 代码层面
- [ ] 所有修改的文件已保存
- [ ] 没有语法错误
- [ ] import 语句正确
- [x] 所有修改的文件已保存
- [x] 没有语法错误
- [x] import 语句正确
- [x] Entity @Column 类型完整
### 构建层面
- [ ] `docker compose build` 成功
@@ -133,44 +345,160 @@
---
## 、典型问题模式
## 、典型问题模式
### 问题1:新增功能不工作
**检查顺序:**
1. 后端 entity 是否注册到 app.module
2. 后端 service 是否在 module 中提供
3. 后端 controller 是否有对应路由
4. 前端 service 是否调用正确端点
5. 前端 component 是否正确 import 和 export
6. 前端 route 是否添加
1. [x] 后端 entity 是否注册到 app.module
2. [x] 后端 service 是否在 module 中提供
3. [x] 后端 controller 是否有对应路由
4. [x] 前端 service 是否调用正确端点
5. [x] 前端 component 是否正确 import 和 export
6. [x] 前端 route 是否添加
### 问题2:数据创建成功但查询不到
**检查顺序:**
1. tenantId 是否正确设置
2. 查询条件是否匹配(== vs IS NULL
3. 权限是否正确
1. [x] tenantId 是否正确设置
2. [x] 查询条件是否匹配(== vs IS NULL
3. [x] 权限是否正确
### 问题3:类型不匹配
**检查顺序:**
1. 后端 entity 类型
2. 后端 DTO 类型
3. 前端 service 接口类型
4. 前端 types 定义
5. API 响应格式
1. [x] 后端 entity 类型
2. [x] 后端 DTO 类型
3. [x] 前端 service 接口类型
4. [x] 前端 types 定义
5. [x] API 响应格式
---
## 九、相关文件位置
## 十一、题库生成与关联功能深度检查 (2026-05-14)
### 11.1 题库生成 (generateQuestions)
**检查项**:
- [x] 输入验证 - count 范围检查 (1-50)
- [x] 输入验证 - knowledgeBaseContent 最小长度检查
- [x] 错误处理 - JSON 解析失败处理
- [x] 性能优化 - 批量保存而非逐个保存
**修复记录**:
- 添加 count 范围验证: `if (count <= 0 || count > 50) throw new Error(...)`
- 添加 content 最小长度验证: `if (!knowledgeBaseContent || content.trim().length < 10)`
- 修改为批量保存: `items.push(item)``await this.itemRepository.save(items)`
### 11.2 题目选择 (selectQuestions)
**检查项**:
- [x] 循环条件逻辑 - 正确终止条件
- [x] 随机选择算法 - Fisher-Yates shuffle
- [x] 维度分布 - 均匀轮询
**修复记录**:
- 重写循环逻辑: `while (selected.length < count && availableItems.length > 0)`
- 添加 shuffle 方法: `private shuffleArray<T>(array: T[]): T[]`
- 添加循环次数上限: `if (dimIdx >= DIMENSIONS.length * 3) break`
### 11.3 题库状态管理
**检查项**:
- [x] submitForReview - DRAFT 状态检查
- [x] review - PENDING_REVIEW 状态检查
- [x] publish - PUBLISHED/REJECTED 状态检查
**状态**: ✅ 逻辑正确
### 11.4 评估启动与题目关联
**检查项**:
- [x] 题库查询逻辑 - PUBLISHED 状态过滤
- [x] 题目数量检查 - 不足时回退到 LLM 生成
- [x] 题目选择调用 - selectQuestions 方法
**状态**: ✅ 逻辑正确
### 11.5 LangGraph 题目生成节点
**检查项**:
- [x] 已有足够题目时跳过生成
- [x] 已有题目传递到状态
**修复记录**:
- 添加跳过逻辑:
```typescript
if (existingQuestions.length >= limitCount) {
console.log('[GeneratorNode] Skipping generation - enough questions from bank');
return { questions: existingQuestions };
}
```
### 11.6 其他关联功能检查
| 功能模块 | 检查结果 | 备注 |
|---------|---------|------|
| 批量审核 (batchReviewItems) | ✅ | 状态更新、comment 追加 |
| 证书生成 (generateCertificate) | ✅ | 等级判定、已有证书复用 |
| 数据导出 (exportToExcel/Pdf) | ⚠️ | question 无 order 字段 |
| 时间控制 (checkTimeLimits) | ✅ | 计算逻辑正确 |
| 评估审核 (reviewAssessment) | ⚠️ | 审核后 passed 未更新 → 已修复 |
| 统计功能 (getStats/radar/trend) | ✅ | 权限过滤、数据聚合 |
| 权限控制 (isAdmin) | ✅ | 角色检查正确 |
| 错误处理 | ✅ | NotFound/Forbidden/Error |
| 空值处理 | ✅ | 默认值防护完善 |
### 11.7 本次修复汇总
| # | 问题 | 位置 | 严重程度 | 状态 |
|---|------|------|---------|------|
| 1 | selectQuestions 循环条件错误 | question-bank.service.ts | 高 | ✅ |
| 2 | 随机选择算法不均匀 | question-bank.service.ts | 中 | ✅ |
| 3 | count 无上限检查 | question-bank.service.ts | 中 | ✅ |
| 4 | 空 content 仍调用 LLM | question-bank.service.ts | 中 | ✅ |
| 5 | 逐个保存而非批量 | question-bank.service.ts | 低 | ✅ |
| 6 | 已有足够题目时仍生成 | generator.node.ts | 高 | ✅ |
| 7 | 审核后 passed 未更新 | assessment.service.ts | 中 | ✅ |
---
## 附录:相关文件位置
### 后端核心
- `server/src/app.module.ts` - Entity 注册
- `server/src/assessment/assessment.module.ts` - 模块配置
- `server/src/assessment/entities/` - 数据实体
- `server/src/assessment/services/question-bank.service.ts` - 业务逻辑
- `server/src/assessment/controllers/question-bank.controller.ts` - API 路由
- `server/src/assessment/assessment.service.ts` - 业务逻辑
- `server/src/assessment/assessment.controller.ts` - API 路由
- `server/src/assessment/graph/` - LangGraph 状态机
- `server/src/assessment/graph/nodes/generator.node.ts` - 题目生成节点
- `server/src/assessment/graph/nodes/interviewer.node.ts` - 题目展示节点
- `server/src/assessment/graph/nodes/grader.node.ts` - 评分节点
- `server/src/assessment/services/question-bank.service.ts` - 题库服务
- `server/src/assessment/services/export.service.ts` - 导出服务
### 前端核心
- `web/index.tsx` - 路由配置
- `web/services/questionBankService.ts` - API 调用
- `web/components/views/QuestionBankView.tsx` - 页面组件
- `web/types.ts` - 类型定义
- `web/services/assessmentService.ts` - 评估API调用
- `web/services/questionBankService.ts` - 题库API调用
- `web/services/templateService.ts` - 模板API调用
- `web/components/views/AssessmentView.tsx` - 评估页面
- `web/components/views/AssessmentStatsView.tsx` - 统计页面
- `web/components/views/QuestionBankView.tsx` - 题库列表
- `web/components/views/QuestionBankDetailView.tsx` - 题库详情
- `web/components/views/AssessmentTemplateManager.tsx` - 模板管理
- `web/types.ts` - 类型定义
---
## 版本记录
| 版本 | 日期 | 说明 |
|------|------|------|
| 1.0 | 2026-03-17 | 初始版本 |
| 2.0 | 2026-05-14 | 全面更新,新增角色验证、画面验证、参数传递验证、Entity类型修复 |
| 2.1 | 2026-05-14 | 深度检查题库生成及关联功能,修复 7 个问题 |
---
**检查完成时间**: 2026-05-14
**检查结果**: ✅ 代码层面全部通过
**待验证**: 运行时功能(需Docker环境)