This commit is contained in:
@@ -117,6 +117,53 @@ flowchart LR
|
||||
不同大纲或节点有多个投放。
|
||||
- **知识点**分为跨大纲语义 `KnowledgeConcept` 和具体大纲位置 `CurriculumNode`。二者允许关联,但不能互相替代。
|
||||
|
||||
### 编辑树与在线查询投影
|
||||
|
||||
租户录题和内容编辑界面仍应以树形结构展示大纲,例如“学科 → 章节 → 小节 → 知识点”,因为树适合人工定位、
|
||||
拖动和维护内容位置。后端不会把完整路径复制到题目,而是用以下两种结构保存大纲:
|
||||
|
||||
- `CurriculumNode.ParentId` 保存直接父子关系,是编辑树的事实来源;
|
||||
- `CurriculumNodeClosure` 保存 `(AncestorNodeId, DescendantNodeId, Depth)`,用于高效查询祖先、后代和整棵子树,
|
||||
避免每次递归遍历邻接表。
|
||||
|
||||
题目导入和题目投放是两个独立用例:
|
||||
|
||||
```text
|
||||
导入 / 录入题目
|
||||
→ 查重、复用或创建 QuestionAsset
|
||||
→ 创建不可变 QuestionRevision
|
||||
|
||||
选择大纲树节点
|
||||
→ 创建 QuestionPlacement
|
||||
→ 保存 CurriculumVersionId + CurriculumNodeId
|
||||
→ 配置适用目标、评分政策和知识概念
|
||||
```
|
||||
|
||||
因此前端可以把“上传 → 查重预览 → 选择树节点 → 完成导入”组织成一个连续流程,但后端不能把
|
||||
`QuestionAsset` 的创建与某个树节点绑定为同一个不可拆分操作。同一道题可以导入一次,再通过多个 Placement
|
||||
放入不同大纲或不同节点。
|
||||
|
||||
发布时,`ContentReleaseCompiler` 将树上的有效 Placement 编译为扁平的 `ContentReleaseQuestion` 候选行,
|
||||
每行直接保存 `CurriculumNodeId`、`QuestionRevisionId`、`AudienceSegmentId`、评分政策和稳定 `Ordinal`。
|
||||
学生在线组题读取这些发布候选,不再从题目向上或向下遍历大纲树,也不在线重新计算目标适用规则。
|
||||
|
||||
```text
|
||||
编辑视图:树形 CurriculumNode
|
||||
↓ 选择节点并创建 Placement
|
||||
发布阶段:编译适用规则和交付版本
|
||||
↓
|
||||
查询视图:扁平 ContentReleaseQuestion 候选投影
|
||||
```
|
||||
|
||||
当前 `ContentCandidateReader` 对 `CurriculumNodeId` 使用**精确匹配**。请求父章节时不会自动包含所有子节点题目。
|
||||
如果产品定义“点击父章节即练习整个子树”,必须显式选择并实现以下策略之一:
|
||||
|
||||
1. 发布时把子树范围预展开到专用候选投影;
|
||||
2. 查询前通过 `CurriculumNodeClosure` 得到后代 NodeId,再批量过滤发布候选;
|
||||
3. 为章节策划并发布 `CollectionRelease`,在线按题集成员读取。
|
||||
|
||||
在方案确定前,不得默认父节点查询已经包含子节点,也不要在高频路径临时加入递归逐层查询。
|
||||
|
||||
## 关系图
|
||||
|
||||
```mermaid
|
||||
|
||||
Reference in New Issue
Block a user