package com.ibeetl.jlw.service; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.jlw.util.EnumUtil; import cn.jlw.util.ToolUtils; import cn.jlw.validate.ValidateConfig; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.ibeetl.admin.core.entity.CoreUser; import com.ibeetl.admin.core.service.CoreBaseService; import com.ibeetl.admin.core.util.PlatformException; import com.ibeetl.admin.core.util.TimeTool; import com.ibeetl.admin.core.web.JsonResult; import com.ibeetl.admin.core.web.JsonReturnCode; import com.ibeetl.jlw.dao.GeneralQuestionLogDao; import com.ibeetl.jlw.dao.GeneralQuestionSettingDao; import com.ibeetl.jlw.dao.GeneralResourcesQuestionSnapshotDao; import com.ibeetl.jlw.dao.QuestionLogSummaryDao; import com.ibeetl.jlw.entity.*; import com.ibeetl.jlw.entity.dto.QuestionSettingDTO; import com.ibeetl.jlw.enums.*; import com.ibeetl.jlw.service.questionQueue.generalQuestionSettingQueue.GeneralQuestionSettingRedisDelayQueueImpl; import com.ibeetl.jlw.web.query.*; import org.apache.commons.lang3.StringUtils; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.beetl.sql.core.SqlId; import org.beetl.sql.core.engine.PageQuery; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.io.*; import java.util.*; import static cn.hutool.core.util.ObjectUtil.defaultIfNull; import static cn.jlw.util.CacheUserUtil.getStudent; import static cn.jlw.util.QuestionUtil.shuffleQuestion; import static com.ibeetl.admin.core.util.ExcelUtil.getCellFormatValue; import static com.ibeetl.jlw.enums.QuestionLogAddTypeEnum.FINALLY_SUBMIT; import static com.ibeetl.jlw.enums.ResourcesQuestionSnapshotFromTypeEnum.*; import static com.ibeetl.jlw.enums.TuckOrErrorEnum.ERROR_TEST; import static com.ibeetl.jlw.enums.TuckOrErrorEnum.TUCK_TEST; /** * 通用题目配置 Service * 当分布式ID开启后请勿使用insert(*,true) */ @Service @Transactional @Validated public class GeneralQuestionSettingService extends CoreBaseService{ @Autowired private GeneralQuestionSettingDao generalQuestionSettingDao; @Autowired private GeneralResourcesQuestionSnapshotDao generalResourcesQuestionSnapshotDao; @Autowired private GeneralQuestionLogDao generalQuestionLogDao; @Autowired private QuestionLogSummaryDao questionLogSummaryDao; @Autowired private GeneralQuestionLogService generalQuestionLogService; @Autowired @Lazy private GeneralResourcesQuestionSnapshotService generalResourcesQuestionSnapshotService; @Autowired private ResourcesQuestionService resourcesQuestionService; @Autowired private GeneralQuestionSettingRedisDelayQueueImpl generalQuestionSettingRedisDelayQueue; public PageQueryqueryByCondition(PageQuery query){ PageQuery ret = generalQuestionSettingDao.queryByCondition(query); queryListAfter(ret.getList()); return ret; } public PageQueryqueryByConditionQuery(PageQuery query){ PageQuery ret = generalQuestionSettingDao.queryByConditionQuery(query); queryListAfter(ret.getList()); return ret; } public void deleteByList(List list){ String ids = ""; ToolUtils.deleteNullList(list); for(int i=0;null != list && i generalQuestionSettingList = new ArrayList<>(); try { generalQuestionSettingList = JSON.parseArray(generalQuestionSettingQuery.getGeneralQuestionSettingJsonStr(), GeneralQuestionSetting.class); } catch (Exception e) { try { generalQuestionSettingList.add(JSONObject.parseObject(generalQuestionSettingQuery.getGeneralQuestionSettingJsonStr(), GeneralQuestionSetting.class)); } catch (Exception e1) {} } ToolUtils.deleteNullList(generalQuestionSettingList); if(null != generalQuestionSettingList && generalQuestionSettingList.size()>0){ for(int i=0;i 0; if(!flag){ msg = "更新指定参数失败"; } }else{ msg = "指定参数为空"; } return msg; } public List getValues (Object paras){ return sqlManager.select(SqlId.of("jlw.generalQuestionSetting.getGeneralQuestionSettingValues"), GeneralQuestionSetting.class, paras); } public List getValuesByQuery (GeneralQuestionSettingQuery generalQuestionSettingQuery){ return generalQuestionSettingDao.getValuesByQuery(generalQuestionSettingQuery); } public List getValuesByQueryNotWithPermission (GeneralQuestionSettingQuery generalQuestionSettingQuery){ return generalQuestionSettingDao.getValuesByQueryNotWithPermission(generalQuestionSettingQuery); } public GeneralQuestionSetting getInfo (Long generalQuestionSettingId){ GeneralQuestionSettingQuery generalQuestionSettingQuery = new GeneralQuestionSettingQuery(); generalQuestionSettingQuery.setGeneralQuestionSettingId(generalQuestionSettingId); generalQuestionSettingQuery.setGeneralQuestionSettingStatusPlural("1");//需要根据实际情况来 List list = generalQuestionSettingDao.getValuesByQuery(generalQuestionSettingQuery); if(null != list && list.size()>0){ return list.get(0); }else{ return null; } } public GeneralQuestionSetting getInfo (GeneralQuestionSettingQuery generalQuestionSettingQuery){ List list = generalQuestionSettingDao.getValuesByQuery(generalQuestionSettingQuery); if(null != list && list.size()>0){ return list.get(0); }else{ return null; } } public JsonResult importTemplate(List fileEntityList,Listlist,CoreUser coreUser){ ListerrMsg = new ArrayList<>(); String msg =""; int count = 0; Date date = new Date(); for(int item=0;null != fileEntityList && item map = new HashMap<>();//获取需要的表头的列 //从第一列找到需要的表头 for (int i=0; i0?JsonReturnCode.SUCCESS.getCode():JsonReturnCode.FAIL.getCode()); jsonResult.setData(errMsg); jsonResult.setMsg((count>0?"导入成功,共导入"+count+"条":"导入失败")+(StringUtils.isNotBlank(msg)?"
"+msg:"")); return jsonResult; } public List> getExcelValues (GeneralQuestionSettingQuery generalQuestionSettingQuery){ return generalQuestionSettingDao.getExcelValues(generalQuestionSettingQuery); } public void editPushStatus(@NotEmpty(message = "题目配置ID不能为空!") String ids, @NotNull(message = "发布状态不能为空!") GlobalPushStatusEnum pushStatus) { for (String settingId : ids.split(",")) { GeneralQuestionSetting model = new GeneralQuestionSetting(); model.setGeneralQuestionSettingId(Long.valueOf(settingId)); model.setGeneralQuestionSettingPushStatus(pushStatus); updateTemplate(model); } } /** * 根据题目配置ID查询当前时间,是否可以参加进行题目测试 * @param questionSettingId * @return */ public boolean verifyQuestionStartAndEndTimeWithNowTime(Long questionSettingId) { if (ObjectUtil.isNotEmpty(questionSettingId)) { GeneralQuestionSetting info = getInfo(questionSettingId); return DateUtil.isIn(DateUtil.date(), info.getGeneralQuestionStartTime(), info.getGeneralQuestionEndTime()); } return false; } /** * 根据题目配置ID查询当前时间,是否可以参加进行题目测试 * 抛出异常 * @param questionSettingId * @return */ public void verifyQuestionStartAndEndTimeWithNowTimeThrow(Long questionSettingId) { Assert.isTrue(verifyQuestionStartAndEndTimeWithNowTime(questionSettingId), "当前时间不在题目操作的时间段!"); } /** * 获取作业 * * @param generalQuestionSettingId 开课作业ID * @param fromTypeEnum * @return */ public List questionDetail(@NotNull(message = "题目配置ID不能为空!") final Long generalQuestionSettingId, @NotNull(message = "类型不能为空!") ResourcesQuestionSnapshotFromTypeEnum fromTypeEnum) { // 获取学生ID final Student student = getStudent(); Assert.notNull(student, "非学生身份,无法获取题目!"); Assert.isTrue(!fromTypeEnum.equals(HOMEWORK_FILE), "作业-附件类型 不需要获取题目快照!"); // 学生ID final Long studentId = student.getStudentId(); // 判断章节练习是否需要重发试卷的题目 final boolean selectIsReSend = generalQuestionLogService. verifyLogAddTypeIsReSend(generalQuestionSettingId, studentId, fromTypeEnum, FINALLY_SUBMIT); // 常量 True的Integer表现 final Integer TRUE_CONST = 1; List resourcesQuestionSnapshots; GeneralQuestionSetting setting = getInfo(generalQuestionSettingId); Assert.notNull(setting, "未查询到来源ID对应的题目!"); // 章节练习,则跳过次数验证; // 其他类型,都需要验证作答次数 if (!EnumUtil.contains(fromTypeEnum, CHAPTER_EXERCISE)) { // 作答次数 Integer generalQuestionSettingSettingDoCount = setting.getGeneralQuestionSettingDoCount(); Assert.isTrue(generalQuestionSettingSettingDoCount > 0, "作答次数设置有误,请联系管理员!"); // 数据库查询该学生已经做过的次数, 这个试卷如果已经交卷的话,就提示用户 GeneralQuestionLog generalQuestionLog = new GeneralQuestionLog(); generalQuestionLog.setStudentId(studentId); generalQuestionLog.setQuestionLogAddType(FINALLY_SUBMIT); generalQuestionLog.setGeneralQuestionSettingId(generalQuestionSettingId); long doCount = generalQuestionLogDao.templateCount(generalQuestionLog); // 断言判断最大作答次数 Assert.isTrue(doCount < generalQuestionSettingSettingDoCount, "已超过最大作答次数!"); } GeneralResourcesQuestionSnapshotQuery questionSnapshotQuery = new GeneralResourcesQuestionSnapshotQuery(); questionSnapshotQuery.setGeneralQuestionSettingId(generalQuestionSettingId); questionSnapshotQuery.setStudentId(studentId); questionSnapshotQuery.setIsReSend(selectIsReSend); // 答卷后显示答案解析 if (TRUE_CONST.equals(setting.getGeneralQuestionSettingEndShowQa())) { /** 实现 {@link GeneralQuestionLogService#questionAnalysis} */ } // 答卷后显示答案对错 if (TRUE_CONST.equals(setting.getGeneralQuestionSettingEndShowTrueFalse())) { /** 实现 {@link GeneralQuestionLogService#questionAnalysis} */ } // 题目乱序(同一大题内) if (TRUE_CONST.equals(setting.getGeneralQuestionSettingQuestionNoOrder())) { questionSnapshotQuery.setRand(true); } // 题目查询 resourcesQuestionSnapshots = generalResourcesQuestionSnapshotService.getValuesByQueryNotWithPermission(questionSnapshotQuery); // resourcesQuestionSnapshots = defaultIfNull(resourcesQuestionSnapshots, new ArrayList<>()); // 选项乱序(限单选、多选) if (TRUE_CONST.equals(setting.getGeneralQuestionSettingOptionNoOrder())) { // 单题选项排序处理 resourcesQuestionSnapshots.forEach(value -> { shuffleQuestion(value, "questionStem","questionOption", "questionAnswer", "questionType"); }); } { // 做题日志关联学生, 初步提交做题日志信息,不包含学生提交的答案和得分情况 generalQuestionLogService.preSubmitStudentQuestionLog(studentId, generalQuestionSettingId, null, resourcesQuestionSnapshots, selectIsReSend); // 学生身份,需要屏蔽答案,再丢给前端 resourcesQuestionSnapshots.forEach(GeneralResourcesQuestionSnapshot::hideAnswer); } // 考试自动交卷 if (EnumUtil.contains(fromTypeEnum, EXAM)) { generalQuestionSettingRedisDelayQueue.questionSettingDelay(generalQuestionSettingId); } return resourcesQuestionSnapshots; } public void deleteSettingAndSnapByIds(@NotEmpty String settingIds) { generalQuestionSettingDao.deleteByIds(settingIds); generalResourcesQuestionSnapshotService.deleteGeneralResourcesQuestionSnapshot(settingIds); } /** * 增加题目类型的数据 * 从系统题库中拉取 *

* 任务一;添加题目配置主表 * 任务二:添加题目快照表 * * @param settingQuery 题目配置信息 * @param courseInfoIdPair 新旧课程ID片段 * @return */ public void addSettingBySystemCourse(@Validated(ValidateConfig.ADD.class) GeneralQuestionSettingQuery settingQuery, Map courseInfoIdPair ) { // 添加到作业主表中 add(settingQuery); // 插入快照 final Long teacherOpenCourseQuestionSettingId = settingQuery.getGeneralQuestionSettingId(); // 传入的开课题目IDS String resourcesQuestionIdPlural = settingQuery.getResourcesQuestionIdPlural(); // 题目类型区分 Collection settingDTOList = settingQuery.getQuestionSettingOptions(); // 如果指定的题目IDs不为空的话,则需要对这些题目进行题目类型分组。 if(ObjectUtil.isNotEmpty(resourcesQuestionIdPlural)) { ResourcesQuestionQuery questionQuery = new ResourcesQuestionQuery(); questionQuery.setQuestionStatus(1); questionQuery.setResourcesQuestionIds(resourcesQuestionIdPlural); List questionList = resourcesQuestionService.getValuesByQueryNotWithPermission(questionQuery); // 无差别题目IDS转换成类型区分的集合 Map map = resourcesQuestionService.buildSettingDtoListByNoDiffQuestionList(questionList); // 设置分值 settingQuery.getQuestionSettingOptions().forEach(item -> { QuestionSettingDTO settingDTO = map.get(item.getQuestionType()); if(ObjectUtil.isAllNotEmpty(settingDTO, item.getSingleScore())) { settingDTO.setSingleScore(item.getSingleScore()); } }); if (ObjectUtil.isNotEmpty(map)) { settingDTOList = map.values(); } } List list = generalResourcesQuestionSnapshotService.getQuestionBySettingOptionDTOList(settingDTOList, Collections.emptyMap()); if (ObjectUtil.isNotEmpty(list)) { list.forEach(item -> { item.setGeneralQuestionSettingId(teacherOpenCourseQuestionSettingId); item.setBusinessCourseInfoId(settingQuery.getBusinessId()); item.setBusinessCourseInfoType(QuestionBusinessTypeEnum.FROM_SYSTEM); }); // 更新ID setNewCourseInfoId(list, courseInfoIdPair); generalResourcesQuestionSnapshotDao.insertBatch(list); } else { throw new PlatformException("题目配置信息有误,未获取到的题目!"); } } /** * 根据课程新旧ID片段集合,设置新的课程ID * * @param insertList * @param courseInfoIdPair */ public void setNewCourseInfoId(@NotNull Collection insertList, @NotNull Map courseInfoIdPair) { if (ObjectUtil.isAllNotEmpty(insertList, courseInfoIdPair)) { insertList.forEach(item -> { Long businessCourseInfoId = item.getBusinessCourseInfoId(); item.setBusinessCourseInfoId(courseInfoIdPair.getOrDefault(businessCourseInfoId, businessCourseInfoId)); }); } } /** * 功能描述:
* 验证学生是否提交试卷 * * @param questionSettingId 题目配置ID * @param studentId 学生ID * @param nothingThrowMessage 没找到任何题目时候异常信息 * @param notSubmitThrowMessage 异常的信息外部定义 * @Author: lx * @Date: 2022/11/30 23:51 */ public void validateFinallySubmitThrow(Long questionSettingId, Long studentId, String nothingThrowMessage, String notSubmitThrowMessage) { boolean isZeroCount = false; if (ObjectUtil.isAllNotEmpty(questionSettingId, studentId)) { QuestionLogSummaryQuery questionLogSummaryQuery = new QuestionLogSummaryQuery(); questionLogSummaryQuery.setQuestionSettingId(questionSettingId); questionLogSummaryQuery.setQuestionLogSummaryStatus(1); questionLogSummaryQuery.setPersonId(studentId); List logSummaryList = questionLogSummaryDao.getValuesByQueryNotWithPermission(questionLogSummaryQuery); if (StrUtil.isNotBlank(notSubmitThrowMessage)) { // 异常的消息,交给调用方来定义 Assert.notEmpty(logSummaryList, notSubmitThrowMessage); } // 查询未提交题目数量 long submitCount = generalQuestionLogDao.createLambdaQuery() .andEq(GeneralQuestionLog::getGeneralQuestionSettingId, questionSettingId) .andEq(GeneralQuestionLog::getGeneralQuestionLogStatus, 1) .andEq(GeneralQuestionLog::getStudentId, studentId) .andEq(GeneralQuestionLog::getQuestionLogAddType, FINALLY_SUBMIT) .count(); // 查询所有题目数量 long allCount = generalQuestionLogDao.createLambdaQuery() .andEq(GeneralQuestionLog::getGeneralQuestionSettingId, questionSettingId) .andEq(GeneralQuestionLog::getStudentId, studentId) .andEq(GeneralQuestionLog::getGeneralQuestionLogStatus, 1) .count(); if (StrUtil.isNotBlank(nothingThrowMessage)) { // 验证这个试卷是否有题目 Assert.isTrue(allCount > 0, nothingThrowMessage); } // 没有提交的题目数量 isZeroCount = submitCount > 0; } if (StrUtil.isNotBlank(notSubmitThrowMessage)) { // 异常的消息,交给调用方来定义 Assert.isTrue(isZeroCount, notSubmitThrowMessage); } } /** * 功能描述:
* 错题练习,错题库根据试卷来 * * @param questionSettingId 题目配置ID(试卷ID) * @param tuckOrError 练习的类型 * @param student 学生 * @return {@link JsonResult} * @Author: 87966 * @Date: 2022/12/1 9:27 */ public List questionDetailTest(@NotNull(message = "题目配置ID不能为空!") Long questionSettingId, @NotNull(message = "练习类型不能为空!") TuckOrErrorEnum tuckOrError, @NotNull(message = "改接口只能学生访问") Student student) { final Long studentId = student.getStudentId(); GeneralQuestionLogQuery logQuery = new GeneralQuestionLogQuery(); if (TUCK_TEST.equals(tuckOrError)) { logQuery.setIsTuck(true); } else if(ERROR_TEST.equals(tuckOrError)) { logQuery.setIsErrorFavorite(true); } logQuery.setStudentId(studentId); logQuery.setGeneralQuestionLogStatus(1); logQuery.setGeneralQuestionSettingId(questionSettingId); List list = generalQuestionLogService.getValuesByQueryNotWithPermission(logQuery); if (ObjectUtil.isNotEmpty(list)) { return BeanUtil.copyToList(list, GeneralResourcesQuestionSnapshot.class); } return Collections.emptyList(); } }