fuliqi
2024-07-01 9dee3e46fdb59eb67b26f8c1958007025d1b7c29
阅卷补充题目答案,开始考试分页bug,开始考试补充数据
12个文件已修改
1个文件已添加
1 文件已重命名
415 ■■■■■ 已修改文件
src/main/java/com/ycl/jxkg/controller/admin/ExamController.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ycl/jxkg/controller/wx/student/ExamPaperAnswerController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ycl/jxkg/domain/entity/ExamPaperScore.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ycl/jxkg/domain/exam/PaperQuestionSettingDTO.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ycl/jxkg/domain/exam/SettingDTO.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ycl/jxkg/domain/vo/QuestionAnswerCopyVO.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ycl/jxkg/domain/vo/admin/exam/ExamPaperMarkNavbarVO.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ycl/jxkg/domain/vo/admin/exam/ExamPaperMarkVO.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ycl/jxkg/mapper/ExamPaperScoreMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ycl/jxkg/service/impl/ExamServiceImpl.java 274 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/ClassesUserMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/ExamMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/ExamPaperScoreDetailMapper.xml 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/ExamPaperScoreMapper.xml 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ycl/jxkg/controller/admin/ExamController.java
@@ -96,6 +96,7 @@
    public Result getMarkPaperInfo(@PathVariable("examId") Integer examId, @PathVariable("userId") Integer userId) {
        return examService.getMarkPaperInfo(examId, userId);
    }
    @PostMapping("/mark/paper")
    @ApiOperation(value = "提交批改", notes = "提交批改")
    public Result submitMarkPaper(@RequestBody ExamPaperMarkVO examPaperMark) {
src/main/java/com/ycl/jxkg/controller/wx/student/ExamPaperAnswerController.java
@@ -58,7 +58,7 @@
//            vo.setUserScore(ExamUtil.scoreToVM(e.getUserScore()));
//            vo.setPaperScore(ExamUtil.scoreToVM(e.getPaperScore()));
            vo.setSubjectName(subject.getName());
            vo.setCreateTime(DateTimeUtil.dateFormat(e.getCreateTime()));
//            vo.setCreateTime(DateTimeUtil.dateFormat(e.get));
            return vo;
        });
        return Result.ok(page);
src/main/java/com/ycl/jxkg/domain/entity/ExamPaperScore.java
@@ -35,14 +35,14 @@
    /**
     * 最终得分
     */
    @TableField("user_score")
    private BigDecimal userScore;
    @TableField("score")
    private BigDecimal score;
    /**
     * 试卷总分
     */
    @TableField("paper_score")
    private BigDecimal paperScore;
    @TableField("total_score")
    private BigDecimal totalScore;
    /**
     * 做对题目数量
@@ -71,8 +71,8 @@
    /**
     * 学生
     */
    @TableField("create_user")
    private Integer createUser;
    @TableField("user_id")
    private Integer userId;
    /**
     * 批改人
@@ -82,18 +82,24 @@
    /**
     * 批改时间
     */
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    private Date createTime;
    @TableField(value = "judge_time", fill = FieldFill.INSERT)
    private Date judgeTime;
    /**
     * 交卷时间
     */
    @TableField(value = "answer_time")
    private Date answerTime;
    @TableField(value = "submit_time")
    private Date submitTime;
    /**
     * 试卷内容
     */
    @TableField(value = "paper_content")
    private String paperContent;
    /**
     * 导航栏
     */
    @TableField(value = "navbar")
    private String navbar;
}
src/main/java/com/ycl/jxkg/domain/exam/PaperQuestionSettingDTO.java
@@ -9,11 +9,15 @@
public class PaperQuestionSettingDTO {
    //标题(单选题(20分)...)
    private String title;
    //题目类别
    private Integer questionType;
    //随机试卷题目数量
    private Integer num;
    //随机试卷题目分数
    private BigDecimal score;
    //题目难度
    private Integer difficult;
    //学科id
    private Integer subjectId;
}
src/main/java/com/ycl/jxkg/domain/exam/SettingDTO.java
New file
@@ -0,0 +1,17 @@
package com.ycl.jxkg.domain.exam;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class SettingDTO {
    //随机试卷题目数量
    private Integer num;
    //随机试卷题目分数
    private BigDecimal score;
    //题目难度
    private Integer difficult;
    //学科id
    private Integer subjectId;
}
src/main/java/com/ycl/jxkg/domain/vo/QuestionAnswerCopyVO.java
@@ -14,6 +14,7 @@
    /** 题目ID */
    private Integer id;
    private Integer difficult;
    /** 解析 */
    private String analyze;
src/main/java/com/ycl/jxkg/domain/vo/admin/exam/ExamPaperMarkNavbarVO.java
File was renamed from src/main/java/com/ycl/jxkg/domain/vo/admin/exam/ExamPaperMarkAnswerVO.java
@@ -3,7 +3,7 @@
import lombok.Data;
@Data
public class ExamPaperMarkAnswerVO {
public class ExamPaperMarkNavbarVO {
    private Boolean right;
    private Integer itemOrder;
}
src/main/java/com/ycl/jxkg/domain/vo/admin/exam/ExamPaperMarkVO.java
@@ -37,6 +37,6 @@
    private BigDecimal deductScore;
    /** 题目 */
    private List<PaperFixQuestionVO> titleItems;
    /** 答案集合(用于前端跳转对应题目) */
    private List<ExamPaperMarkAnswerVO> answers;
    /** 题目集合(用于前端跳转对应题目) */
    private List<ExamPaperMarkNavbarVO> navbar;
}
src/main/java/com/ycl/jxkg/mapper/ExamPaperScoreMapper.java
@@ -26,4 +26,6 @@
    List<ExamPaperAnswerPageResponseVO> adminPage(ExamPaperAnswerPageRequestVO requestVM);
    List<ExamPaperAnswerPageResponseVO> pageExamPaper(ExamPaperAnswerPageRequestVO model);
    ExamPaperScore getByExamIdUserId(@Param("examId") Integer examId, @Param("userId") Integer userId);
}
src/main/java/com/ycl/jxkg/service/impl/ExamServiceImpl.java
@@ -1,6 +1,7 @@
package com.ycl.jxkg.service.impl;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
@@ -16,9 +17,10 @@
import com.ycl.jxkg.domain.form.ExamForm;
import com.ycl.jxkg.domain.form.ForceSubmitForm;
import com.ycl.jxkg.domain.query.ExamQuery;
import com.ycl.jxkg.domain.question.QuestionItemObject;
import com.ycl.jxkg.domain.question.QuestionObject;
import com.ycl.jxkg.domain.vo.*;
import com.ycl.jxkg.domain.vo.admin.exam.ExamPaperMarkAnswerVO;
import com.ycl.jxkg.domain.vo.admin.exam.ExamPaperMarkNavbarVO;
import com.ycl.jxkg.domain.vo.admin.exam.ExamPaperMarkVO;
import com.ycl.jxkg.enums.DeductTypeEnum;
import com.ycl.jxkg.enums.ExamPaperTypeEnum;
@@ -28,6 +30,7 @@
import com.ycl.jxkg.enums.general.ExamSubmitTempStatusEnum;
import com.ycl.jxkg.mapper.*;
import com.ycl.jxkg.server.WebsocketServer;
import com.ycl.jxkg.service.ExamPaperScoreService;
import com.ycl.jxkg.service.ExamPaperService;
import com.ycl.jxkg.service.ExamService;
import com.ycl.jxkg.utils.PageUtil;
@@ -63,8 +66,8 @@
    private final WebsocketServer websocketServer;
    private final UserMapper userMapper;
    private final ExamPaperScoreMapper examPaperScoreMapper;
    private final ExamPaperScoreDetailMapper examPaperScoreDetailMapper;
    private final ExamPaperScoreService examPaperScoreService;
    private static final String ANSWER_SPLIT = ",";
    /**
     * 添加
     *
@@ -194,13 +197,13 @@
        startExamVO.setId(exam.getId());
        startExamVO.setSuggestTime(examPaper.getSuggestTime());
        // 试卷内容
        List<PaperFixQuestionVO> examData;
        List<PaperFixQuestionVO> examData = new ArrayList<>();
        // 拿到题目副本数据
        List<QuestionAnswerCopyVO> questionAnswerCopyVOList = new ArrayList<>(32);
        // 将题目转换为可临时保存的题目结构。固定试卷和随序试卷的题目是直接保存到content字段的
        if (ExamPaperTypeEnum.Fixed.getCode().equals(examPaper.getPaperType())
                || ExamPaperTypeEnum.RandomOrder.getCode().equals(examPaper.getPaperType())) {
            if (StringUtils.hasText(examPaper.getContent())) {
            if (!StringUtils.hasText(examPaper.getContent())) {
                throw new RuntimeException("试卷题目为空");
            }
            // 转换
@@ -227,6 +230,8 @@
                    DoQuestionVO doQuestionVO = new DoQuestionVO();
                    doQuestionVO.setTitle(item.getTitle());
                    doQuestionVO.setQuestionType(item.getQuestionType());
                    //从配置里拿题目分数
                    doQuestionVO.setQuestionScore(paperSetting.getScore());
                    if (StringUtils.hasText(item.getContent())) {
                        QuestionObject questionObject = JSON.parseObject(item.getContent(), QuestionObject.class);
                        doQuestionVO.setQuestionItemList(questionObject.getQuestionItemObjects());
@@ -237,8 +242,19 @@
                    // 题目副本
                    QuestionAnswerCopyVO copy = new QuestionAnswerCopyVO();
                    copy.setId(item.getId());
                    copy.setDifficult(item.getDifficult());
                    copy.setAnalyze(JSON.parseObject(item.getContent(), PaperQuestion.class).getAnalyze());
                    copy.setCorrect(item.getCorrect());
                    //填空的答案在Json里
                    if (QuestionTypeEnum.GapFilling.getCode().equals(item.getQuestionType())) {
                        List<String> gapAnswer = new ArrayList<>();
                        for (QuestionItemObject questionItemObject : doQuestionVO.getQuestionItemList()) {
                            gapAnswer.add(questionItemObject.getContent());
                        }
                        copy.setCorrect(String.join(ANSWER_SPLIT, gapAnswer));
                    } else {
                        copy.setCorrect(item.getCorrect());
                    }
                    questionAnswerCopyVOList.add(copy);
                    return doQuestionVO;
@@ -246,26 +262,25 @@
                paperFixQuestionVO.setQuestionList(childQuestions);
                examData.add(paperFixQuestionVO);
            }
            ExamSubmitTemp examSubmitTemp = new ExamSubmitTemp();
            examSubmitTemp.setExamId(id);
            examSubmitTemp.setStatus(ExamSubmitTempStatusEnum.temp);
            examSubmitTemp.setExamSubmit(JSON.toJSONString(examData));
            examSubmitTemp.setCreateTime(new Date());
            examSubmitTemp.setUserId(webContext.getCurrentUser().getId());
            examSubmitTemp.setMarkPaperStatus(ExamSubmitTempStatusEnum.temp);
            examSubmitTemp.setQuestionAnswerCopy(JSON.toJSONString(questionAnswerCopyVOList));
            examSubmitTempMapper.insert(examSubmitTemp);
            startExamVO.setTitleList(examData);
            return Result.ok(startExamVO);
        }
        return Result.ok();
        ExamSubmitTemp examSubmitTemp = new ExamSubmitTemp();
        examSubmitTemp.setExamId(id);
        examSubmitTemp.setStatus(ExamSubmitTempStatusEnum.temp);
        examSubmitTemp.setExamSubmit(JSON.toJSONString(examData));
        examSubmitTemp.setCreateTime(new Date());
        examSubmitTemp.setUserId(webContext.getCurrentUser().getId());
        examSubmitTemp.setMarkPaperStatus(ExamSubmitTempStatusEnum.temp);
        examSubmitTemp.setQuestionAnswerCopy(JSON.toJSONString(questionAnswerCopyVOList));
        examSubmitTempMapper.insert(examSubmitTemp);
        startExamVO.setTitleList(examData);
        return Result.ok(startExamVO);
    }
    /**
     * 将数据库存储的题目,转为可临时保存的题目结构
     *
     * @param examPaper 试卷
     * @param examPaper                试卷
     * @param questionAnswerCopyVOList 题目副本集合
     * @return
     */
@@ -282,7 +297,8 @@
                DoQuestionVO doQuestionVO = new DoQuestionVO();
                doQuestionVO.setTitle(question.getTitle());
                doQuestionVO.setQuestionType(item.getQuestionType());
                //增加题目分数
                doQuestionVO.setQuestionScore(question.getScore());
                // 填空题需要抹除content(因为是答案)
                if (QuestionTypeEnum.GapFilling.getCode().equals(doQuestionVO.getQuestionType())) {
                    question.getItems().stream().forEach(option -> {
@@ -296,8 +312,19 @@
                // 题目副本
                QuestionAnswerCopyVO copy = new QuestionAnswerCopyVO();
                copy.setId(question.getId());
                copy.setAnalyze(question.getAnalyze());
                copy.setCorrect(question.getCorrect());
                copy.setDifficult(question.getDifficult());
                //填空的答案在Json里
                if (QuestionTypeEnum.GapFilling.getCode().equals(item.getQuestionType())) {
                    List<String> gapAnswer = new ArrayList<>();
                    for (QuestionItemObject questionItemObject : doQuestionVO.getQuestionItemList()) {
                        gapAnswer.add(questionItemObject.getContent());
                    }
                    copy.setCorrect(String.join(ANSWER_SPLIT, gapAnswer));
                } else {
                    copy.setCorrect(question.getCorrect());
                }
                questionAnswerCopyVOList.add(copy);
                return doQuestionVO;
@@ -379,8 +406,10 @@
        // 阅卷后才往exam_paper_answer保存考试成绩、以及保存到exam_paper_customer_answer
        // 现在只需要保存到一张临时表
        // 该接口是主动提交,所以状态都设置为完成,以便后续老师阅卷
        //TODO
        saveTempExam(submitData, ExamSubmitTempStatusEnum.finish);
        //TODO:考试状态设定为结束
        return Result.ok();
    }
@@ -392,7 +421,6 @@
     */
    @Override
    public Result timingSubmit(StartExamVO submitData) {
        //TODO
        saveTempExam(submitData, ExamSubmitTempStatusEnum.temp);
        return Result.ok();
    }
@@ -407,19 +435,19 @@
        ExamSubmitTemp one = new LambdaQueryChainWrapper<>(examSubmitTempMapper)
                .eq(ExamSubmitTemp::getExamId, submitData.getId())
                .eq(ExamSubmitTemp::getUserId, webContext.getCurrentUser().getId())
                .eq(ExamSubmitTemp::getDeleted,0)
                .eq(ExamSubmitTemp::getDeleted, 0)
                .one();
        if (Objects.nonNull(one)) {
            long doTimeL = one.getUpdateTime().getTime() - one.getCreateTime().getTime();
            Integer doTime = (int) doTimeL;
            //TODO
            if (ExamSubmitTempStatusEnum.finish.equals(one.getStatus())) {
                return;
            }
            one.setDoTime(doTime);
            Date now = new Date();
            one.setExamSubmit(JSON.toJSONString(submitData.getTitleList()));
            one.setUpdateTime(new Date());
            one.setUpdateTime(now);
            long doTimeL = now.getTime() - one.getCreateTime().getTime();
            Integer doTime = (int) doTimeL;
            one.setDoTime(doTime);
            one.setStatus(status);
            examSubmitTempMapper.updateById(one);
        } else {
@@ -429,7 +457,6 @@
            examSubmitTemp.setStatus(status);
            examSubmitTemp.setUserId(webContext.getCurrentUser().getId());
            examSubmitTemp.setExamSubmit(JSON.toJSONString(submitData.getTitleList()));
            //TODO
            examSubmitTemp.setMarkPaperStatus(ExamSubmitTempStatusEnum.temp);
            examSubmitTempMapper.insert(examSubmitTemp);
        }
@@ -446,12 +473,12 @@
            throw new RuntimeException("考试试卷不存在");
        }
        List<ExamSubmitTemp> examSubmitTempList = new LambdaQueryChainWrapper<>(examSubmitTempMapper)
                .eq(ExamSubmitTemp::getDeleted,0)
                .eq(ExamSubmitTemp::getExamId, id)
                .list();
        // 参考人数
        Integer joinExamNum = examSubmitTempList.size();
        // 参考但未完成提交人数
        //TODO
        Integer joinButNotFinishedNum = Math.toIntExact(examSubmitTempList.stream().filter(item -> ExamSubmitTempStatusEnum.temp.equals(item.getStatus())).count());
        List<StudentExamInfoVO> studentExamList = classesUserMapper.getClassesUserList(exam.getClassesId());
@@ -488,81 +515,95 @@
        if (Objects.isNull(userExam)) {
            throw new RuntimeException("该学员考试记录不存在");
        }
        ExamVO exam = examMapper.getById(examId);
        //如果已经阅过卷了,查成绩表
        Result<ExamPaperMarkVO> paperMarkVO1 = checkHasJudge(examId, userId, userExam);
        if (paperMarkVO1 != null) return paperMarkVO1;
        User student = userMapper.getUserById(userId);
        ExamVO exam = examMapper.getById(examId);
        //封装阅卷基本数据
        ExamPaperMarkVO paperMarkVO = createVO(userExam, exam, student);
        //TODO:补充题目答案、解析
        List<PaperFixQuestionVO> titleItems = paperMarkVO.getTitleItems();
        for (PaperFixQuestionVO titleItem : titleItems) {
            for (DoQuestionVO doQuestionVO : titleItem.getQuestionList()) {
            }
        }
        List<QuestionAnswerCopyVO> answerList = JSONArray.parseArray(userExam.getQuestionAnswerCopy(), QuestionAnswerCopyVO.class);
        //补充题目答案、解析
        addAnswer(paperMarkVO, answerList);
        //阅卷,客观题打分
        Result InnerError = markPaper(paperMarkVO);
        if (InnerError != null) return InnerError;
        return Result.ok(paperMarkVO);
    }
    //提交批改
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result submitMarkPaper(ExamPaperMarkVO examPaperMark) {
        Integer userId = webContext.getCurrentUser().getId();
        //插入exam_paper_answer(成绩表)
        ExamPaperScore examPaperScore = new ExamPaperScore();
        BeanUtils.copyProperties(examPaperMark,examPaperScore);
        examPaperScore.setUserScore(new BigDecimal(examPaperMark.getScore()));
        examPaperScore.setPaperScore(new BigDecimal(examPaperMark.getTotalScore()));
        examPaperScore.setJudgeUser(userId);
        examPaperScore.setCreateUser(examPaperMark.getUserId());
        examPaperScore.setAnswerTime(examPaperMark.getSubmitTime());
        examPaperScore.setPaperContent(JSON.toJSONString(examPaperMark.getTitleItems()));
        long questionCorrect =0;
        long questionCount=0;
        if(!CollectionUtils.isEmpty(examPaperMark.getAnswers())){
            questionCorrect = examPaperMark.getAnswers().stream().filter(ExamPaperMarkAnswerVO::getRight).count();
            questionCount = examPaperMark.getAnswers().size();
    //补充题目答案、解析
    private void addAnswer(ExamPaperMarkVO paperMarkVO, List<QuestionAnswerCopyVO> answerList) {
        List<PaperFixQuestionVO> titleItems = paperMarkVO.getTitleItems();
        for (PaperFixQuestionVO titleItem : titleItems) {
            for (DoQuestionVO doQuestionVO : titleItem.getQuestionList()) {
                Integer questionId = doQuestionVO.getId();
                Optional<QuestionAnswerCopyVO> first = answerList.stream().filter(answer -> questionId.equals(answer.getId())).findFirst();
                if (first.isPresent()) {
                    QuestionAnswerCopyVO answerCopyVO = first.get();
                    doQuestionVO.setQuestionAnswer(answerCopyVO.getCorrect());
                    doQuestionVO.setAnalyze(answerCopyVO.getAnalyze());
                    doQuestionVO.setDifficult(answerCopyVO.getDifficult());
                }
            }
        }
        examPaperScore.setQuestionCorrect(Integer.valueOf(questionCorrect+""));
        examPaperScore.setQuestionCount(Integer.valueOf(questionCount+""));
        examPaperScoreMapper.insert(examPaperScore);
        return Result.ok();
    }
    //检查是否阅卷
    private Result<ExamPaperMarkVO> checkHasJudge(Integer examId, Integer userId, ExamSubmitTemp userExam) {
        if (ExamSubmitTempStatusEnum.finish.equals(userExam.getMarkPaperStatus())) {
            ExamPaperScore examPaperScore = examPaperScoreMapper.getByExamIdUserId(examId, userId);
            ExamPaperMarkVO paperMarkVO = new ExamPaperMarkVO();
            BeanUtils.copyProperties(examPaperScore, paperMarkVO);
            paperMarkVO.setTotalScore(examPaperScore.getTotalScore() + "");
            paperMarkVO.setScore(examPaperScore.getScore() + "");
            List<PaperFixQuestionVO> paperFixQuestionVOS = JSONArray.parseArray(examPaperScore.getPaperContent(), PaperFixQuestionVO.class);
            paperMarkVO.setTitleItems(paperFixQuestionVOS);
            paperMarkVO.setNavbar(JSONArray.parseArray(examPaperScore.getNavbar(), ExamPaperMarkNavbarVO.class));
            return Result.ok(paperMarkVO);
        }
        return null;
    }
    //阅卷
    private Result markPaper(ExamPaperMarkVO paperMarkVO) {
        List<PaperFixQuestionVO> titleItems = paperMarkVO.getTitleItems();
        //初始化题目序号
        Integer num = 1;
        List<ExamPaperMarkAnswerVO> answers = new ArrayList<>();
        BigDecimal score = BigDecimal.ZERO;
        //前端导航数组
        List<ExamPaperMarkNavbarVO> navbar = new ArrayList<>();
        //过滤掉题目为空的题目类型
        titleItems = titleItems.stream().filter(paperFixQuestionVO -> !CollectionUtils.isEmpty(paperFixQuestionVO.getQuestionList())).collect(Collectors.toList());
        for (PaperFixQuestionVO titleItem : titleItems) {
            for (DoQuestionVO doQuestionVO : titleItem.getQuestionList()) {
                //准备题目序号供前端跳转使用
                ExamPaperMarkAnswerVO answerVO = new ExamPaperMarkAnswerVO();
                ExamPaperMarkNavbarVO navbarVO = new ExamPaperMarkNavbarVO();
                //获取试卷类型
                Integer questionType = doQuestionVO.getQuestionType();
                /* 如果是简答、计算、分析,不设置right只设置题目序号 */
                if (QuestionTypeEnum.ShortAnswer.getCode().equals(questionType) || QuestionTypeEnum.Calculate.getCode().equals(questionType) || QuestionTypeEnum.Analysis.getCode().equals(questionType)) {
                    answerVO.setItemOrder(num);
                    navbarVO.setItemOrder(num);
                    doQuestionVO.setItemOrder(num);
                }
                /* 如果是单选、语音、判断(判断答案是A、B) */
                else if (QuestionTypeEnum.SingleChoice.getCode().equals(questionType) || QuestionTypeEnum.Audio.getCode().equals(questionType) || QuestionTypeEnum.TrueFalse.getCode().equals(questionType)) {
                    answerVO.setItemOrder(num);
                    navbarVO.setItemOrder(num);
                    doQuestionVO.setItemOrder(num);
                    if (StringUtils.isEmpty(doQuestionVO.getQuestionAnswer())) {
                        return Result.fail(SystemCode.InnerError.getCode(), doQuestionVO.getTitle() + ",此题目缺少答案,请先完善");
                        return Result.fail(SystemCode.InnerError.getCode(), "题目id为:" + doQuestionVO.getId() + "的题目缺少答案,请先完善");
                    }
                    trueOrFalse(doQuestionVO, answerVO, doQuestionVO.getQuestionAnswer().equals(doQuestionVO.getAnswer()));
                    trueOrFalse(score,doQuestionVO, navbarVO, doQuestionVO.getQuestionAnswer().equals(doQuestionVO.getAnswer()));
                }
                /* 如果是多选 */
                else if (QuestionTypeEnum.MultipleChoice.getCode().equals(questionType)) {
                    answerVO.setItemOrder(num);
                    navbarVO.setItemOrder(num);
                    doQuestionVO.setItemOrder(num);
                    if (StringUtils.isEmpty(doQuestionVO.getQuestionAnswer())) {
                        return Result.fail(SystemCode.InnerError.getCode(), doQuestionVO.getTitle() + ",此题目缺少答案,请先完善");
                        return Result.fail(SystemCode.InnerError.getCode(), "题目id为:" + doQuestionVO.getId() + "的题目缺少答案,请先完善");
                    }
                    //学生答案
                    List<String> answerList = doQuestionVO.getAnswerList();
@@ -571,7 +612,9 @@
                    List<String> questionAnswerList = Arrays.asList(questionAnswer.split(","));
                    //学生答案为空,判断为错
                    if (CollectionUtils.isEmpty(answerList)) {
                        trueOrFalse(doQuestionVO, answerVO, false);
                        trueOrFalse(score,doQuestionVO, navbarVO, false);
                        num++;
                        navbar.add(navbarVO);
                        continue;
                    }
                    //答案数量,不需要考虑顺序
@@ -580,7 +623,9 @@
                    Set<String> set2 = new HashSet<>(questionAnswerList);
                    //答案完全一致,满分
                    if (set1.equals(set2)) {
                        trueOrFalse(doQuestionVO, answerVO, true);
                        trueOrFalse(score,doQuestionVO, navbarVO, true);
                        num++;
                        navbar.add(navbarVO);
                        continue;
                    }
                    if (paperMarkVO.getDeductType() == null) {
@@ -588,18 +633,19 @@
                    }
                    //如果多选得分类型为 答错不得分
                    if (Integer.valueOf(DeductTypeEnum.AllCorrect.getCode()).equals(paperMarkVO.getDeductType())) {
                        trueOrFalse(doQuestionVO, answerVO, false);
                        trueOrFalse(score,doQuestionVO, navbarVO, false);
                    }
                    //如果多选得分类型为 漏选得固定分值,包含错误选项不得分
                    else if (Integer.valueOf(DeductTypeEnum.PartCorrect.getCode()).equals(paperMarkVO.getDeductType())) {
                        //学生答案移除所有正确答案,如果还有元素说明包含错误选项
                        answerList.removeAll(questionAnswerList);
                        if (!CollectionUtils.isEmpty(answerList)) {
                            trueOrFalse(doQuestionVO, answerVO, false);
                            trueOrFalse(score,doQuestionVO, navbarVO, false);
                        } else {
                            answerVO.setRight(false);
                            navbarVO.setRight(false);
                            doQuestionVO.setRight(false);
                            //漏选得固定分
                            score = score.add(paperMarkVO.getDeductScore());
                            doQuestionVO.setScore(paperMarkVO.getDeductScore());
                        }
                    }
@@ -608,9 +654,9 @@
                        //学生答案移除所有正确答案,如果还有元素说明包含错误选项
                        answerList.removeAll(questionAnswerList);
                        if (!CollectionUtils.isEmpty(answerList)) {
                            trueOrFalse(doQuestionVO, answerVO, false);
                            trueOrFalse(score,doQuestionVO, navbarVO, false);
                        } else {
                            answerVO.setRight(false);
                            navbarVO.setRight(false);
                            doQuestionVO.setRight(false);
                            //漏选得分
                            doQuestionVO.setScore(paperMarkVO.getDeductScore().multiply(new BigDecimal(answerCount)));
@@ -619,10 +665,10 @@
                }
                /* 如果是填空 */
                else if (QuestionTypeEnum.GapFilling.getCode().equals(questionType)) {
                    answerVO.setItemOrder(num);
                    navbarVO.setItemOrder(num);
                    doQuestionVO.setItemOrder(num);
                    if (StringUtils.isEmpty(doQuestionVO.getQuestionAnswer())) {
                        return Result.fail(SystemCode.InnerError.getCode(), doQuestionVO.getTitle() + ",此题目缺少答案,请先完善");
                        return Result.fail(SystemCode.InnerError.getCode(), "题目id为:" + doQuestionVO.getId() + "的题目缺少答案,请先完善");
                    }
                    //学生答案
                    List<String> answerList = doQuestionVO.getAnswerList();
@@ -631,21 +677,23 @@
                    List<String> questionAnswerList = Arrays.asList(questionAnswer.split(","));
                    //学生答案为空,判断为错
                    if (CollectionUtils.isEmpty(answerList)) {
                        trueOrFalse(doQuestionVO, answerVO, false);
                        trueOrFalse(score,doQuestionVO, navbarVO, false);
                        num++;
                        navbar.add(navbarVO);
                        continue;
                    }
                    //总空的数量
                    int questionAnswerCount = questionAnswerList.size();
                    //答案完全一致,满分
                    if (answerList.equals(questionAnswerList)) {
                        trueOrFalse(doQuestionVO, answerVO, true);
                        trueOrFalse(score,doQuestionVO, navbarVO, true);
                    } else {
                        answerVO.setRight(false);
                        navbarVO.setRight(false);
                        doQuestionVO.setRight(false);
                        //做对的数量,需要按顺序比较
                        int count = 0;
                        for (int i = 0; i < answerList.size(); i++) {
                            if(answerList.get(i).equals(questionAnswerList.get(i))){
                            if (answerList.get(i).equals(questionAnswerList.get(i))) {
                                count++;
                            }
                        }
@@ -653,29 +701,32 @@
                        BigDecimal questionScore = doQuestionVO.getQuestionScore();
                        //每个空的分数
                        BigDecimal scoreEach = questionScore.divide(new BigDecimal(questionAnswerCount), 1, RoundingMode.DOWN);
                        BigDecimal score = scoreEach.multiply(new BigDecimal(count));
                        doQuestionVO.setScore(score);
                        //填空得分
                        BigDecimal gapScore = scoreEach.multiply(new BigDecimal(count));
                        doQuestionVO.setScore(gapScore);
                    }
                }
                num++;
                answers.add(answerVO);
                navbar.add(navbarVO);
            }
        }
        paperMarkVO.setAnswers(answers);
        paperMarkVO.setTitleItems(titleItems);
        paperMarkVO.setNavbar(navbar);
        return null;
    }
    //设置全对或全错
    private void trueOrFalse(DoQuestionVO doQuestionVO, ExamPaperMarkAnswerVO answerVO, Boolean isCorrect) {
    private void trueOrFalse(BigDecimal score,DoQuestionVO doQuestionVO, ExamPaperMarkNavbarVO orderVO, Boolean isCorrect) {
        if (isCorrect) {
            //正确
            answerVO.setRight(isCorrect);
            orderVO.setRight(isCorrect);
            doQuestionVO.setRight(isCorrect);
            doQuestionVO.setScore(doQuestionVO.getQuestionScore());
            score = score.add(doQuestionVO.getQuestionScore());
        } else {
            //错误
            answerVO.setRight(isCorrect);
            orderVO.setRight(isCorrect);
            doQuestionVO.setRight(isCorrect);
            doQuestionVO.setScore(BigDecimal.ZERO);
        }
@@ -683,21 +734,56 @@
    //封装阅卷返回数据
    private ExamPaperMarkVO createVO(ExamSubmitTemp userExam, ExamVO exam, User student) {
        Integer paperId = exam.getExamPaperId();
        ExamPaper examPaper = examPaperMapper.selectById(paperId);
        ExamPaperMarkVO paperMarkVO = new ExamPaperMarkVO();
        BeanUtils.copyProperties(userExam, paperMarkVO);
        paperMarkVO.setPaperId(exam.getExamPaperId());
        //TODO: 试卷总分、(多选得分类型、多选得分分数)需要取ExamSubmitTemp
        paperMarkVO.setExamName(exam.getExamName());
        paperMarkVO.setPaperType(exam.getExamPaperType());
        paperMarkVO.setSubmitTime(userExam.getUpdateTime());
        paperMarkVO.setUserName(student.getRealName());
        paperMarkVO.setTitleItems(JSON.parseArray(userExam.getExamSubmit(), PaperFixQuestionVO.class));
        paperMarkVO.setTotalScore("100");
        paperMarkVO.setDeductType(DeductTypeEnum.AllCorrect.getCode());
        paperMarkVO.setDeductScore(BigDecimal.ZERO);
        paperMarkVO.setTotalScore(examPaper.getScore() + "");
        paperMarkVO.setDeductType(examPaper.getDeductType());
        paperMarkVO.setDeductScore(examPaper.getDeductTypeScore());
        return paperMarkVO;
    }
    //提交批改
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result submitMarkPaper(ExamPaperMarkVO examPaperMark) {
        Integer userId = webContext.getCurrentUser().getId();
        //插入exam_paper_answer(成绩表)
        ExamPaperScore examPaperScore = new ExamPaperScore();
        BeanUtils.copyProperties(examPaperMark, examPaperScore);
        examPaperScore.setScore(new BigDecimal(examPaperMark.getScore()));
        examPaperScore.setTotalScore(new BigDecimal(examPaperMark.getTotalScore()));
        examPaperScore.setJudgeUser(userId);
        examPaperScore.setJudgeTime(new Date());
        examPaperScore.setPaperContent(JSON.toJSONString(examPaperMark.getTitleItems()));
        examPaperScore.setNavbar(JSON.toJSONString(examPaperMark.getNavbar()));
        long questionCorrect = 0;
        long questionCount = 0;
        if (!CollectionUtils.isEmpty(examPaperMark.getNavbar())) {
            questionCorrect = examPaperMark.getNavbar().stream().filter(ExamPaperMarkNavbarVO::getRight).count();
            questionCount = examPaperMark.getNavbar().size();
        }
        examPaperScore.setQuestionCorrect(Integer.valueOf(questionCorrect + ""));
        examPaperScore.setQuestionCount(Integer.valueOf(questionCount + ""));
        //找之前有无批改记录
        ExamPaperScore score = examPaperScoreMapper.getByExamIdUserId(examPaperMark.getExamId(), examPaperMark.getUserId());
        if (score != null) {
            examPaperScore.setId(score.getId());
            examPaperScoreMapper.updateById(examPaperScore);
        } else {
            examPaperScoreMapper.insert(examPaperScore);
        }
        return Result.ok();
    }
    @Override
    public Result monitorList(ExamQuery query) {
        IPage<ExamSubmitTempVO> page = PageUtil.getPage(query, ExamSubmitTempVO.class);
src/main/resources/mapper/ClassesUserMapper.xml
@@ -67,7 +67,7 @@
            INNER JOIN t_user TU ON TU.id = TCU.user_id AND TCU.classes_id = #{classesId}
            LEFT JOIN t_exam_submit_temp EST ON EST.user_id = TU.id
        WHERE
            TCU.deleted = 0
            TCU.deleted = 0 and EST.deleted = 0
    </select>
    <select id="getClassesByUserId" resultType="java.lang.Integer">
src/main/resources/mapper/ExamMapper.xml
@@ -98,7 +98,7 @@
        FROM
            t_exam TE
        INNER JOIN t_classes TC ON TC.id = TE.classes_id AND TC.deleted = 0 AND TC.status = 'normal'
        INNER JOIN t_classes_user TCU ON TC.id = TCU.classes_id AND TC.deleted = 0 AND TCU.user_id = #{userId}
        INNER JOIN t_classes_user TCU ON TC.id = TCU.classes_id  And TCU.deleted = 0 AND TC.deleted = 0 AND TCU.user_id = #{userId}
        INNER JOIN t_exam_paper TEP ON TEP.id = TE.exam_paper_id AND TEP.deleted = 0
        WHERE
            TE.deleted = 0
src/main/resources/mapper/ExamPaperScoreDetailMapper.xml
@@ -74,13 +74,13 @@
    <select id="selectCountByDate" resultType="com.ycl.jxkg.domain.other.KeyValue">
        SELECT answer_time as name, sum(question_count) as value
        SELECT submit_time as name, sum(question_count) as value
        from
            (
            SELECT question_count ,DATE_FORMAT(answer_time, '%Y-%m-%d') as answer_time from t_exam_paper_score
            WHERE answer_time between #{startTime} and #{endTime}
            SELECT question_count ,DATE_FORMAT(submit_time, '%Y-%m-%d') as submit_time from t_exam_paper_score
            WHERE submit_time between #{startTime} and #{endTime}
            ) a
        GROUP BY answer_time
        GROUP BY submit_time
    </select>
    <update id="updateScore" parameterType="java.util.List">
src/main/resources/mapper/ExamPaperScoreMapper.xml
@@ -2,28 +2,30 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ycl.jxkg.mapper.ExamPaperScoreMapper">
    <resultMap id="BaseResultMap" type="com.ycl.jxkg.domain.entity.ExamPaperScore">
        <id column="id" jdbcType="INTEGER" property="id"/>
        <result column="paper_id" jdbcType="INTEGER" property="examPaperId"/>
        <result column="paper_name" jdbcType="VARCHAR" property="paperName"/>
        <result column="paper_type" jdbcType="INTEGER" property="paperType"/>
        <result column="user_score" jdbcType="INTEGER" property="userScore"/>
        <result column="paper_score" jdbcType="INTEGER" property="paperScore"/>
        <result column="question_correct" jdbcType="INTEGER" property="questionCorrect"/>
        <result column="question_count" jdbcType="INTEGER" property="questionCount"/>
        <result column="do_time" jdbcType="INTEGER" property="doTime"/>
        <result column="status" jdbcType="INTEGER" property="status"/>
        <result column="create_user" jdbcType="INTEGER" property="createUser"/>
        <result column="judge_user" jdbcType="INTEGER" property="judgeUser"/>
        <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
        <result column="answer_time" jdbcType="TIMESTAMP" property="answerTime"/>
        <result column="exam_id" jdbcType="INTEGER" property="examId"/>
        <result column="exam_name" jdbcType="INTEGER" property="examName"/>
        <result column="paper_content" jdbcType="INTEGER" property="paperContent"/>
        <id column="id" property="id"/>
        <result column="paper_id" property="examPaperId"/>
        <result column="paper_name" property="paperName"/>
        <result column="paper_type" property="paperType"/>
        <result column="score" property="score"/>
        <result column="total_score" property="totalScore"/>
        <result column="question_correct" property="questionCorrect"/>
        <result column="question_count" property="questionCount"/>
        <result column="do_time" property="doTime"/>
        <result column="status" property="status"/>
        <result column="user_id" property="userId"/>
        <result column="judge_user" property="judgeUser"/>
        <result column="submit_time" property="submitTime"/>
        <result column="judge_time" property="judgeTime"/>
        <result column="exam_id" property="examId"/>
        <result column="exam_name" property="examName"/>
        <result column="paper_content" property="paperContent"/>
        <result column="navbar" property="navbar"/>
    </resultMap>
    <sql id="Base_Column_List">
        id, paper_id, paper_name, paper_type, user_score,paper_score,
        question_correct, question_count, do_time, status, create_user, create_time,
        judge_user,answer_time,paper_content,create_time
        id
        , paper_id, paper_name, paper_type, score,total_score,
        question_correct, question_count, do_time, status, user_id, exam_id,exam_name,
        judge_user,submit_time,paper_content,judge_time,navbar
    </sql>
    <select id="studentPage" resultMap="BaseResultMap"
@@ -32,32 +34,38 @@
        <include refid="Base_Column_List"/>
        FROM t_exam_paper_answer
        <where>
            and create_user = #{createUser}
            <if test="subjectId != null">
                and subject_id = #{subjectId}
            </if>
            and user_id = #{createUser}
        </where>
    </select>
    <select id="getByExamIdUserId" resultType="com.ycl.jxkg.domain.entity.ExamPaperScore">
        SELECT
        <include refid="Base_Column_List"/>
        from t_exam_paper_score
        <where>
            and user_id = #{userId}
            and exam_id = #{examId}
        </where>
    </select>
    <select id="selectAllCount" resultType="java.lang.Integer">
        SELECT count(*)
        from t_exam_paper_score
    </select>
    <select id="selectAllQuestionCount" resultType="java.lang.Integer">
        SELECT sum(question_count)
        from t_exam_paper_score
    </select>
    <select id="selectCountByDate" resultType="com.ycl.jxkg.domain.other.KeyValue">
        SELECT create_time as name, COUNT(create_time) as value
        SELECT submit_time as name, sum(question_count) as value
        from
            (
            SELECT DATE_FORMAT(create_time, '%Y-%m-%d') as create_time from t_exam_paper_score
            WHERE create_time between #{startTime} and #{endTime}
            SELECT question_count ,DATE_FORMAT(submit_time, '%Y-%m-%d') as submit_time from t_exam_paper_score
            WHERE submit_time between #{startTime} and #{endTime}
            ) a
        GROUP BY create_time
        GROUP BY submit_time
    </select>
@@ -65,7 +73,7 @@
        select
        <include refid="Base_Column_List"/>
        from t_exam_paper_score
        where paper_id = #{pid} and create_user=#{uid}
        where paper_id = #{pid} and user_id=#{uid}
        limit 1
    </select>