You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tianze-pro/web/src/main/java/com/ibeetl/jlw/service/GeneralQuestionLogService.java

981 lines
48 KiB
Java

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package com.ibeetl.jlw.service;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReUtil;
import cn.jlw.util.ToolUtils;
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.StudentDao;
import com.ibeetl.jlw.entity.*;
import com.ibeetl.jlw.entity.dto.QuestionLogAddDTO;
import com.ibeetl.jlw.enums.QuestionLogAddTypeEnum;
import com.ibeetl.jlw.enums.ResourcesQuestionSnapshotFromTypeEnum;
import com.ibeetl.jlw.web.query.GeneralQuestionLogQuery;
import com.ibeetl.jlw.web.query.GeneralQuestionSettingQuery;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
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.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.*;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import static cn.hutool.core.date.DateUnit.SECOND;
import static cn.hutool.core.util.ArrayUtil.join;
import static cn.jlw.util.CacheUserUtil.getStudent;
import static com.ibeetl.admin.core.util.ExcelUtil.getCellFormatValue;
import static com.ibeetl.jlw.enums.QuestionLogAddTypeEnum.FINALLY_SUBMIT;
import static com.ibeetl.jlw.enums.QuestionLogAddTypeEnum.PRE_SUBMIT;
import static com.ibeetl.jlw.enums.ResourcesQuestionSnapshotFromTypeEnum.CHAPTER_EXERCISE;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.joining;
/**
* 通用做题日志 Service
* 当分布式ID开启后请勿使用insert(*,true)
*/
@Service
@Transactional
@Validated
public class GeneralQuestionLogService extends CoreBaseService<GeneralQuestionLog>{
@Autowired private GeneralQuestionLogDao generalQuestionLogDao;
@Autowired private StudentDao studentDao;
@Autowired @Lazy
private GeneralQuestionSettingService generalQuestionSettingService;
public PageQuery<GeneralQuestionLog>queryByCondition(PageQuery query){
PageQuery ret = generalQuestionLogDao.queryByCondition(query);
queryListAfter(ret.getList());
return ret;
}
public PageQuery<GeneralQuestionLog>queryByConditionQuery(PageQuery query){
PageQuery ret = generalQuestionLogDao.queryByConditionQuery(query);
queryListAfter(ret.getList());
return ret;
}
public void deleteByList(List list){
String ids = "";
ToolUtils.deleteNullList(list);
for(int i=0;null != list && i<list.size();i++){
ids += list.get(i).toString()+(i==list.size()-1?"":",");
}
if(StringUtils.isNotBlank(ids)){
generalQuestionLogDao.deleteByIds(ids);
}
}
public void deleteGeneralQuestionLog(String ids){
try {
generalQuestionLogDao.deleteGeneralQuestionLogByIds(ids);
} catch (Exception e) {
throw new PlatformException("批量删除通用做题日志失败", e);
}
}
public void logicDeleteBySettingIds(String settingIds){
try {
generalQuestionLogDao.logicDeleteBySettingIds(settingIds);
} catch (Exception e) {
throw new PlatformException("批量删除通用做题日志失败", e);
}
}
public void deleteBySettingIds(String settingIds){
try {
generalQuestionLogDao.deleteBySettingIds(settingIds);
} catch (Exception e) {
throw new PlatformException("批量删除通用做题日志失败", e);
}
}
public String addAll(GeneralQuestionLogQuery generalQuestionLogQuery){
String msg = "";
List<GeneralQuestionLog> generalQuestionLogList = new ArrayList<>();
try {
generalQuestionLogList = JSON.parseArray(generalQuestionLogQuery.getGeneralQuestionLogJsonStr(), GeneralQuestionLog.class);
} catch (Exception e) {
try {
generalQuestionLogList.add(JSONObject.parseObject(generalQuestionLogQuery.getGeneralQuestionLogJsonStr(), GeneralQuestionLog.class));
} catch (Exception e1) {}
}
ToolUtils.deleteNullList(generalQuestionLogList);
if(null != generalQuestionLogList && generalQuestionLogList.size()>0){
for(int i=0;i<generalQuestionLogList.size();i++){
GeneralQuestionLog generalQuestionLog = generalQuestionLogList.get(i);
generalQuestionLog.setUserId(generalQuestionLogQuery.getUserId());
generalQuestionLog.setOrgId(generalQuestionLogQuery.getOrgId());
}
insertBatch(generalQuestionLogList);
}
return msg;
}
public JsonResult add(GeneralQuestionLogQuery generalQuestionLogQuery){
String msg = "";
GeneralQuestionLog generalQuestionLog = generalQuestionLogQuery.pojo();
generalQuestionLogDao.insert(generalQuestionLog);
generalQuestionLogQuery.setGeneralQuestionLogId(generalQuestionLog.getGeneralQuestionLogId());
JsonResult jsonResult = new JsonResult();
jsonResult.setData(generalQuestionLog.getGeneralQuestionLogId());//自增的ID丢进去
jsonResult.setCode(JsonReturnCode.SUCCESS.getCode());
jsonResult.setMsg(msg);
return jsonResult;
}
public String edit(GeneralQuestionLogQuery generalQuestionLogQuery){
String msg = "";
GeneralQuestionLog generalQuestionLog = generalQuestionLogQuery.pojo();
generalQuestionLogDao.updateTemplateById(generalQuestionLog);
return msg;
}
public String updateGivenByIds(GeneralQuestionLogQuery generalQuestionLogQuery){
String msg = "";
if(StringUtils.isNotBlank(generalQuestionLogQuery.get_given())){
boolean flag = generalQuestionLogDao.updateGivenByIds(generalQuestionLogQuery) > 0;
if(!flag){
msg = "更新指定参数失败";
}
}else{
msg = "指定参数为空";
}
return msg;
}
public List<GeneralQuestionLog> getValues (Object paras){
return sqlManager.select(SqlId.of("jlw.generalQuestionLog.getGeneralQuestionLogValues"), GeneralQuestionLog.class, paras);
}
public List<GeneralQuestionLog> getValuesByQuery (GeneralQuestionLogQuery generalQuestionLogQuery){
return generalQuestionLogDao.getValuesByQuery(generalQuestionLogQuery);
}
public List<GeneralQuestionLog> getValuesByQueryNotWithPermission (GeneralQuestionLogQuery generalQuestionLogQuery){
return generalQuestionLogDao.getValuesByQueryNotWithPermission(generalQuestionLogQuery);
}
public GeneralQuestionLog getInfo (Long generalQuestionLogId){
GeneralQuestionLogQuery generalQuestionLogQuery = new GeneralQuestionLogQuery();
generalQuestionLogQuery.setGeneralQuestionLogId(generalQuestionLogId);
generalQuestionLogQuery.setGeneralQuestionLogStatusPlural("1,2");//需要根据实际情况来
List<GeneralQuestionLog> list = generalQuestionLogDao.getValuesByQuery(generalQuestionLogQuery);
if(null != list && list.size()>0){
return list.get(0);
}else{
return null;
}
}
public GeneralQuestionLog getInfo (GeneralQuestionLogQuery generalQuestionLogQuery){
List<GeneralQuestionLog> list = generalQuestionLogDao.getValuesByQuery(generalQuestionLogQuery);
if(null != list && list.size()>0){
return list.get(0);
}else{
return null;
}
}
public JsonResult importTemplate(List<FileEntity> fileEntityList,List<Long>list,CoreUser coreUser){
List<String[]>errMsg = new ArrayList<>();
String msg ="";
int count = 0;
Date date = new Date();
for(int item=0;null != fileEntityList && item<fileEntityList.size();item++){
FileEntity fileEntity = fileEntityList.get(item);
if(null != fileEntity){
File file = new File(fileEntity.getAbsoluteUrl());
if(file.exists() && file.isFile() && file.canRead() && ToolUtils.findInSet("xls,xlsx",fileEntity.getFormat())){
Workbook wb = null;
InputStream is = null;
try {
is = new FileInputStream(fileEntity.getAbsoluteUrl());
if("xls".equals(fileEntity.getFormat())){
wb = new HSSFWorkbook(is);
}else if("xlsx".equals(fileEntity.getFormat())){
wb = new XSSFWorkbook(is);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(null != is){
is.close();
}
}catch (Exception e){
e.printStackTrace();
}
if(wb != null){
//获取Sheet1
Sheet sheet = wb.getSheet("Sheet1");
//获取最大行数
int rowNum = sheet.getPhysicalNumberOfRows();
//获取第一行
Row firstRow = sheet.getRow(0);
//获取最大列数
int colNum = firstRow.getPhysicalNumberOfCells();
String columns[] = {
"通用题目配置",
"题目快照",
"学生提交的答案",
"附件,学生端上传附件",
"创建时间",
"状态",
"学生",
"学生得分",
"题型",
"分值",
"题干",
"选项A",
"选项B",
"选项C",
"选项D",
"选项E",
"答案",
"解析",
"是否收藏夹",
"是否错题库",
};
Map<String,Integer> map = new HashMap<>();//获取需要的表头的列
//从第一列找到需要的表头
for (int i=0; i<colNum; i++){
String cellData = getCellFormatValue(firstRow.getCell(i));
for(int j=0;j<columns.length;j++){
if(columns[j].equals(cellData)){
map.put(columns[j],i);
}
}
}
//验证所需要的表头是否全
Integer flag = 0;
for(int i=0;i<columns.length;i++){
if(null != map.get(columns[i])){
flag ++;
}
}
if(flag != columns.length){
String str = " ";
for(int i=0;i<columns.length;i++){
str += "\""+columns[i]+"\""+(i == columns.length-1?"":", ");
}
return JsonResult.failMessage("导入失败,表格表头应包含"+str);
}
for (int i = 1; i<rowNum; i++) {
Row row = sheet.getRow(i);
if(null == row){
errMsg.add(new String[]{"第"+(i+1)+"数据为空"});
continue;
}
String generalQuestionSettingId = getCellFormatValue(row.getCell(map.get(columns[0])));
String generalResourcesQuestionSnapshotId = getCellFormatValue(row.getCell(map.get(columns[1])));
String generalQuestionLogAnswer = getCellFormatValue(row.getCell(map.get(columns[2])));
String generalQuestionLogUploadFile = getCellFormatValue(row.getCell(map.get(columns[3])));
String generalQuestionLogAddTime = getCellFormatValue(row.getCell(map.get(columns[4])));
String generalQuestionLogStatus = getCellFormatValue(row.getCell(map.get(columns[5])));
String studentId = getCellFormatValue(row.getCell(map.get(columns[6])));
String studentScore = getCellFormatValue(row.getCell(map.get(columns[7])));
String questionType = getCellFormatValue(row.getCell(map.get(columns[8])));
String questionScore = getCellFormatValue(row.getCell(map.get(columns[9])));
String questionStem = getCellFormatValue(row.getCell(map.get(columns[10])));
String questionOptionA = getCellFormatValue(row.getCell(map.get(columns[11])));
String questionOptionB = getCellFormatValue(row.getCell(map.get(columns[12])));
String questionOptionC = getCellFormatValue(row.getCell(map.get(columns[13])));
String questionOptionD = getCellFormatValue(row.getCell(map.get(columns[14])));
String questionOptionE = getCellFormatValue(row.getCell(map.get(columns[15])));
String questionAnswer = getCellFormatValue(row.getCell(map.get(columns[16])));
String questionAnalysis = getCellFormatValue(row.getCell(map.get(columns[17])));
String isTuck = getCellFormatValue(row.getCell(map.get(columns[18])));
String isErrorFavorite = getCellFormatValue(row.getCell(map.get(columns[19])));
//TODO 判断(如重复等复杂判断要额外写)
if(StringUtils.isBlank(generalQuestionSettingId)){
errMsg.add(new String[]{"第"+ToolUtils.numberToLetter(map.get(columns[0])+1)+"列,第"+(i+1)+"行通用题目配置为空"});
continue;
}else
if(StringUtils.isBlank(generalResourcesQuestionSnapshotId)){
errMsg.add(new String[]{"第"+ToolUtils.numberToLetter(map.get(columns[1])+1)+"列,第"+(i+1)+"行题目快照为空"});
continue;
}else
if(StringUtils.isBlank(generalQuestionLogAnswer)){
errMsg.add(new String[]{"第"+ToolUtils.numberToLetter(map.get(columns[2])+1)+"列,第"+(i+1)+"行学生提交的答案为空"});
continue;
}else
if(StringUtils.isBlank(generalQuestionLogUploadFile)){
errMsg.add(new String[]{"第"+ToolUtils.numberToLetter(map.get(columns[3])+1)+"列,第"+(i+1)+"行附件,学生端上传附件为空"});
continue;
}else
if(StringUtils.isBlank(generalQuestionLogAddTime)){
errMsg.add(new String[]{"第"+ToolUtils.numberToLetter(map.get(columns[4])+1)+"列,第"+(i+1)+"行创建时间为空"});
continue;
}else
if(StringUtils.isBlank(generalQuestionLogStatus)){
errMsg.add(new String[]{"第"+ToolUtils.numberToLetter(map.get(columns[5])+1)+"列,第"+(i+1)+"行状态为空"});
continue;
}else
if(StringUtils.isBlank(studentId)){
errMsg.add(new String[]{"第"+ToolUtils.numberToLetter(map.get(columns[6])+1)+"列,第"+(i+1)+"行学生为空"});
continue;
}else
if(StringUtils.isBlank(studentScore)){
errMsg.add(new String[]{"第"+ToolUtils.numberToLetter(map.get(columns[7])+1)+"列,第"+(i+1)+"行学生得分为空"});
continue;
}else
if(StringUtils.isBlank(questionType)){
errMsg.add(new String[]{"第"+ToolUtils.numberToLetter(map.get(columns[8])+1)+"列,第"+(i+1)+"行题型为空"});
continue;
}else
if(StringUtils.isBlank(questionScore)){
errMsg.add(new String[]{"第"+ToolUtils.numberToLetter(map.get(columns[9])+1)+"列,第"+(i+1)+"行分值为空"});
continue;
}else
if(StringUtils.isBlank(questionStem)){
errMsg.add(new String[]{"第"+ToolUtils.numberToLetter(map.get(columns[10])+1)+"列,第"+(i+1)+"行题干为空"});
continue;
}else
if(StringUtils.isBlank(questionOptionA)){
errMsg.add(new String[]{"第"+ToolUtils.numberToLetter(map.get(columns[11])+1)+"列,第"+(i+1)+"行选项A为空"});
continue;
}else
if(StringUtils.isBlank(questionOptionB)){
errMsg.add(new String[]{"第"+ToolUtils.numberToLetter(map.get(columns[12])+1)+"列,第"+(i+1)+"行选项B为空"});
continue;
}else
if(StringUtils.isBlank(questionOptionC)){
errMsg.add(new String[]{"第"+ToolUtils.numberToLetter(map.get(columns[13])+1)+"列,第"+(i+1)+"行选项C为空"});
continue;
}else
if(StringUtils.isBlank(questionOptionD)){
errMsg.add(new String[]{"第"+ToolUtils.numberToLetter(map.get(columns[14])+1)+"列,第"+(i+1)+"行选项D为空"});
continue;
}else
if(StringUtils.isBlank(questionOptionE)){
errMsg.add(new String[]{"第"+ToolUtils.numberToLetter(map.get(columns[15])+1)+"列,第"+(i+1)+"行选项E为空"});
continue;
}else
if(StringUtils.isBlank(questionAnswer)){
errMsg.add(new String[]{"第"+ToolUtils.numberToLetter(map.get(columns[16])+1)+"列,第"+(i+1)+"行答案为空"});
continue;
}else
if(StringUtils.isBlank(questionAnalysis)){
errMsg.add(new String[]{"第"+ToolUtils.numberToLetter(map.get(columns[17])+1)+"列,第"+(i+1)+"行解析为空"});
continue;
}else
if(StringUtils.isBlank(isTuck)){
errMsg.add(new String[]{"第"+ToolUtils.numberToLetter(map.get(columns[18])+1)+"列,第"+(i+1)+"行是否收藏夹为空"});
continue;
}else
if(StringUtils.isBlank(isErrorFavorite)){
errMsg.add(new String[]{"第"+ToolUtils.numberToLetter(map.get(columns[19])+1)+"列,第"+(i+1)+"行是否错题库为空"});
continue;
}else
{
//TODO 保存
GeneralQuestionLog generalQuestionLog = new GeneralQuestionLog();
generalQuestionLog.setGeneralQuestionSettingId(Long.parseLong(generalQuestionSettingId));
generalQuestionLog.setGeneralResourcesQuestionSnapshotId(Long.parseLong(generalResourcesQuestionSnapshotId));
generalQuestionLog.setGeneralQuestionLogAnswer(generalQuestionLogAnswer);
generalQuestionLog.setGeneralQuestionLogUploadFile(generalQuestionLogUploadFile);
generalQuestionLog.setGeneralQuestionLogAddTime(TimeTool.getTime(generalQuestionLogAddTime));
generalQuestionLog.setGeneralQuestionLogStatus(Integer.parseInt(generalQuestionLogStatus));
generalQuestionLog.setStudentId(Long.parseLong(studentId));
generalQuestionLog.setStudentScore(new BigDecimal(studentScore));
generalQuestionLog.setQuestionType(Integer.parseInt(questionType));
generalQuestionLog.setQuestionScore(new BigDecimal(questionScore));
generalQuestionLog.setQuestionStem(questionStem);
generalQuestionLog.setQuestionOptionA(questionOptionA);
generalQuestionLog.setQuestionOptionB(questionOptionB);
generalQuestionLog.setQuestionOptionC(questionOptionC);
generalQuestionLog.setQuestionOptionD(questionOptionD);
generalQuestionLog.setQuestionOptionE(questionOptionE);
generalQuestionLog.setQuestionAnswer(questionAnswer);
generalQuestionLog.setQuestionAnalysis(questionAnalysis);
generalQuestionLog.setIsTuck(Boolean.valueOf(isTuck));
generalQuestionLog.setIsErrorFavorite(Boolean.valueOf(isErrorFavorite));
generalQuestionLog.setOrgId(coreUser.getOrgId());
generalQuestionLog.setUserId(coreUser.getId());
count++;
}
}
}
}
}
}
JsonResult jsonResult = new JsonResult();
jsonResult.setCode(count>0?JsonReturnCode.SUCCESS.getCode():JsonReturnCode.FAIL.getCode());
jsonResult.setData(errMsg);
jsonResult.setMsg((count>0?"导入成功,共导入"+count+"条":"导入失败")+(StringUtils.isNotBlank(msg)?"<br>"+msg:""));
return jsonResult;
}
public List<Map<String,Object>> getExcelValues (GeneralQuestionLogQuery generalQuestionLogQuery){
return generalQuestionLogDao.getExcelValues(generalQuestionLogQuery);
}
/**
* 教师端-手动批改一些题目的分数
*
* @param generalQuestionLogIds 指定更新分数的题目日志IDs
* @param score 分数
* @param reply 评语
*/
public void manualModifyQuestionScores(@NotNull(message = "题目做题日志ID不能为空") final String generalQuestionLogIds, @NotEmpty final BigDecimal score, @Nullable final String reply) {
GeneralQuestionLogQuery generalQuestionLogQuery = new GeneralQuestionLogQuery();
generalQuestionLogQuery.setGeneralQuestionLogIdPlural(generalQuestionLogIds);
generalQuestionLogQuery.setGeneralQuestionLogStatus(1);
List<GeneralQuestionLog> updateList = generalQuestionLogDao.getValuesByQueryNotWithPermission(generalQuestionLogQuery);
final Date now = new Date();
// 批量更新分数。支持重复设置分数和评语
updateList.forEach(questionLog -> {
BigDecimal questionScore = questionLog.getQuestionScore();
questionLog.setStudentScore(score);
questionLog.setGeneralQuestionLogReply(reply);
// 这里不是记录用时,只是记录教师批阅的时间
questionLog.setGeneralQuestionLogUpdateTime(now);
// 是否错题库,也可以用作标记答案是对的错的
questionLog.setIsErrorFavorite(NumberUtil.equals(questionScore, score));
});
updateBatchTemplate(updateList);
}
/**
* 和题目有关的做题提交方法
* 直接计算出学生得分情况
*
* @param questionLogAddDTO 题目信息
*/
public void insertQuestionLog(@NotNull(message = "提交题目信息不能为空") QuestionLogAddDTO questionLogAddDTO) {
Long questionSettingId = questionLogAddDTO.getQuestionSettingId();
Map<String, String> questionLogMap = questionLogAddDTO.getQuestionLogMap();
// 查询学生身份
final Student student = getStudent();
Assert.notNull(student, "非学生身份,无法提交!");
GeneralQuestionSetting info = generalQuestionSettingService.getInfo(questionSettingId);
Assert.notNull(info, "题目配置ID有误");
// 校验当前时间是否在考试的时间段
generalQuestionSettingService.verifyQuestionStartAndEndTimeWithNowTimeThrow(questionSettingId);
switch(info.getGeneralQuestionSettingType()) {
case HOMEWORK_FILE: {
addFileRelatedLog(join(questionLogMap.values().toArray(), ","), questionSettingId, student);
} break;
// 这些都和题目相关,暂时先放在一个方法
case CHAPTER_EXERCISE:
case EXAM:
case HOMEWORK_QUESTION:{
addQuestionRelatedLog(questionLogAddDTO, student);
} break;
}
}
/**
* 跟题目相关的题目日志提交方法
* 附件类型的需要单独,拆分除去
*
* @param absFilePath
* @param questionSettingId
* @param student
*/
private void addFileRelatedLog(@NotBlank(message = "上传的附件不能为空!") String absFilePath, Long questionSettingId, Student student) {
GeneralQuestionLogQuery query = new GeneralQuestionLogQuery();
query.setGeneralQuestionLogUploadFile(absFilePath);
query.setGeneralQuestionSettingId(questionSettingId);
query.setGeneralQuestionLogUpdateTime(new Date());
query.setGeneralQuestionLogStatus(1);
// 附件作业,只有一题,所有默认是全部提交的方式
query.setQuestionLogAddType(FINALLY_SUBMIT);
query.setOrgId(student.getOrgId());
query.setUserId(student.getUserId());
query.setStudentId(student.getStudentId());
add(query);
}
/**
* 跟题目相关的题目日志提交方法
* 附件类型的需要单独,拆分除去
*
* @param questionLogAddDTO 题目信息
* @param student 学生信息
*/
private void addQuestionRelatedLog(@NotNull(message = "提交题目信息不能为空") QuestionLogAddDTO questionLogAddDTO, Student student) {
// 参数获取
QuestionLogAddTypeEnum addType = questionLogAddDTO.getQuestionLogAddType();
Date addTime = questionLogAddDTO.getAddTime(); Long studentId = student.getStudentId();
Long questionSettingId = questionLogAddDTO.getQuestionSettingId();
Map<String, String> questionLogMap = questionLogAddDTO.getQuestionLogMap();
// 查询符合条件的日志表
String questionSnapshotIds = join(questionLogMap.keySet().toArray(), ",");
// 做题思路先从通用GeneralQuestionSetting表中生成题目日志到GeneralQuestionLog中学生这个时候提交答案再修改日志中的结果。
// 查询条件
GeneralQuestionLogQuery questionLogQuery = GeneralQuestionLogQuery.builder()
.generalResourcesQuestionSnapshotIdPlural(questionSnapshotIds)
.generalQuestionLogStatus(1)
.studentId(student.getStudentId())
.generalQuestionSettingId(questionSettingId)
.build();
List<GeneralQuestionLog> logList = generalQuestionLogDao.getValuesByQuery(questionLogQuery);
Assert.notEmpty(logList, "未查询到题目信息!");
// 当前时间, 存储要更新的题目日志集合
Date now = new Date(); List<GeneralQuestionLog> updateList = new ArrayList<>();
// 处理答案和分数
logList.forEach(questionLog -> {
// 验证最新的提交时间,防止网络延迟
if (!validateQuestionLogAddTimeLatest(questionSettingId, questionLog.getGeneralResourcesQuestionSnapshotId().toString(), studentId, addTime)) {
return;
}
Assert.isTrue(null == questionLog.getQuestionLogAddType()
|| questionLog.getQuestionLogAddType().equals(PRE_SUBMIT), "已交卷,无法重复提交!");
// 学生提交的答案
String answersText = join(questionLogMap.get(questionLog.getGeneralResourcesQuestionSnapshotId().toString()).split(","), ",");
// 是否是正确答案
Boolean isCorrectAnswer = questionLog.getQuestionAnswer().equalsIgnoreCase(answersText);
// 计算该题目学生的得分情况
questionLog.setStudentScore(isCorrectAnswer ? questionLog.getQuestionScore() : BigDecimal.valueOf(0));
// 完成时间
long finishSecondTime = DateUtil.between(questionLog.getGeneralQuestionLogAddTime(), now, SECOND);
// 填充属性
questionLog.setGeneralQuestionLogUpdateTime(now);
questionLog.setGeneralQuestionLogFinishTime(finishSecondTime);
questionLog.setGeneralQuestionLogAnswer(answersText);
questionLog.setQuestionLogAddType(addType);
questionLog.setOrgId(student.getOrgId());
questionLog.setUserId(student.getUserId());
// 只添加可以更新的数据
updateList.add(questionLog);
});
// 学生做的题目的答案与日志关联
updateBatchTemplate(updateList);
}
/**
* 验证前端传递过来的添加时间是否是最新的
* @param questionSettingId 题目配置ID
* @param questionSnapshotIds 题目快照ID
* @param studentId 学生ID
* @param addTime 前端传递的添加时间
* @return
*/
private boolean validateQuestionLogAddTimeLatest(@NotNull(message = "开课题目配置ID不能为空") Long questionSettingId,
@NotBlank(message = "题目快照IDs不能为空") String questionSnapshotIds,
@NotNull(message = "学生ID不能为空") Long studentId,
@NotNull(message = "提交时间不能为空!") Date addTime) {
return generalQuestionLogDao.validateQuestionLogAddTimeLatest(questionSettingId, questionSnapshotIds, studentId, addTime);
}
/**
* 日志关联学生信息和配置ID信息
*
* @param studentId 学生ID
* @param setting 题目配置
* @param resourcesQuestionSnapshots 题目快照结合
* @param isReSend 是否根据题目快照强制重新发题
*/
public void preSubmitStudentQuestionLog(@NotNull(message = "学生ID不能为空") final Long studentId,
@NotNull(message = "题目配置不能为空!") final GeneralQuestionSetting setting,
@NotEmpty(message = "题目快照列表不能为空!") List<GeneralResourcesQuestionSnapshot> resourcesQuestionSnapshots,
boolean isReSend
) {
if (CollectionUtil.isEmpty(resourcesQuestionSnapshots)) {
return;
}
// 不是强制发题,则不覆盖现有的题目日志,则继续做题
// 验证题目日志,是否已经存在试卷
if(!isReSend) {
GeneralQuestionLogQuery questionLogQuery = new GeneralQuestionLogQuery();
questionLogQuery.setStudentId(studentId);
// 正在做题的话,再次进来如果这个试卷没提交,则继续做题,不会重新生成题目
questionLogQuery.setQuestionLogAddType(PRE_SUBMIT);
questionLogQuery.setGeneralQuestionSettingId(setting.getGeneralQuestionSettingId());
questionLogQuery.setGeneralQuestionLogStatus(1);
List<GeneralQuestionLog> existsList = getValuesByQueryNotWithPermission(questionLogQuery);
// 如果题目日志里存在预先布置的题目,则直接返回
if (CollectionUtil.isNotEmpty(existsList)) {
return;
}
}
// generalQuestionSettingId类似试卷ID题目日志里会出现重复的试卷ID
// 逻辑删除之前的题目日志,防止学生做题统计数据异常
// 保证试卷是最新的
// 考试逻辑删除记录,作业或者章节测试都是直接删除记录。
Long teacherOpenCourseQuestionSettingId = setting.getGeneralQuestionSettingId();
// 强制发题
if (isReSend) {
logicDeleteBySettingIds(teacherOpenCourseQuestionSettingId.toString());
}
// 断言
Assert.notBlank(resourcesQuestionSnapshots.get(0).getQuestionAnswer(), "题目快照选项不能为空!");
List<GeneralQuestionLog> generalQuestionLogs = BeanUtil.copyToList(resourcesQuestionSnapshots, GeneralQuestionLog.class);
// 设计个单表,后面进行修改操作
generalQuestionLogs.forEach(questionLog -> {
// 题目的答案,如果最后一位是逗号,则删除掉
String questionAnswer = ReUtil.replaceAll(questionLog.getQuestionAnswer(), "\\,$", "");
questionLog.setGeneralQuestionSettingId(setting.getGeneralQuestionSettingId());
questionLog.setGeneralQuestionLogStatus(1);
questionLog.setStudentId(studentId);
questionLog.setGeneralQuestionLogAddTime(new Date());
questionLog.setQuestionAnswer(questionAnswer);
});
insertBatch(generalQuestionLogs);
}
/**
* 根据题目配置ID查询题目快照并根据类型分组
*
* @param questionSettingId
* @return
*/
public Map<Integer, List<GeneralQuestionLog>> questionAnalysis(@NotNull(message = "题目配置ID不能为空") Long questionSettingId, @NotNull(message = "学生ID不能为空") Long studentId) {
GeneralQuestionLogQuery query = new GeneralQuestionLogQuery();
query.setGeneralQuestionSettingId(questionSettingId);
query.setGeneralQuestionLogStatus(1);
query.setStudentId(studentId);
List<GeneralQuestionLog> valuesByQuery = getValuesByQueryNotWithPermission(query);
return questionAnalysis(valuesByQuery);
}
/**
* 根据题目快照ID查询题目快照并根据类型分组
*
* @param questionSnapshotIds
* @return
*/
public Map<Integer, List<GeneralQuestionLog>> questionAnalysis(@NotNull(message = "题目配置ID不能为空") TreeSet<Long> questionSnapshotIds, @NotNull(message = "学生ID不能为空") Long studentId) {
GeneralQuestionLogQuery query = new GeneralQuestionLogQuery();
query.setGeneralQuestionLogIdPlural(join(questionSnapshotIds.toArray(), ","));
query.setGeneralQuestionLogStatus(1);
query.setStudentId(studentId);
List<GeneralQuestionLog> valuesByQuery = getValuesByQueryNotWithPermission(query);
return questionAnalysis(valuesByQuery);
}
/**
* 题目相关-考试或者作业,答题提交后,获取问题解析。根据配置获取
* @param questionLogList
* @return
*/
public Map<Integer, List<GeneralQuestionLog>> questionAnalysis(@NotEmpty(message = "未查询到题目列表!") final List<GeneralQuestionLog> questionLogList) {
GeneralQuestionSettingQuery settingQuery = new GeneralQuestionSettingQuery();
settingQuery.setGeneralQuestionSettingId(questionLogList.get(0).getGeneralQuestionSettingId());
final GeneralQuestionSetting hwSetting = generalQuestionSettingService.getInfo(settingQuery);
// 答卷后显示答案解析
final Boolean isEndShowQa = BooleanUtil.toBoolean(String.valueOf(hwSetting.getGeneralQuestionSettingEndShowQa()));
// 答卷后显示答案对错
final Boolean isEndShowTrueFalse = BooleanUtil.toBoolean(String.valueOf(hwSetting.getGeneralQuestionSettingEndShowTrueFalse()));
return questionLogList.stream().map(item -> {
GeneralQuestionLog questionLog = new GeneralQuestionLog();
questionLog.setGeneralResourcesQuestionSnapshotId(item.getGeneralResourcesQuestionSnapshotId());
questionLog.setQuestionAnswer(isEndShowQa ? item.getQuestionAnswer() : "");
questionLog.setQuestionAnalysis(isEndShowTrueFalse ? item.getQuestionAnswer(): "");
return questionLog;
}).collect(groupingBy(GeneralQuestionLog::getQuestionType));
}
/**
* 查询学生的分数列表信息(分页)
* 不带权限
*
* @param query
*/
public PageQuery<GeneralQuestionLog> studentScoreList(PageQuery query) {
PageQuery ret = generalQuestionLogDao.studentScoreList(query);
queryListAfter(ret.getList());
return ret;
}
/**
* 收藏题目根据题目配置ID + 题目快照ID
*
* @param questionSettingId 题目配置ID
* @param questionSnapIds 题目快照IDs
* @param isTuck 是否收藏 true收藏 false取消收藏
* @param student 学生信息
*/
public void tuck(@NotNull(message = "题目配置ID不能为空") Long questionSettingId,
@NotBlank(message = "题目快照IDs不能为空") String questionSnapIds, boolean isTuck,
@NotNull(message = "学生信息不能为空!") Student student) {
GeneralQuestionLogQuery logQuery = new GeneralQuestionLogQuery();
logQuery.setGeneralQuestionSettingId(questionSettingId);
logQuery.setGeneralResourcesQuestionSnapshotIdPlural(questionSnapIds);
logQuery.setGeneralQuestionLogStatus(1);
logQuery.setStudentId(student.getStudentId());
List<GeneralQuestionLog> list = getValuesByQueryNotWithPermission(logQuery);
if (ObjectUtil.isEmpty(list)) {
throw new PlatformException("收藏失败,未查询到要收藏的题目");
}
String logIds = list.stream()
.map(o -> o.getGeneralQuestionLogId().toString()).collect(joining(","));
// 根据做题的日志ID收藏题目
tuckByLogIds(logIds, isTuck);
}
/**
* 批量收藏题目
* @param generalQuestionLogIds
* @param isTuck
*/
public void tuckByLogIds(@NotEmpty(message = "题目日志ID不能为空") String generalQuestionLogIds, final boolean isTuck) {
Function<String, GeneralQuestionLog> stringQuestionLogFunction = logId -> {
GeneralQuestionLog questionLog = new GeneralQuestionLog();
questionLog.setGeneralQuestionLogId(Long.valueOf(logId));
questionLog.setIsTuck(isTuck);
return questionLog;
};
List<GeneralQuestionLog> logSet = Arrays.asList(generalQuestionLogIds.split(",")).stream()
.map(stringQuestionLogFunction).collect(Collectors.toList());
updateBatchTemplate(logSet);
}
/**
* 批量收藏到错题库
* @param generalQuestionLogIds
* @param isErrorFavorite
*/
public void errorFavorite(@NotEmpty(message = "题目日志ID不能为空") String generalQuestionLogIds, final boolean isErrorFavorite) {
Function<String, GeneralQuestionLog> stringgeneralQuestionLogFunction = logId -> {
GeneralQuestionLog questionLog = new GeneralQuestionLog();
questionLog.setGeneralQuestionLogId(Long.valueOf(logId));
questionLog.setIsErrorFavorite(isErrorFavorite);
return questionLog;
};
List<GeneralQuestionLog> logSet = Arrays.asList(generalQuestionLogIds.split(",")).stream()
.map(stringgeneralQuestionLogFunction).collect(Collectors.toList());
updateBatchTemplate(logSet);
}
/**
* 查询分数详细信息(系统,非教师开课)
* @param query 题目分数查询实体
* @return
*/
public PageQuery<GeneralQuestionLogScoreDetailsInfo> getQuestionLogScoreDetailsInfo(PageQuery query) {
return generalQuestionLogDao.getQuestionLogScoreDetailsInfo(query);
}
/**
* 验证是否需要重新发题,则返回重新发题的标记
* @param questionSettingId 题目配置ID
* @param studentId 学生ID
* @param questionSettingType 题目配置类型
* @param questionLogAddType 题目日志添加类型(用于判断是否交卷)
* @return boolean
*/
public boolean verifyLogAddTypeIsReSend(Long questionSettingId,
Long studentId, ResourcesQuestionSnapshotFromTypeEnum questionSettingType,
QuestionLogAddTypeEnum questionLogAddType) {
// 只有章节练习,才能进行重发试题的操作
if (!questionSettingType.equals(CHAPTER_EXERCISE)) {
return false;
}
if (ObjectUtil.isAllNotEmpty(questionSettingId, studentId, questionSettingType, questionLogAddType)) {
return generalQuestionLogDao.verifyLogAddTypeIsReSend(questionSettingId, studentId, questionSettingType, questionLogAddType);
}
return false;
}
/**
* 导出
* @param request
* @param response
* @param generalQuestionLogQuery
* @param coreUser
*/
public void exportErrorFavorite(HttpServletRequest request, HttpServletResponse response, GeneralQuestionLogQuery generalQuestionLogQuery, CoreUser coreUser) {
if(null == coreUser){
return;
}
HSSFWorkbook workbook = null;
try {
//表头数据
String[] header = {
"通用题目配置", "题目快照", "学生提交的答案", "附件,学生端上传附件", "创建时间", "状态", "学生",
"学生得分", "题型", "分值", "题干", "选项A", "选项B", "选项C", "选项D", "选项E", "答案", "解析",
"是否收藏夹", "是否错题库",
};
String[] headerCode = {
"generalQuestionSettingId", "generalResourcesQuestionSnapshotId", "generalQuestionLogAnswer",
"generalQuestionLogUploadFile", "generalQuestionLogAddTime", "generalQuestionLogStatus",
"studentId", "studentScore", "questionType", "questionScore", "questionStem", "questionOptionA",
"questionOptionB", "questionOptionC", "questionOptionD", "questionOptionE", "questionAnswer",
"questionAnalysis", "isTuck", "isErrorFavorite",
};
//数据内容
List<Map<String, Object>> mapList = getExcelValues(generalQuestionLogQuery);
//内容宽度
Map<String, Object> widthMap = mapList.get(0);
mapList.remove(0);
//声明一个工作簿
workbook = new HSSFWorkbook();
//生成一个表格,设置表格名称为"Sheet1"
HSSFSheet sheet = workbook.createSheet("Sheet1");
//冻结表头
sheet.createFreezePane(0, 1, 0, 1);
//设置默认列宽度为5个字节
sheet.setDefaultColumnWidth(5);
//创建第一行表头
HSSFRow headRow = sheet.createRow(0);
//头部样式
HSSFCellStyle headerStyle = workbook.createCellStyle();
//垂直居中
headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
//水平居中
headerStyle.setAlignment(HorizontalAlignment.CENTER);
//单元格样式
HSSFCellStyle cellStyle = workbook.createCellStyle();
//垂直居中
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
//水平居左
cellStyle.setAlignment(HorizontalAlignment.CENTER);
//自动换行
cellStyle.setWrapText(true);
//遍历添加表头
for (int i = 0; i < header.length; i++) {
//设置表格特定的列宽度
if (null != widthMap.get(headerCode[i])) {
String width = widthMap.get(headerCode[i]).toString().split("\\.")[0];
Integer w = Integer.parseInt(width) > header[i].length()*3?Integer.parseInt(width):header[i].length()*3;
sheet.setColumnWidth(i, w * 190);
}
//创建一个单元格
HSSFCell cell = headRow.createCell(i);
//创建一个内容对象
HSSFRichTextString text = new HSSFRichTextString(header[i]);
//将内容对象的文字内容写入到单元格中
cell.setCellValue(text);
//设置样式
cell.setCellStyle(headerStyle);
}
//遍历结果集,把内容加入表格
for (int i = 0; i < mapList.size(); i++) {
HSSFRow row = sheet.createRow(i + 1);
row.setHeight((short) (50*10));
Map<String, Object> map = mapList.get(i);
for (int j = 0; j < headerCode.length; j++) {
HSSFCell cell = row.createCell(j);
cell.setCellStyle(cellStyle);
HSSFRichTextString text = new HSSFRichTextString(null != map.get(headerCode[j]) ? map.get(headerCode[j]).toString() : " ");
cell.setCellValue(text);
}
}
//准备将Excel的输出流通过response输出到页面下载
//八进制输出流
response.setContentType("application/octet-stream");
//这后面可以设置导出Excel的名称此例中名为student.xls
String fileName = ToolUtils.web2fileName(request,"generalQuestionLog(" + TimeTool.getNowTime("YMD") + ").xls");
response.setHeader("Content-disposition", "attachment;filename="+fileName);
//刷新缓冲
response.flushBuffer();
//workbook将Excel写入到response的输出流中供页面下载
workbook.write(response.getOutputStream());
}catch (Exception e){
e.printStackTrace();
} finally {
try {
if (null != workbook) {
workbook.close();
}
if (null != response && null != response.getOutputStream()) {
response.getOutputStream().close();
}
} catch (Exception e) { }
}
}
}