比对

旧系统 vs V6 对比分析

题库数据结构层面差异

旧系统 vs V6 新设计 —— 题库层面差异对比

本文档对比「池馆」旧 API 系统与 V6 题库分类设计方案,在题库数据结构层面的主要差异。 基于旧系统源码 src/database/schema.tssrc/models/question.model.tssrc/models/course-task.model.ts 与 V6 设计文档 题库分类设计方案_v6.md 及种子数据 seed.py 的分析。


一、架构层级差异(最根本)

维度旧系统V6 新设计
层级结构三层扁平:CourseTask(题组)→ Question(题目)→ QuestionMeta(元数据/答案)四层分离:Material ⇄ 多对多 ⇄ QuestionBlockQuestionPoint
材料独立性❌ 没有独立的「材料」实体。材料(音频/文本/视频)作为字段(audioUrlvideoUrltranscriptmainTitlesubTitle散落在 CourseTask 和 Question 上,无法跨题组复用Material 独立建表,多对多关系,同一材料可被多个 QuestionBlock 引用
题组与题目的关系CourseTaskQuestion 是 1:N(直接外键),但 CourseTask 本身混杂了课程内容(paragraphs、audioMarks、notes、transcript)和题库两种职责QuestionBlockQuestion 是 1:N,职责纯粹——只管「教学和发布的最小单元」
计分粒度QuestionMeta.answers 是扁平数组 QuestionSingleAnswer[],每项只有 key/value/defaultValue——答案和判分混在一起Point 是独立实体,有 locator(定位)、answerhintmatch_rulescoring(批改方式)五个维度,判分规则从答案中解耦

二、题型/作答形式体系

维度旧系统V6 新设计
分类枚举QuestionType 枚举有 13 种(含注释掉的 6 种),实际启用 13 个值,如 SINGLE_CHOICEGAP_FILLING_WITH_CHOICESORALCOMPOSITIONTRANSLATIONFREE_FORMSTRESSMARKFREE_TALKCONNECTCLOZEquestion_type 固定词表 8 值:单选、多选、正误判断、匹配、排序、选词填空、单行填空、开放作答
口语/写作/翻译分成三个独立的 QuestionType:ORAL(口语跟读)、COMPOSITION(作文)、TRANSLATION(翻译),且 FREE_FORMFREE_TALK 也是独立类型合并为单一 question_type = 开放作答,通过 input_modality(文本多行/语音/图片)区分录入方式
题型 vs 作答形式混在一起——QuestionType 同时表达了"题型"(如完形填空)和"作答形式"(如单选)两个概念分离question_type(作答形式,8 值,挂题目)+ block_type(题型,开放词表,挂题组)
主观/客观标记isSubjective: boolean 一个布尔值粗暴区分去掉了 isSubjective,由计分点的 scoring 字段(机器/人工/AI/混合)精确表达批改方式

三、分类/标注体系

维度旧系统V6 新设计
能力维度。没有"听力/阅读/写作/翻译/口语/语言知识运用"的能力标注primary_ability(主能力,单选)+ secondary_abilities(次能力,多选),挂在题组上
标签体系Tag 表只有 name 字段,通过 CourseTagLink 关联到 CourseTask——单一维度,无法区分公共/私人标签双轨制public_tag(封闭键 exam/topic,全体可见)+ tags(个人标签,仅本人可见)
考试对照❌ 无。Exam 是独立的考试实体(组卷/考试管理),和题库没有分类关系public_tag.exam 键直接关联考试/卷种(CET-4、TEM-8、考研一 等),可做筛选
材料体裁❌ 无。CourseTask.type 只区分 passage/exercise,无法表达"对话/篇章/新闻/讲座·独白/图表"等体裁Material.genre 固定词表 11 种体裁
材料模态散落在多个字段:audioUrlvideoUrltranscriptcaptionUrlMaterial.modality(JSON 数组:文本/音频/视频/图片),多选

四、来源与审核

维度旧系统V6 新设计
来源CourseTaskSource 三值枚举:original(原创)、official(官方真题)、ai(AI 生成);QuestionSource 两值枚举:original/official——两套词表不统一,且无 AI 选项在 Question 层统一二值:AI生成 / 真人编制(挂在 Material 和 Question 两层),题组层不存来源而是自动推导为 三态(真人编制/AI生成/人机混合)
审核状态❌ 无审核机制。只有 isPublished(发布)和 isPublic(公共)两个布尔开关review_status 三态(待审核/已通过/已驳回),且材料有独立的审核闸门
可见性isPublished(boolean)+ isPublic(boolean)+ universityIds(逗号分隔字符串)——三个字段混搭,无统一模型visibility(private/public/custom)+ visibility_scale(JSON 对象,机构+用户 ID 列表),且非 private 须已通过审核

五、挖空/填空机制

维度旧系统V6 新设计
完形填空GAP_FILLING_WITH_CHOICES 类型,body 结构为 {text: string, options?: string[]},空位用 ${_} 占位符标记——空位定位和答案解析都在运行时处理blanks 常驻键(含 answer_word + occurrence),材料存填入答案后的完整文本,空位由题目层规格定位——前端渲染灵活
填空标记${_} 占位符——语义不明确,无编号{{n}} 内嵌标记——与 Point.blank[n] 一一对应,编号为题组内顺序号
词库/选项options?: string[]——简单字符串数组,无标签(label)bank: [{label, word}]options: [{label, text}]——带标签的结构化选项

六、数据存储/技术栈

维度旧系统V6 新设计
数据库MySQL(Drizzle ORM)SQLite(demo 阶段,设计上无关具体 DB)
题干/答案存储body: object(宽泛 JSON)+ answer: QuestionAnswerType{value: QuestionAnswerValueType})——类型系统靠 TypeScript 枚举/联合类型,运行时是弱类型content: TEXT(JSON,结构随 question_type 宽松承载)+ Point.answer(字符串或列表)+ Point.hint + Point.match_rule——判分细节结构化独立存储
媒体资源内嵌字段:audioUrlvideoUrltranscriptaudioMarksvocabularyMarkscaptionUrl 直接挂在实体上媒体文件不入库,一律走 Material.resources_url 外链或附件

七、入库校验

维度旧系统V6 新设计
校验机制❌ 无入库校验。数据结构弱约束(body: object,运行时才解析)10 条入库时自动检查(题型与作答形式相容、翻译方向越界、blanks 定位、可见性闸门等),违例直接拒绝
数据一致性靠代码运行时校验(checkers 目录下有 single/multiple/filling/default 四种 checker)靠入库前一次性校验(Python validate_block),确保数据结构层面自洽

八、旧系统有而 V6 去掉的

旧系统概念V6 处理
CourseTask.paragraphs(段落)、audioMarksvocabularyMarks归入 Material 或 Question 的 content 结构,不再作为题组字段
Question.mainTitle / subTitle题组的 instruction 和 Material 的 content 承载,不再单独列标题字段
Question.analysis(解析)V6 方案本轮未定义解析字段(备忘中提到后续处理)
STRESS(重音标注)、MARK(单词高亮)、CONNECT(连线题)这些是池馆的特色题型,V6 的 29 种题型词表未收录——需要走扩展评审
QuestionOverview / TaskOverview(统计)V6 方案有统计口径说明(第十二节),但本轮未落地表结构

九、V6 有而旧系统没有的

V6 新概念说明
Material 层完全独立的材料实体,支持多对多复用、独立审核
Point 层计分点独立建模,支持 hint/match_rule/scoring
能力维度L/R/W/T/S/K 六维度,主+次能力体系
public_tag + tags 双轨系统级标签与个人标签完全隔离
source 推导题组来源由材料+题目 source 自动推导为三态
review_status 闸门未过审 → 只能 private,从结构上杜绝污染
input_modality开放作答的录入方式正交维度(文本多行/语音/图片)
translation_direction翻译题的翻译方向,仅翻译类题组使用
source_text保留原题样貌,结构化数据与教学现场可互相对照

总结

旧系统本质上是一个课程内容管理 + 简单题库的混合体(CourseTask 身兼课程段落和题目载体两职),题型分类靠单一 QuestionType 枚举硬编码。

V6 则是一套专业的外语题库分类体系,通过四层分离、双轨标签、能力维度、来源推导、审核闸门、入库校验等机制,解决了旧系统的录入重、词表打架、发布口径对不上三大核心问题。