# 问卷功能完整实现方案 ## 📋 需求概述 系统需要支持完整的问卷功能,包括: 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 scaleList = scaleService.selectScaleList(scale); // 如果需要包含问卷 if (includeQuestionnaire != null && includeQuestionnaire) { List questionnaireList = questionnaireService.selectQuestionnaireList(...); // 转换为统一的Scale格式,添加sourceType标识 // 合并到scaleList } return getDataTable(scaleList); } ``` **前端修改**: ```javascript // scale/index.vue // 在表格中添加类型列 ``` ### 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