etms/EXAM_PAPER_MODEL_ANALYSIS.md
liyuchen bdba4a37fe Add: 分析考试与试卷数据模型问题报告
发现核心问题:
- 考试(Exam)和试卷(Paper)共用同一数据对象
- et_exam_exampaper_and_editexampaper 视图合并了两个独立概念
- 字段混用:时间属性和试题属性在同一表
- 无法支持'同一试卷用于多次考试'的业务场景

输出文件:EXAM_PAPER_MODEL_ANALYSIS.md
2026-04-16 17:34:52 +08:00

261 lines
9.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 考试与试卷数据模型问题分析报告
## 一、问题概述
当前系统中,**考试(Exam)** 和 **试卷(Paper)** 被设计为**同一个数据对象**,导致两个本应独立的概念混在一起,造成功能边界模糊和数据冗余。
---
## 二、当前数据模型分析
### 2.1 现有数据库表结构
```
et_exam_examination -- 考试信息表(独立)
├── id -- 考试ID
├── planid -- 关联培训计划ID
├── name -- 考试名称
├── starttime/endtime -- 考试时间窗口
├── duration -- 考试时长
├── isonline -- 是否在线
└── shouldJoin/realJoin -- 应考/实考人数
et_exam_exampaper -- 试卷表有examid字段关联考试
├── id -- 试卷ID
├── examid -- 关联考试ID外键
├── name -- 试卷名称
├── totalpoints -- 总分
├── passpoint -- 及格分数
├── description -- 描述
├── category -- 所属知识点
├── state -- 状态(是否可编辑)
└── sum1~sum4 -- 各题型数量统计
et_exam_question -- 试题题库表
├── id
├── type -- 题型1单选2多选3判断4问答
├── subject -- 题目内容
├── answer -- 正确答案
└── optionA~F -- 选项
et_exam_exampaper_question -- 试卷-题目关联表
├── id
├── examid -- 考试ID
├── questionid -- 试题ID
├── score -- 分值
├── isMust -- 是否必答
└── num -- 题目序号
```
### 2.2 实际使用的数据源
代码中实际使用的是 **`et_exam_exampaper_and_editexampaper`** 视图/联合表,将考试和试卷合并:
```sql
-- 在 SQL 映射中大量使用
select * from et_exam_exampaper_and_editexampaper
```
这个视图/表包含了考试和试卷的所有字段,导致两个概念完全混在一起。
---
## 三、核心问题分析
### 3.1 问题一:考试与试卷概念混淆
| 维度 | 考试(Exam) | 试卷(Paper) |
|------|-----------|-------------|
| **本质** | 一次考试活动 | 一份试题集合 |
| **属性** | 时间、人数、时长 | 题目、总分、及格分 |
| **生命周期** | 有开始/结束时间 | 可长期存在、复用 |
| **关联** | 关联培训计划 | 可关联多个考试 |
**当前问题**:考试和试卷共用同一张表,无法体现"同一份试卷可用于多次考试"的业务场景。
### 3.2 问题二:字段冗余与混用
`exampaper_edit.ftl` 中,同一个表单同时包含:
```html
<!-- 考试属性 -->
开放时间startdate / enddate
考试时长sc (小时)
<!-- 试卷属性 -->
试卷名称name
试卷描述description
及格分数passpoints
试卷类别category
```
这导致:
- 一份试卷不能同时用于多场考试(因为考试时间不同)
- 修改考试时间会影响试卷本身
### 3.3 问题三:题型统计字段冗余
`et_exam_exampaper` 表中有 `sum1~sum4` 字段存储各题型数量:
```sql
`sum1` int -- 单选题数量
`sum2` int -- 多选题数量
`sum3` int -- 判断题数量
`sum4` int -- 问答题数量
```
**问题**:这些统计值应该通过 SQL 动态计算,而不是冗余存储。试题数量变化时需要手动同步更新。
### 3.4 问题四:关联表使用不一致
`et_exam_limitation.map.xml` 中可以看到:
```sql
-- limitation 表使用 exam_id 关联
select * from et_exam_limitation where exam_id = ?
-- usertest 表也使用 exam_id 关联
select * from et_exam_usertest where exam_id = ?
```
这里的 `exam_id` 实际存储的是**试卷ID**(因为 `et_exam_exampaper_and_editexampaper` 视图本身就是考试+试卷的合并),命名语义混乱。
### 3.5 问题五:考试和问卷共用一套表
从代码中可以看到,`pg` 参数区分:
| pg值 | 类型 | 说明 |
|------|------|------|
| 1 | 考试/试卷 | 需要评分 |
| 2 | 调研问卷 | 不评分 |
但底层共用同一套表结构,只是业务逻辑不同。这种设计虽然灵活,但缺乏清晰的边界。
---
## 四、业务场景冲突示例
### 场景1同一试卷用于多次考试
**业务需求**某课程结业考试3月份和6月份各举办一次但使用同一份试卷。
**当前限制**
```
方案A创建两份试卷内容完全相同但ID不同→ 数据冗余
方案B使用同一试卷修改时间 → 影响历史考试记录
```
**理想设计**
```
试卷表(不变) ← 考试表(每次考试独立)
```
### 场景2考试延期
**当前问题**
- 用户需要修改考试时间,但操作入口在"编辑试卷"
- 修改后影响所有关联记录
**理想设计**
- 考试时间在考试表中独立管理
- 试卷表只负责试题内容
---
## 五、建议的数据模型重构
### 5.1 分离考试和试卷表
```
┌─────────────────────────────────────────────────────────────┐
│ 当前设计(混用) │
├─────────────────────────────────────────────────────────────┤
│ et_exam_exampaper_and_editexampaper │
│ ├── 考试属性(时间、人数) │
│ └── 试卷属性(题目、总分) │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 建议设计(分离) │
├─────────────────────────────────────────────────────────────┤
│ et_exam_exampaper试卷表
│ ├── id, name, description, category │
│ ├── totalpoints, passpoint │
│ └── creatperson, edittime │
├─────────────────────────────────────────────────────────────┤
│ et_exam_examination考试表
│ ├── id, paper_id关联试卷
│ ├── name, starttime, endtime, duration │
│ ├── shouldJoin, realJoin │
│ └── state, leader │
├─────────────────────────────────────────────────────────────┤
│ et_exam_exampaper_question关联表
│ ├── id, paper_id, question_id │
│ ├── score每场考试可单独设置分值
│ └── num, isMust │
└─────────────────────────────────────────────────────────────┘
```
### 5.2 关键改进点
| 改进项 | 当前 | 建议 |
|--------|------|------|
| 试卷复用 | 同一试卷不能用于多场考试 | 一份试卷可关联多场考试 |
| 时间独立 | 考试时间绑定试卷 | 考试时间独立管理 |
| 题目分值 | 固定分值 | 每场考试可单独设置 |
| 题型统计 | 冗余字段 sum1~sum4 | 动态 SQL 计算 |
---
## 六、重构风险评估
| 风险项 | 等级 | 说明 |
|--------|------|------|
| 历史数据迁移 | 高 | 现有数据需要重新整理 |
| 业务逻辑修改 | 高 | 涉及多个控制器和页面 |
| 关联表改动 | 中 | limitation、usertest 等表需同步修改 |
| 测试工作量 | 高 | 需要全面回归测试 |
---
## 七、建议执行步骤
1. **分析阶段**:梳理所有使用 `et_exam_exampaper_and_editexampaper` 的代码
2. **设计阶段**:完成新的数据模型设计
3. **开发阶段**
- 新建考试表相关逻辑
- 保留试卷表
- 修改关联表
4. **数据迁移**:编写迁移脚本
5. **测试验证**:全面回归测试
6. **上线部署**:灰度发布
---
## 八、附录:涉及文件清单
### SQL 映射文件
- `et_exam_exampaper_and_editexampaper.map.xml`
- `et_exam_editexampaper.map.xml`
- `et_exam_usertest.map.xml`
- `et_exam_limitation.map.xml`
### 前端模板
- `exam/exampaper.ftl`
- `exam/exampaper_edit.ftl`
- `exam/exampaper_list.ftl`
- `exam/exampaper_detail.ftl`
- `exam/exam.ftl`
- `exam/exam_list.ftl`
### Java 控制器
- `ExamController.class`
- `ExampaperController.class`
- `ExamResultController.class`
- `ExampaperServiceImpl.class`
- `ExamServiceImpl.class`
---
*报告生成时间2026-04-16*