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

7.3 KiB
Raw Blame History

问卷功能完整实现方案

📋 需求概述

系统需要支持完整的问卷功能,包括:

  1. 问卷在量表管理中显示:创建的问卷能够出现在量表管理中
  2. 问卷答题功能:用户填写完问卷后,客观题自动打分,主观题传给管理员进行打分
  3. 多种题目类型支持:单选、多选、判断、填空、排序、计算、简答、问答、作文等
  4. 多种组卷形式:自助组卷、随机组卷、手动随机相结合
  5. 成绩排名统计:客观题系统自动实现打分,成绩自动排名统计

🎯 实现方案

阶段一:让问卷显示在量表管理中

方案1统一查询接口推荐

  • 修改量表列表查询,同时返回问卷数据
  • 添加类型标识字段(sourceType: 'scale' 或 'questionnaire'
  • 前端统一显示,根据类型标识区分操作

方案2创建统一视图

  • 在数据库创建视图,统一量表和问卷
  • 查询时使用视图

选择方案1,因为更灵活,不需要修改数据库结构。


阶段二:问卷答题功能

参考量表测评的实现方式:

  1. 开始问卷:创建问卷答题记录
  2. 获取题目:根据组卷方式获取题目列表
  3. 保存答案:实时保存用户答案
  4. 提交问卷
    • 客观题自动计分
    • 主观题标记为待评分
    • 计算客观题总分
    • 更新排名

阶段三:自动打分功能

客观题类型

  • radio单选:根据选项的is_correctoption_score计分
  • checkbox多选:全对得满分,部分对按比例得分
  • boolean判断:根据选项的is_correct计分
  • input填空:如果有标准答案,进行文本匹配(支持模糊匹配)
  • sort排序:顺序完全正确得满分,部分正确按比例得分
  • calculate计算:数值匹配,允许误差范围

主观题类型

  • text简答:需要管理员评分
  • textarea问答:需要管理员评分
  • essay作文:需要管理员评分
  • input无标准答案:需要管理员评分

阶段四:主观题评分管理

  1. 待评分列表:显示所有待评分的主观题
  2. 评分界面:管理员可以查看题目、答案,进行评分
  3. 批量评分:支持批量评分功能
  4. 评分后更新:评分后更新总分和排名

阶段五:成绩排名统计

  1. 排名计算
    • 按总分从高到低排序
    • 相同分数按提交时间排序(先提交的排名靠前)
  2. 排名更新:提交问卷或评分后自动更新排名
  3. 排名查询:支持按问卷查询排名列表

📁 需要创建/修改的文件

数据库

  • psy_questionnaire - 问卷表(已存在)
  • psy_questionnaire_item - 问卷题目表(已存在)
  • psy_questionnaire_option - 问卷选项表(已存在)
  • 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. 量表列表统一显示问卷

后端修改

// 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);
}

前端修改

// 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. 自动计分逻辑

// 客观题计分
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. 排名计算

-- 更新排名
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