xinli/z_Project change/进度汇总/21-问卷功能完整实现方案.md
2025-11-12 15:25:47 +08:00

222 lines
7.3 KiB
Markdown
Raw 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.

# 问卷功能完整实现方案
## 📋 需求概述
系统需要支持完整的问卷功能,包括:
1. **问卷在量表管理中显示**:创建的问卷能够出现在量表管理中
2. **问卷答题功能**:用户填写完问卷后,客观题自动打分,主观题传给管理员进行打分
3. **多种题目类型支持**:单选、多选、判断、填空、排序、计算、简答、问答、作文等
4. **多种组卷形式**:自助组卷、随机组卷、手动随机相结合
5. **成绩排名统计**:客观题系统自动实现打分,成绩自动排名统计
---
## 🎯 实现方案
### 阶段一:让问卷显示在量表管理中
#### 方案1统一查询接口推荐
- 修改量表列表查询,同时返回问卷数据
- 添加类型标识字段(`sourceType`: 'scale' 或 'questionnaire'
- 前端统一显示,根据类型标识区分操作
#### 方案2创建统一视图
- 在数据库创建视图,统一量表和问卷
- 查询时使用视图
**选择方案1**,因为更灵活,不需要修改数据库结构。
---
### 阶段二:问卷答题功能
参考量表测评的实现方式:
1. **开始问卷**:创建问卷答题记录
2. **获取题目**:根据组卷方式获取题目列表
3. **保存答案**:实时保存用户答案
4. **提交问卷**
- 客观题自动计分
- 主观题标记为待评分
- 计算客观题总分
- 更新排名
---
### 阶段三:自动打分功能
#### 客观题类型
- **radio单选**:根据选项的`is_correct`和`option_score`计分
- **checkbox多选**:全对得满分,部分对按比例得分
- **boolean判断**:根据选项的`is_correct`计分
- **input填空**:如果有标准答案,进行文本匹配(支持模糊匹配)
- **sort排序**:顺序完全正确得满分,部分正确按比例得分
- **calculate计算**:数值匹配,允许误差范围
#### 主观题类型
- **text简答**:需要管理员评分
- **textarea问答**:需要管理员评分
- **essay作文**:需要管理员评分
- **input无标准答案**:需要管理员评分
---
### 阶段四:主观题评分管理
1. **待评分列表**:显示所有待评分的主观题
2. **评分界面**:管理员可以查看题目、答案,进行评分
3. **批量评分**:支持批量评分功能
4. **评分后更新**:评分后更新总分和排名
---
### 阶段五:成绩排名统计
1. **排名计算**
- 按总分从高到低排序
- 相同分数按提交时间排序(先提交的排名靠前)
2. **排名更新**:提交问卷或评分后自动更新排名
3. **排名查询**:支持按问卷查询排名列表
---
## 📁 需要创建/修改的文件
### 数据库
- [x] `psy_questionnaire` - 问卷表(已存在)
- [x] `psy_questionnaire_item` - 问卷题目表(已存在)
- [x] `psy_questionnaire_option` - 问卷选项表(已存在)
- [x] `psy_questionnaire_answer` - 问卷答题记录表(已存在)
- [ ] `psy_questionnaire_answer_detail` - 问卷答案详情表(需要创建)
### 后端Java文件
- [ ] `PsyQuestionnaireAnswerDetail.java` - 问卷答案详情实体类
- [ ] `PsyQuestionnaireAnswerDetailMapper.java` - Mapper接口
- [ ] `PsyQuestionnaireAnswerDetailMapper.xml` - MyBatis映射
- [ ] `IPsyQuestionnaireAnswerService.java` - 问卷答题服务接口
- [ ] `PsyQuestionnaireAnswerServiceImpl.java` - 问卷答题服务实现
- [ ] `PsyQuestionnaireController.java` - 问卷控制器(需要增强)
- [ ] `PsyScaleController.java` - 量表控制器(需要修改列表查询)
### 前端Vue文件
- [ ] `questionnaire/taking.vue` - 问卷答题页面
- [ ] `questionnaire/start.vue` - 开始问卷页面
- [ ] `questionnaire/scoring.vue` - 主观题评分页面
- [ ] `questionnaire/ranking.vue` - 成绩排名页面
- [ ] `scale/index.vue` - 量表管理页面(需要修改,显示问卷)
---
## 🔧 技术实现细节
### 1. 量表列表统一显示问卷
**后端修改**
```java
// PsyScaleController.java
@GetMapping("/list")
public TableDataInfo list(PsyScale scale, @RequestParam(required = false) Boolean includeQuestionnaire)
{
startPage();
List<PsyScale> scaleList = scaleService.selectScaleList(scale);
// 如果需要包含问卷
if (includeQuestionnaire != null && includeQuestionnaire) {
List<PsyQuestionnaire> questionnaireList = questionnaireService.selectQuestionnaireList(...);
// 转换为统一的Scale格式添加sourceType标识
// 合并到scaleList
}
return getDataTable(scaleList);
}
```
**前端修改**
```javascript
// scale/index.vue
// 在表格中添加类型列
<el-table-column label="类型" prop="sourceType" width="100">
<template slot-scope="scope">
<el-tag v-if="scope.row.sourceType === 'questionnaire'" type="warning">问卷</el-tag>
<el-tag v-else type="primary">量表</el-tag>
</template>
</el-table-column>
```
### 2. 问卷答题流程
参考量表测评的实现:
1. 开始问卷 → 创建`PsyQuestionnaireAnswer`记录
2. 获取题目 → 根据`paper_type`获取题目列表
3. 保存答案 → 保存到`PsyQuestionnaireAnswerDetail`
4. 提交问卷 → 自动计分 + 更新排名
### 3. 自动计分逻辑
```java
// 客观题计分
private BigDecimal calculateObjectiveScore(PsyQuestionnaireItem item, AnswerDetailVO answer) {
switch(item.getItemType()) {
case "radio":
// 单选:检查选项是否正确
return checkOptionCorrect(item, answer.getOptionId()) ? item.getScore() : BigDecimal.ZERO;
case "checkbox":
// 多选:检查所有选项是否正确
return calculateMultiChoiceScore(item, answer.getOptionIds());
case "boolean":
// 判断:检查选项是否正确
return checkOptionCorrect(item, answer.getOptionId()) ? item.getScore() : BigDecimal.ZERO;
case "input":
// 填空:文本匹配
return checkTextMatch(item, answer.getAnswerText()) ? item.getScore() : BigDecimal.ZERO;
// ... 其他类型
}
}
```
### 4. 排名计算
```sql
-- 更新排名
UPDATE psy_questionnaire_answer qa
SET qa.rank = (
SELECT COUNT(*) + 1
FROM psy_questionnaire_answer qa2
WHERE qa2.questionnaire_id = qa.questionnaire_id
AND (
qa2.total_score > qa.total_score
OR (qa2.total_score = qa.total_score AND qa2.submit_time < qa.submit_time)
)
)
WHERE qa.questionnaire_id = #{questionnaireId}
AND qa.status = '1'
```
---
## 📌 实施步骤
1.**创建问卷答案详情表**SQL
2.**修改量表列表查询,包含问卷**(后端)
3.**修改量表管理页面,显示问卷**(前端)
4.**创建问卷答题功能**(后端+前端)
5.**实现自动计分功能**(后端)
6.**实现主观题评分功能**(后端+前端)
7.**实现成绩排名功能**(后端+前端)
---
## ⚠️ 注意事项
1. 问卷和量表的数据结构不同,需要统一转换
2. 组卷方式(随机、手动、混合)需要在获取题目时实现
3. 主观题评分需要权限控制
4. 排名计算要考虑性能,可能需要定时任务
5. 填空题的文本匹配需要考虑容错性
---
**创建时间**: 2025-01-XX
**最后更新**: 2025-01-XX