feat(education): question browsing and practice configuration preview

This commit is contained in:
2026-07-27 20:13:09 +08:00
parent 478d3d65b7
commit 73b2a8edcc
26 changed files with 2898 additions and 16 deletions

View File

@@ -4,7 +4,7 @@
## 当前状态
此模块提供教育业务功能骨架题库目录浏览 tracer bullet。
此模块提供教育业务功能骨架题库目录浏览 tracer bullet,以及题目预览与练习配置预览
**已实现**
- 模块骨架与包结构
@@ -12,8 +12,11 @@
- 租户识别端点 (`/education/tenant/resolve`) — 学生端登录前使用
- 教育上下文端点 (`/education/context`) — 学生端已认证状态
- 题库目录端点 (见下方 Catalog API) — 学生端已认证
- 题目浏览与筛选端点 (见下方 Questions API) — 学生端已认证
- 练习配置预览端点 (见下方 Practice API) — 学生端已认证
- 题目安全过滤(答案/解析绝不暴露到前端)
- 独立的功能开关配置 + Scalar 数据源配置
- 错误码常量(通用 + 租户 + Catalog/Scalar
- 错误码常量(通用 + 租户 + Catalog/Scalar + 题目/练习
- 权限与菜单种子数据
## 功能配置
@@ -40,7 +43,7 @@ GET /admin-api/education/capability
"module": "education",
"enabled": true,
"version": "1.0.0",
"capabilities": ["shell", "catalog"]
"capabilities": ["shell", "catalog", "questions", "practice-preview"]
}
}
```
@@ -166,6 +169,7 @@ mysql -u root -p ruoyi-vue-pro < sql/mysql/education/001-education-tenant-rollba
- 每个正向脚本应有对应的回滚脚本
- schema 文件仅包含 DDLseed 文件仅包含 DML
- **不修改**项目根目录的 `ruoyi-vue-pro.sql` 巨量全量转储
- Ticket #5 为只读/预览操作,无新增数据库 schema 或 DML
## 前端状态
@@ -278,6 +282,104 @@ Browser → Controller(/education/catalog/*) → CatalogService → CatalogProvi
**当前阻塞**:完整前端源码不存在,后端目录接口已就绪可通过 Swagger/curl 验证。
### 用户 APP - 题目与练习预览Questions & Practice
所有端点需要学生登录态Bearer Token`userId``tenantId` 由安全上下文派生,不接受客户端传参。
返回的题目数据经过白名单过滤,绝不包含 `correctAnswer``answer``explanation``analysis` 或选项的 `isCorrect` 字段。
#### 架构边界
```
Browser -> Controller(/education/questions/*) -> QuestionCatalogService -> QuestionCatalogProvider -> [Scalar]
↑ SafeQuestionRespVO ↑ CatalogQuestionDTO
```
- **业务层**Controller/Service仅操作安全 VO`SafeQuestionRespVO` 等),答案字段在 DTO→VO 转换时被剥离
- **集成层**Scalar DTO + ScalarCatalogProvider封装 Scalar 协议差异,答案字段在此层被映射但绝不透传到上层
#### 端点列表
| 端点 | 说明 | 参数 |
|------|------|------|
| `GET /app-api/education/questions/page` | 分页查询安全题目 | `collectionId`, `nodeId`, `type`, `difficulty` (可选), `pageNo` (默认1), `pageSize` (默认20) |
| `GET /app-api/education/questions/get` | 获取单个安全题目 | `id` (必填) |
| `GET /app-api/education/questions/collection-questions` | 查询题集中的安全题目 | `collectionId` (必填), `type`, `difficulty` (可选), `pageNo`, `pageSize` |
| `GET /app-api/education/practice-config/preview` | 预览练习配置(不创建会话) | `collectionId` (必填), `nodeId`, `type`, `difficulty` (可选), `questionCount` (默认10, 1-1000) |
#### 分页响应格式
```json
{
"code": 0,
"msg": "成功",
"data": {
"list": [
{
"id": "q-001",
"contentVersion": "v2",
"stem": "1+1等于几",
"type": "choice",
"difficulty": "easy",
"options": [
{"label": "A", "content": "2", "order": 1.0}
]
}
],
"total": 50
}
}
```
#### 练习预览响应格式
```json
{
"code": 0,
"msg": "成功",
"data": {
"eligibleCount": 50,
"totalCount": 100,
"availableTypes": ["choice", "fill"],
"availableDifficulties": ["easy", "medium"],
"minQuestions": 1,
"maxQuestions": 50,
"suggestedCount": 20,
"normalizedCount": 10,
"countWithinRange": true
}
}
```
#### 错误响应
| HTTP 状态 | 错误码 | 说明 |
|-----------|--------|------|
| 401 | 1_016_000_002 | 未登录或会话过期 |
| 404 | 1_005_003_001 | 题目不存在或不可见 |
| 400 | 1_005_003_002 | 无效的练习配置 |
| 400 | 1_005_003_003 | 符合条件的题目数量不足 |
| 500 | 1_005_003_004 | 题库数据源返回不安全内容 |
#### 安全字段白名单
`SafeQuestionRespVO` 仅包含以下字段,前端可安全展示:
- `id`, `contentVersion`, `stem`, `type`, `difficulty`
- `options[]` 中仅包含 `label`, `content`, `order`
以下字段**绝不**出现在响应中:
- `correctAnswer`, `answer`, `explanation`, `analysis`
- 选项的 `isCorrect`
- 任何管理元数据
#### 前端集成提示
前端就位后,学生端练习入口应:
1. 浏览题库目录Catalog API选择题集
2. 调用 `/education/questions/page``/education/questions/collection-questions` 预览题目概要
3. 调用 `/education/practice-config/preview` 获取可用题量范围和建议配置
4. 展示预览结果后用户在可用范围内选择题量开始练习Ticket #6 创建持久会话)
**当前阻塞**:完整前端源码不存在,后端接口已就绪可通过 Swagger/curl 验证。
### 更新后的错误码
| 错误码 | 说明 |
@@ -297,3 +399,10 @@ Browser → Controller(/education/catalog/*) → CatalogService → CatalogProvi
| 1_005_002_007 | 上游超时 |
| 1_005_002_008 | 上游返回异常:{状态码} |
| 1_005_002_009 | 不支持的题库数据源模式 |
| 1_005_002_010 | Scalar 数据源未配置 |
| 1_005_002_011 | 上游题库返回数据格式异常 |
| 1_005_002_012 | 上游题库服务不可达 |
| 1_005_003_001 | 题目不存在或不可见 |
| 1_005_003_002 | 无效的练习配置 |
| 1_005_003_003 | 符合条件的题目数量不足 |
| 1_005_003_004 | 题库数据源返回不安全内容 |