Files
examination/docs/architecture.md
T
wonder d3cba0e23c feat: 初始化 CS 知识应试强化系统
- 纯 HTML/CSS/JS 单页应用,支持填空题和选择题交互
- 5 个主题共 100 道题(GC/JVM、AI 结构化输出、记忆管理、幻觉、工具链)
- 按主题组织、按题型拆分的 JSON 数据结构
- JSON Schema 校验 + 提示词模板 + 题型模板
- 自定义导入功能(粘贴/上传 JSON)
- 项目文档(需求 + 架构)

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-02 18:22:20 +08:00

12 KiB
Raw Blame History

架构文档

1. 系统总览

┌─────────────────────────────────────────────────────┐
│                    用户浏览器                         │
│  ┌───────────────────────────────────────────────┐  │
│  │  index.html  (单文件 SPA)                     │  │
│  │  ┌─────────┐  ┌──────────┐  ┌─────────────┐  │  │
│  │  │ 导航栏   │  │ 做题区域  │  │ 导入模态框   │  │  │
│  │  └────┬────┘  └─────┬────┘  └──────┬──────┘  │  │
│  └───────┼─────────────┼──────────────┼──────────┘  │
└──────────┼─────────────┼──────────────┼─────────────┘
           │ fetch       │ fetch        │ JSON.parse
           ▼             ▼              ▼
┌─────────────────────────────────────────────────────┐
│  topics/  (数据层)                                   │
│  ├── index.json          ← 主题索引                  │
│  └── {topic-slug}/                                   │
│      ├── meta.json        ← 主题元信息(稳定)        │
│      ├── fill_blank.json  ← 填空题集                  │
│      └── single_choice.json ← 单选题集               │
└─────────────────────────────────────────────────────┘
           ▲
           │ git push / pull
           ▼
┌─────────────────────────────────────────────────────┐
│  Agent / LLM  (生成层)                               │
│  ├── Claude Code Skill (generate / validate)         │
│  ├── LLM + 提示词模板 (schema/prompt-template.md)    │
│  └── JSON Schema 校验 (schema/question.schema.json)  │
└─────────────────────────────────────────────────────┘

2. 目录结构

examination/
├── index.html                      # 前端入口(单文件 SPA)
├── topics/                         # 题目数据
│   ├── index.json                  # 主题索引
│   └── {topic-slug}/               # 主题目录
│       ├── meta.json               # 主题元信息
│       ├── fill_blank.json         # 填空题
│       ├── single_choice.json      # 单选题
│       ├── multiple_choice.json    # 多选题(可选)
│       ├── true_false.json         # 判断题(可选)
│       ├── short_answer.json       # 简答题(可选)
│       ├── code_reading.json       # 代码阅读题(可选)
│       └── scenario.json           # 场景分析题(可选)
├── schema/                         # Schema 与模板
│   ├── question.schema.json        # 题目 JSON Schema(Draft-07)
│   ├── prompt-template.md          # LLM 生成提示词模板
│   └── templates/                  # 各题型示例
│       ├── single_choice.json
│       ├── multiple_choice.json
│       ├── true_false.json
│       ├── fill_blank.json
│       ├── short_answer.json
│       ├── code_reading.json
│       └── scenario.json
├── docs/                           # 文档
│   ├── requirements.md             # 需求文档
│   └── architecture.md             # 架构文档(本文件)
├── .gitignore                      # 排除 .ref/
└── README.md

3. 数据模型

3.1 主题索引 — topics/index.json

{
  "version": "1.0.0",
  "updated": "2026-09-02",
  "topics": [
    {
      "slug": "gc-jvm",
      "name": "GC / JVM / 三色标记",
      "description": "...",
      "path": "topics/gc-jvm",
      "stats": {
        "total": 20,
        "by_type": { "fill_blank": 10, "single_choice": 10 }
      }
    }
  ]
}

前端加载此文件渲染主题列表,stats 字段用于展示题目数量。

3.2 主题元信息 — topics/{slug}/meta.json

{
  "slug": "gc-jvm",
  "name": "GC / JVM / 三色标记",
  "description": "JVM 堆内存模型、GC 算法、三色标记法、垃圾收集器",
  "tags": ["jvm", "gc", "heap"],
  "difficulty_range": [1, 5],
  "schema_version": "1.0.0",
  "question_files": ["fill_blank", "single_choice"],
  "stats": {
    "total": 20,
    "by_type": { "fill_blank": 10, "single_choice": 10 }
  }
}
  • question_files 列出该主题包含的题型文件名(不含 .json 后缀)
  • 前端根据此列表动态加载对应的题目文件
  • stats 在每次生成/追加题目后由 Agent 更新

3.3 题目文件 — topics/{slug}/{type}.json

{
  "topic": "gc-jvm",
  "type": "fill_blank",
  "schema_version": "1.0.0",
  "generated": "2026-09-02T00:00:00Z",
  "questions": [ /* 题目数组 */ ]
}

每种题型一个文件,支持多 Agent 并行写入不同题型文件而无冲突。

3.4 题目对象

公共字段(所有题型必有)

字段 类型 必填 说明
id string ✅ 格式 {type_short}-{seq},如 fb-001
type enum ✅ 题型标识
difficulty integer ✅ 1-5
tags string[] ✅ 细粒度知识点标签
question string ✅ 题干
explanation string ✅ 解析
source string ❌ 来源
related string[] ❌ 关联题目 id

填空题 (fill_blank)

{
  "answer": ["老", "Old"],
  "answer_rule": "any"
}
  • answer: string[],可接受的答案列表
  • answer_rule: "any"(任一匹配) | "all"(全部匹配) | "ordered"(按序匹配)

单选题 (single_choice)

{
  "options": { "A": "选项A", "B": "选项B", "C": "选项C", "D": "选项D" },
  "answer": "B"
}

多选题 (multiple_choice)

{
  "options": { "A": "...", "B": "...", "C": "...", "D": "..." },
  "answer": ["A", "C"]
}

判断题 (true_false)

{ "answer": true }

简答题 (short_answer)

{
  "answer": "参考答案文本",
  "keywords": ["关键词1", "关键词2"],
  "scoring_rubric": "评分标准说明"
}

代码阅读题 (code_reading)

{
  "code": "int x = 1;\nprintf(\"%d\", x);",
  "language": "c",
  "sub_questions": [
    { "index": 1, "type": "single_choice", "question": "...", "options": {...}, "answer": "A", "explanation": "..." }
  ]
}

场景分析题 (scenario)

{
  "context": "一个电商系统在高峰期出现超卖问题...",
  "code": null,
  "sub_questions": [
    { "index": 1, "type": "short_answer", "question": "...", "answer": "...", "keywords": [...], "explanation": "..." }
  ]
}

3.5 ID 编码规则

{type_short}-{sequence}
   fb     -   001
type_short 题型
sc single_choice
mc multiple_choice
tf true_false
fb fill_blank
sa short_answer
cr code_reading
sn scenario

4. 前端架构

4.1 页面结构

┌──────────────────────────────────────────┐
│  Header: 🎯 CS 知识应试强化              │
├────────────┬─────────────────────────────┤
│  Sidebar   │  Main Content               │
│            │                             │
│  📚 主题   │  ┌─ Toolbar ──────────────┐ │
│  · gc-jvm  │  │ 进度 ✅ ❌ ⏳  按钮组  │ │
│  · ai-so   │  └────────────────────────┘ │
│  · ai-mm   │  ┌─ Progress Bar ─────────┐ │
│  · ai-he   │  └────────────────────────┘ │
│  · ai-at   │  ┌─ Question Card ────────┐ │
│            │  │ #1 填空  ★★★           │ │
│  ────────  │  │ 题干 [____]            │ │
│  📥 导入   │  │ [检查] [显示答案]       │ │
│            │  │ 💡 解析...              │ │
│            │  └────────────────────────┘ │
│            │  ┌─ Question Card ────────┐ │
│            │  │ ...                    │ │
│            │  └────────────────────────┘ │
└────────────┴─────────────────────────────┘

4.2 数据流

页面加载
  │
  ▼
fetch topics/index.json ──→ 渲染侧边栏主题列表
  │
  │ 用户点击主题
  ▼
fetch topics/{slug}/meta.json ──→ 获取 question_files 列表
  │
  ▼
fetch topics/{slug}/{type}.json (并行) ──→ 合并 questions 数组
  │
  ▼
renderQuiz() ──→ 按题型渲染题目卡片
  │
  │ 用户交互(选择/输入/检查/显示答案)
  ▼
answers 状态更新 ──→ re-render ──→ 更新统计

4.3 状态管理

let topics = [];            // 从 index.json 加载的主题列表
let currentTopic = null;    // 当前选中的主题 slug
let currentQuestions = [];  // 当前主题的所有题目(合并自多个题型文件)
let answers = {};           // qId → { value, correct, revealed }
let customQuestions = [];   // 通过导入功能临时添加的题目

4.4 题型渲染逻辑

题型 渲染方式 判定逻辑
fill_blank 题干中的 ______ 替换为 <input> matchFillAnswer() 根据 answer_rule 匹配
single_choice 选项列表,radio 样式 value === answer
multiple_choice 选项列表,checkbox 样式 数组比较
true_false 两个大按钮 value === answer
short_answer <textarea> 关键词匹配(辅助)
code_reading 代码块 + 子题列表 按子题类型分别判定
scenario 场景描述 + 子题列表 按子题类型分别判定

5. 生成工作流

5.1 非 Agent 环境(手动 LLM 对话)

  1. 打开 schema/prompt-template.md,复制提示词模板
  2. 替换 {topic_name}、{question_type}、{count} 等变量
  3. 将提示词发送给 LLM(ChatGPT / Claude 等)
  4. 获取 JSON 输出后,粘贴到对应题型文件中
  5. 更新 meta.json 的 stats 字段
  6. 刷新前端页面

5.2 Agent 环境(Claude Code Skill)

/examination generate --topic gc-jvm --type fill_blank --count 10
/examination validate --file topics/gc-jvm/fill_blank.json
/examination batch-generate --topic gc-jvm --types fill_blank,single_choice

Skill 内部流程:

  1. 读取 meta.json 获取主题上下文
  2. 调用 LLM 生成题目(使用 schema 约束)
  3. 校验输出是否符合 question.schema.json
  4. 写入对应题型文件
  5. 更新 meta.json 和 index.json 的 stats

5.3 多 Agent 并行生成

Agent 1 ──→ topics/gc-jvm/fill_blank.json
Agent 2 ──→ topics/gc-jvm/single_choice.json
Agent 3 ──→ topics/gc-jvm/multiple_choice.json

由于每种题型写入独立文件,多个 Agent 可并行生成同一主题的不同题型而无写冲突。

6. 扩展指南

新增主题

  1. 创建 topics/{new-slug}/ 目录
  2. 创建 meta.json
  3. 按题型创建题目 JSON 文件
  4. 更新 topics/index.json

新增题型

  1. 在 schema/question.schema.json 的 definitions.question.type.enum 中添加新类型
  2. 添加对应的 allOf 条件分支定义字段约束
  3. 在前端 typeLabel() 中添加映射
  4. 在前端 renderQuestionCard() 中添加渲染逻辑
  5. 在 schema/templates/ 中添加示例模板