Files
aurak/docs/plans/2026-04-20-assessment-system-complete-plan.md
Developer 0a9588abb7 feat: implement QuestionBank CRUD with pagination and template query
- Add pagination support to findAll (page, limit query params)
- Add findByTemplateId method to service
- Add GET /by-template/:templateId endpoint to controller
- Service already includes CRUD for QuestionBank and QuestionBankItem
2026-04-23 17:19:11 +08:00

19 KiB
Raw Permalink Blame History

AuraK 评估系统完整实施计划

For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

Goal: 构建完整的AI人才评估系统,包含题库管理、维度均衡抽取、审核流程、评估统计

Architecture:

  • 题库通过模板间接关联知识库分组
  • 评估时从题库维度均衡抽取,不足时实时生成备用
  • 管理员通过独立页面管理题库和查看统计

Tech Stack: NestJS + TypeORM + LangGraph + React + TypeScript


一、问题与方案对照表

# 待修复问题 解决思路 对应Task
1 评分计算错误 已修复
2 题目维度分配不均 已修复
3 多轮对话中断 已修复
4 计数器显示错误 已修复
5 历史问答查询 统计页面 Task 4
6 知识覆盖度来源 用户不 care -
7 实时反馈无内容 用户确认已有内容 -
8 预生成题目功能 题库+抽取 Task 1,2,3
9 题目生成不稳定 题库前置 Task 1,7
10 题目来源不是知识库 题库+范围控制 Task 1,3
11 选择题实际无选项 题库管理 Task 1,5

二、系统架构

2.1 数据层级

KnowledgeGroup(知识库分组)
    ↓
AssessmentTemplate(模板)→ 题目数量、知识库配置
    ↓
QuestionBank(题库)→ 审核状态
    ↓
QuestionBankItem(题目)→ 维度/难度/答案
    ↓
评估抽取使用

2.2 评估流程

开始评估
    ↓
1. 加载模板配置(题目数量、维度配置)
    ↓
2. 检查已发布题库题目数量
    ↓
   充足 → 维度均衡随机抽取 → 进入答题
   不足 → 实时生成题目(备用) → 进入答题
    ↓
3. 用户答题 → 即时评分 → 实时反馈
    ↓
4. 追问(如Grader判断需要)
    ↓
5. 答题完成 → 生成报告 + 记录统计

三、数据模型

3.1 QuestionBank(题库)

// server/src/assessment/entities/question-bank.entity.ts
@Entity('question_banks')
export class QuestionBank {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column({ name: 'template_id' })
  templateId: string;

  @ManyToOne(() => AssessmentTemplate)
  @JoinColumn({ name: 'template_id' })
  template: AssessmentTemplate;

  @Column({ name: 'name' })
  name: string;                    // 题库名称

  @Column({ type: 'text', description: '题库描述' })
  description: string;

  @Column({ type: 'enum', enum: QuestionBankStatus, default: QuestionBankStatus.DRAFT })
  status: QuestionBankStatus;    // DRAFT | PENDING_REVIEW | PUBLISHED

  @Column({ name: 'created_by' })
  createdBy: string;

  @Column({ name: 'reviewed_by', nullable: true })
  reviewedBy: string;

  @Column({ name: 'reviewed_at', nullable: true })
  reviewedAt: Date;

  @Column({ name: 'review_comment', nullable: true })
  reviewComment: string;          // 审核意见

  @OneToMany(() => QuestionBankItem, item => item.bank)
  items: QuestionBankItem[];

  @CreateDateColumn({ name: 'created_at' })
  createdAt: Date;

  @UpdateDateColumn({ name: 'updated_at' })
  updatedAt: Date;
}

enum QuestionBankStatus {
  DRAFT = 'DRAFT',                  // 草稿
  PENDING_REVIEW = 'PENDING_REVIEW',   // 待审核
  PUBLISHED = 'PUBLISHED',           // 已发布
  REJECTED = 'REJECTED',            // 审核拒绝
}

3.2 QuestionBankItem(题目)

// server/src/assessment/entities/question-bank-item.entity.ts
@Entity('question_bank_items')
export class QuestionBankItem {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column({ name: 'bank_id' })
  bankId: string;

  @ManyToOne(() => QuestionBank, bank => bank.items)
  @JoinColumn({ name: 'bank_id' })
  bank: QuestionBank;

  @Column({ type: 'text', name: 'question_text' })
  questionText: string;

  @Column({ type: 'enum', enum: QuestionType })
  questionType: QuestionType;     // SHORT_ANSWER | MULTIPLE_CHOICE | TRUE_FALSE

  @Column({ type: 'simple-json', nullable: true })
  options: string[];               // 选择题选项 ["A. xxx", "B. xxx", ...]

  @Column({ type: 'text', nullable: true })
  correctAnswer: string;         // 正确答案

  @Column({ type: 'simple-json', name: 'key_points' })
  keyPoints: string[];           // 关键点 ["point1", "point2"]

  @Column({ type: 'enum', enum: QuestionDifficulty })
  difficulty: QuestionDifficulty; // STANDARD | ADVANCED | SPECIALIST

  @Column({ type: 'enum', enum: QuestionDimension })
  dimension: QuestionDimension;   // PROMPT | LLM | IDE | DEV_PATTERN | WORK_CAPABILITY

  @Column({ type: 'text', name: ' basis', nullable: true })
  basis: string;                 // 出题依据

  @Column({ name: 'created_by' })
  createdBy: string;

  @CreateDateColumn({ name: 'created_at' })
  createdAt: Date;
}

enum QuestionType {
  SHORT_ANSWER = 'SHORT_ANSWER',       // 简答题
  MULTIPLE_CHOICE = 'MULTIPLE_CHOICE', // 选择题
  TRUE_FALSE = 'TRUE_FALSE',          // 判断题
}

enum QuestionDifficulty {
  STANDARD = 'STANDARD',        // 标准
  ADVANCED = 'ADVANCED',         // 进阶
  SPECIALIST = 'SPECIALIST',    // 专家
}

enum QuestionDimension {
  PROMPT = 'PROMPT',            // 提示词
  LLM = 'LLM',                  // LLM原理
  IDE = 'IDE',                  // IDE协作
  DEV_PATTERN = 'DEV_PATTERN',  // 开发范式
  WORK_CAPABILITY = 'WORK_CAPABILITY', // 工作能力
}

3.3 评估统计

// API返回结构
interface AssessmentStats {
  // 统计卡片
  totalAttempts: number;       // 总考核次数
  highestScore: number;        // 最高分
  averageScore: number;       // 平均分
  completionRate: number;     // 完成率

  // 得分趋势(可选用于图表)
  scoreTrend: { date: string; score: number }[];

  // 历史记录
  recentRecords: {
    id: string;
    knowledgeBase: string;
    template: string;
    score: number;
    status: 'IN_PROGRESS' | 'COMPLETED';
    createdAt: string;
  }[];
}

四、API设计

4.1 题库管理API

// 题库CRUD
POST   /api/question-banks              // 创建题库
GET    /api/question-banks              // 列表(带分页)
GET    /api/question-banks/:id          // 详情(含题目)
PUT    /api/question-banks/:id         // 更新题库信息
DELETE /api/question-banks/:id         // 删除题库

// 题目管理
POST   /api/question-banks/:bankId/items     // 添加单题
PUT    /api/question-banks/:bankId/items/:id // 更新题目
DELETE /api/question-banks/:bankId/items/:id // 删除题目

// 批量操作
POST   /api/question-banks/:bankId/batch-add  // 批量添加题目(AI生成或Excel导入)
POST   /api/question-banks/:bankId/generate    // AI批量生成待审核

// 审核流程
PUT    /api/question-banks/:id/submit      // 提交审核(草稿→待审核)
PUT    /api/question-banks/:id/review     // 审核(通过/拒绝,附带意见)
PUT    /api/question-banks/:id/publish    // 发布(审核通过→已发布)
PUT    /api/question-banks/:id/unpublish   // 下架

// 模板关联
GET    /api/question-banks/by-template/:templateId  // 按模板查询题库

4.2 统计API

// 评估统计
GET    /api/assessment/stats                    // 当前用户统计
GET    /api/assessment/stats/admin              // 管理员统计(所有用户)
Query: startDate, endDate, templateId, knowledgeGroupId

五、前端页面设计

5.1 题库管理页面(QuestionBankView

┌──────────────────────────────────────────────────────────────────────────┐
│ 题库管理                                          [新建题库]      │
├────────────┬─────────────────────────────────────────────────────┤
│ 我的题库   │  筛选: [模板▼] [状态▼] [维度▼] [难度▼] [搜索...]   │
│           ├─────────────────────────────────────────────────────┤
│ □ AI开发  │  ┌────┬────────┬────────┬──────┬────────────┐      │
│ □ Python │  │选择│ 题目内容│ 题型   │ 维度 │ 难度 │ 操作│      │
│           │  ├────┼────────┼────────┼──────┼────────────┤      │
│           │  │ ○  │xxx     │ 简答   │ llm  │ 标准  │编辑│      │
│           │  │ ○  │xxx     │ 选择   │ ide  │ 进阶 │编辑│      │
│           │  │ ○  │xxx     │ 判断   │ Work │ 专家 │删除│      │
│           │  └────┴────────┴────────┴──────┴────────────┘      │
│           │                                             [批量导入] │
│           ├─────────────────────────────────────────────────────┤
│           │  [AI批量生成] [提交审核] [全选] [取消选择]          │
└────────────┴─────────────────────────────────────────────────────┘

5.2 题库详情/编辑面板

┌────────────────────────────────────┐
│ 编辑题目                    [保存]  │
├────────────────────────────────────┤
│ 题目内容                        │
│ ┌──────────────────────────────┐  │
│ │                            │  │
│ └────────────────────────────┘  │
│                                │
│ 题型: ●简答 ○选择 ○判断         │
│                                │
│ [选择题时显示]                  │
│ 选项:                           │
│ A. ___________________           │
│ B. ___________________           │
│ C. ___________________           │
│ D. ___________________           │
│                                │
│ 正确答案: ________________      │
│                                │
│ 关键点:                        │
│ _________________________       │
│ _________________________       │
│                                │
│ 维度: [prompt▼] 难度: [标准▼]   │
│                                │
│ 出题依据:                      │
│ _________________________       │
└────────────────────────────────────┘

5.3 统计页面(AssessmentStatsView

┌─────────────────────────────────────────────────────────────────┐
│ 评估统计                                              [导出]    │
├─────────────────────────────────────────────────────────────────┤
│ 筛选: [时间范围▼] [知识库▼] [重置]                       │
├─────────────────────────────────────────────────────────────────┤
│  总考核   │   最高分   │   平均分   │   完成率              │
│    15    │    9.2     │    7.8    │    80%               │
├─────────────────────────────────────────────────────────────────┤
│ 得分趋势(折线图 - 可选)                                  │
│     10 ____                                         │
│      8 ____▓▓▓____▓▓                               │
│      6 ____▓▓▓▓▓____▓▓▓▓___                         │
│      4 _______________________________________        │
│      2 ____________________________________________│
│         04/10  04/12  04/14  04/16  04/18          │
├─────────────────────────────────────────────────────────────────┤
│ 历史记录                                            │
│ 日期       知识库      模板       得分   状态   操作│
│ 04/18      AI开发    AI基础      9.2    完成  查看 │
│ 04/15      Python    编程基础   7.5    完成  查看 │
│ 04/12      AI开发    AI基础      8.1    完成  查看 │
│ 04/10      -        LLM原理    -     进行中 查看 │
└─────────────────────────────────────────────────────────────────┘

六、实施计划

Task 1: 题库管理功能(核心)

Files:

  • Create: server/src/assessment/entities/question-bank.entity.ts
  • Create: server/src/assessment/entities/question-bank-item.entity.ts
  • Create: server/src/assessment/question-bank.service.ts
  • Create: server/src/assessment/question-bank.controller.ts
  • Modify: server/src/assessment/assessment.module.ts (import)
  • Create: 迁移文件 add_question_banks.sql

实施步骤:

  1. 创建 QuestionBank 实体 + 迁移
  2. 创建 QuestionBankItem 实体 + 迁移
  3. 实现 QuestionBankServiceCRUD
  4. 实现 QuestionBankControllerAPI
  5. 注册模块

验收标准:

  • 可以创建题库
  • 可以添加/编辑/删除题目
  • 可以设置题目维度/难度/答案
  • 支持审核流程(草稿→待审核→发布)

Task 2: AI批量生成

目标: 调用AI批量生成题目,待人工审核

Files:

  • Modify: server/src/assessment/question-bank.service.ts (generate)
  • Modify: server/src/assessment/graph/nodes/generator.node.ts (复用)

实施步骤:

  1. 实现批量生成逻辑
  2. 调用generator node生成题目
  3. 保存为草稿状态
  4. 提供审核界面

验收标准:

  • 点击生成按钮,调用AI生成题目
  • 生成的题目进入草稿状态
  • 可以批量审核通过

Task 3: 题目抽取逻

目标: 评估时从题库维度均衡随机抽取

Files:

  • Modify: server/src/assessment/question-bank.service.ts (selectQuestions)

实施步骤:

  1. 实现维度均衡抽取算法
  2. 处理题目不足情况
  3. 单元测试

验收标准:

  • 抽取的题目维度大致均衡
  • 不重复抽取同一题目
  • 数量不足时有补充逻辑

Task 4: 评估接入题库

目标: 评估优先使用题库题目

Files:

  • Modify: server/src/assessment/assessment.service.ts (startSession)

实施步骤:

  1. 修改startSession逻辑
  2. 先查询题库
  3. 题库不足时使用实时生成
  4. 测试完整流程

验收标准:

  • 有题库时优先从题库抽取
  • 题库不足时使用实时生成
  • 两者都可正常工作

Task 5: 统计页面

目标: 独立统计页面

Files:

  • Create: server/src/assessment/assessment.controller.ts (stats API)
  • Create: web/src/services/assessmentStatsService.ts
  • Create: web/components/views/AssessmentStatsView.tsx
  • Modify: web/index.tsx (路由)
  • Modify: web/components/layouts/WorkspaceLayout.tsx (侧边栏)

验收标准:

  • 统计卡片显示正确
  • 支持时间筛选
  • 管理员可查看所有用户
  • 历史记录表格完整

Task 6: 选择题渲染

目标: 前端支持选择题渲染

Files:

  • Modify: web/components/views/AssessmentView.tsx

验收标准:

  • 选择题显示选项按钮
  • 点击选项提交答案

Task 7: 判断题渲染

目标: 前端支持判断题渲染

Files:

  • Modify: web/components/views/AssessmentView.tsx

验收标准:

  • 判断题显示True/False按钮
  • 点击提交答案

Task 8: 稳定性优化

目标: 提高AI生成稳定性

Files:

  • Modify: server/src/assessment/graph/nodes/generator.node.ts

实施步骤:

  1. 添加重试逻辑
  2. 优化prompt
  3. 错误处理

七、执行顺序

Task 1 (题库管理)
    ↓
Task 2 (AI批量生成)
    ↓
Task 3 (抽取逻辑)
    ↓
Task 4 (评估接入)
    ↓
Task 5 (统计页面)
    ↓
Task 6 (选择题)
    ↓
Task 7 (判断题)
    ↓
Task 8 (稳定性)

八、技术要点

8.1 维度均衡算法

// 伪代码
function selectQuestions(bankId: string, count: number): Question[] {
  const allItems = getPublishedItems(bankId);
  const dimensions = ['prompt', 'llm', 'ide', 'devPattern', 'workCapability'];
  const selected: Question[] = [];
  const usedIds = new Set<string>();

  // 轮询从各维度选取
  let dimIdx = 0;
  while (selected.length < count && dimIdx < count * dimensions.length) {
    const dim = dimensions[dimIdx % dimensions.length];
    const available = allItems.filter(
      (i) => i.dimension === dim && !usedIds.has(i.id)
    );

    if (available.length > 0) {
      const random = available[Math.floor(Math.random() * available.length)];
      selected.push(random);
      usedIds.add(random.id);
    }
    dimIdx++;
  }

  // 补充不足的题目(随机)
  if (selected.length < count) {
    const remaining = allItems.filter((i) => !usedIds.has(i.id));
    // ... 随机补充
  }

  return selected;
}

8.2 审核工作流

草稿(DRAFT) → 提交审核 → 待审核(PENDING_REVIEW)
                              ↓
                         审核通过 → 已发布(PUBLISHED)
                              ↓
                         审核拒绝 → 草稿(DRAFT) + 意见

九、注意事项

  1. 权限控制:题库管理、统计只对管理员开放
  2. 数据隔离:用户只能看到自己的评估记录,管理员可见所有
  3. 维度映射:确保题目维度与评估维度一致
  4. 题库状态:只有已发布的题目才能被抽取
  5. 回退机制:题库不足时使用实时生成作为备用

Plan Complete

Two execution options:

1. Subagent-Driven (this session) - 继续在此会话,使用 subagent 逐个执行任务

2. Parallel Session (separate) - 开新会话使用 executing-plans,分批执行

Which approach?