package com.ycl.jxkg.service.impl;
|
|
import com.alibaba.excel.EasyExcel;
|
import com.alibaba.fastjson.JSON;
|
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.github.pagehelper.PageHelper;
|
import com.github.pagehelper.PageInfo;
|
import com.ycl.jxkg.base.Result;
|
import com.ycl.jxkg.domain.entity.Question;
|
import com.ycl.jxkg.domain.entity.Subject;
|
import com.ycl.jxkg.domain.other.KeyValue;
|
import com.ycl.jxkg.domain.question.QuestionItemObject;
|
import com.ycl.jxkg.domain.question.QuestionObject;
|
import com.ycl.jxkg.domain.vo.admin.exam.ExamPaperImportVO;
|
import com.ycl.jxkg.domain.vo.admin.exam.QuestionExportVO;
|
import com.ycl.jxkg.domain.vo.admin.exam.QuestionImportVO;
|
import com.ycl.jxkg.domain.vo.admin.question.QuestionEditItemVO;
|
import com.ycl.jxkg.domain.vo.admin.question.QuestionEditRequestVO;
|
import com.ycl.jxkg.domain.vo.admin.question.QuestionPageRequestVO;
|
import com.ycl.jxkg.domain.vo.admin.question.QuestionResponseVO;
|
import com.ycl.jxkg.enums.QuestionTypeEnum;
|
import com.ycl.jxkg.enums.general.StatusEnum;
|
import com.ycl.jxkg.excel.CurrencyDataListener;
|
import com.ycl.jxkg.excel.FixedMergeCellStrategy;
|
import com.ycl.jxkg.excel.SelectExcel;
|
import com.ycl.jxkg.mapper.QuestionMapper;
|
import com.ycl.jxkg.service.QuestionService;
|
import com.ycl.jxkg.service.SubjectService;
|
import com.ycl.jxkg.utils.DateTimeUtil;
|
import com.ycl.jxkg.utils.ExamUtil;
|
import com.ycl.jxkg.utils.HtmlUtil;
|
import com.ycl.jxkg.utils.JsonUtil;
|
import lombok.RequiredArgsConstructor;
|
import lombok.SneakyThrows;
|
import org.springframework.beans.BeanUtils;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.web.multipart.MultipartFile;
|
|
import javax.servlet.http.HttpServletResponse;
|
import java.net.URLEncoder;
|
import java.util.ArrayList;
|
import java.util.Arrays;
|
import java.util.Date;
|
import java.util.List;
|
import java.util.function.Consumer;
|
import java.util.stream.Collectors;
|
|
@Service
|
@RequiredArgsConstructor
|
public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, Question> implements QuestionService {
|
|
private final QuestionMapper questionMapper;
|
private final SubjectService subjectService;
|
|
@Override
|
public PageInfo<QuestionResponseVO> page(QuestionPageRequestVO requestVM) {
|
return PageHelper.startPage(requestVM.getPageIndex(), requestVM.getPageSize(), "create_time desc").doSelectPageInfo(() ->
|
questionMapper.page(requestVM)
|
);
|
}
|
|
|
@Override
|
@Transactional
|
public Question insertFullQuestion(QuestionEditRequestVO model, Integer userId) {
|
Date now = new Date();
|
|
//题干、解析、选项等 插入
|
String questionObject = setQuestionInfoFromVM(model);
|
|
Question question = new Question();
|
question.setSubjectId(model.getSubjectId());
|
question.setCreateTime(now);
|
question.setQuestionType(model.getQuestionType());
|
question.setStatus(StatusEnum.ENABLE);
|
question.setCorrectFromVM(model.getCorrect(), model.getCorrectArray());
|
question.setDifficult(model.getDifficult());
|
question.setContent(questionObject);
|
question.setCreateUser(userId);
|
question.setTitle(HtmlUtil.clear(model.getTitle()));
|
question.setAudioFile(model.getAudioFile());
|
question.setOriginalFile(model.getOriginalFile());
|
questionMapper.insert(question);
|
return question;
|
}
|
|
@Override
|
@Transactional
|
public Question updateFullQuestion(QuestionEditRequestVO model) {
|
Question question = questionMapper.selectById(model.getId());
|
question.setSubjectId(model.getSubjectId());
|
question.setDifficult(model.getDifficult());
|
question.setCorrectFromVM(model.getCorrect(), model.getCorrectArray());
|
//题干、解析、选项等 更新
|
String questionObject = setQuestionInfoFromVM(model);
|
question.setContent(questionObject);
|
question.setTitle(HtmlUtil.clear(model.getTitle()));
|
question.setAudioFile(model.getAudioFile());
|
question.setOriginalFile(model.getOriginalFile());
|
questionMapper.updateById(question);
|
return question;
|
}
|
|
@Override
|
public QuestionEditRequestVO getQuestionEditRequestVM(Integer questionId) {
|
//题目映射
|
Question question = questionMapper.selectById(questionId);
|
return getQuestionEditRequestVM(question);
|
}
|
|
@Override
|
public QuestionEditRequestVO getQuestionEditRequestVM(Question question) {
|
//题目映射
|
QuestionObject questionObject = JsonUtil.toJsonObject(question.getContent(), QuestionObject.class);
|
QuestionEditRequestVO questionEditRequestVO = new QuestionEditRequestVO();
|
BeanUtils.copyProperties(question, questionEditRequestVO);
|
questionEditRequestVO.setTitle(questionObject.getTitleContent());
|
|
//答案
|
QuestionTypeEnum questionTypeEnum = QuestionTypeEnum.fromCode(question.getQuestionType());
|
switch (questionTypeEnum) {
|
case SingleChoice:
|
case TrueFalse:
|
case Audio:
|
questionEditRequestVO.setCorrect(question.getCorrect());
|
break;
|
case MultipleChoice:
|
questionEditRequestVO.setCorrectArray(ExamUtil.contentToArray(question.getCorrect()));
|
break;
|
case GapFilling:
|
List<String> correctContent = questionObject.getQuestionItemObjects().stream().map(d -> d.getContent()).collect(Collectors.toList());
|
questionEditRequestVO.setCorrectArray(correctContent);
|
break;
|
case ShortAnswer:
|
case Calculate:
|
case Analysis:
|
questionEditRequestVO.setCorrect(questionObject.getCorrect());
|
break;
|
default:
|
break;
|
}
|
questionEditRequestVO.setAnalyze(questionObject.getAnalyze());
|
|
|
//题目项映射
|
List<QuestionEditItemVO> editItems = questionObject.getQuestionItemObjects().stream().map(o -> {
|
QuestionEditItemVO questionEditItemVO = new QuestionEditItemVO();
|
BeanUtils.copyProperties(o, questionEditItemVO);
|
return questionEditItemVO;
|
}).collect(Collectors.toList());
|
questionEditRequestVO.setItems(editItems);
|
return questionEditRequestVO;
|
}
|
|
public String setQuestionInfoFromVM(QuestionEditRequestVO model) {
|
List<QuestionItemObject> itemObjects = model.getItems().stream().map(i ->
|
{
|
QuestionItemObject item = new QuestionItemObject();
|
item.setPrefix(i.getPrefix());
|
item.setContent(i.getContent());
|
item.setItemUuid(i.getItemUuid());
|
return item;
|
}
|
).collect(Collectors.toList());
|
QuestionObject questionObject = new QuestionObject();
|
questionObject.setQuestionItemObjects(itemObjects);
|
questionObject.setAnalyze(model.getAnalyze());
|
questionObject.setTitleContent(model.getTitle());
|
questionObject.setCorrect(model.getCorrect());
|
return JsonUtil.toJsonStr(questionObject);
|
}
|
|
@Override
|
public Integer selectAllCount() {
|
return questionMapper.selectAllCount();
|
}
|
|
@Override
|
public List<Integer> selectMothCount() {
|
Date startTime = DateTimeUtil.getMonthStartDay();
|
Date endTime = DateTimeUtil.getMonthEndDay();
|
List<String> mothStartToNowFormat = DateTimeUtil.MothStartToNowFormat();
|
List<KeyValue> mouthCount = questionMapper.selectCountByDate(startTime, endTime);
|
return mothStartToNowFormat.stream().map(md -> {
|
KeyValue keyValue = mouthCount.stream().filter(kv -> kv.getName().equals(md)).findAny().orElse(null);
|
return null == keyValue ? 0 : keyValue.getValue();
|
}).collect(Collectors.toList());
|
}
|
|
@Override
|
public Boolean updateStatus(QuestionResponseVO question) {
|
return new LambdaUpdateChainWrapper<>(questionMapper)
|
.set(Question::getStatus, question.getStatus())
|
.eq(Question::getId, question.getId())
|
.update();
|
}
|
|
@Override
|
public List<ExamPaperImportVO> export(QuestionExportVO query) {
|
return questionMapper.export(query);
|
}
|
|
@Override
|
@Transactional
|
@SneakyThrows
|
public Result<Boolean> importQuestion(MultipartFile file) {
|
List<Subject> subjects = subjectService.list();
|
// 题目集合用于批量保存
|
ArrayList<Question> questions = new ArrayList<>();
|
Consumer<List<QuestionImportVO>> consumer = (data) -> {
|
// 循环每一行
|
for (int i = 0; i < data.size(); i++) {
|
// 读取的题目
|
QuestionImportVO excelQuestion = data.get(i);
|
String questionType = excelQuestion.getQuestionType();
|
// 判断是否完整题目
|
if (excelQuestion.intact()) {
|
// 循环题目
|
while (Boolean.TRUE) {
|
// 更新读取的题目
|
excelQuestion = data.get(i);
|
Question question = new Question();
|
// 该题的选项
|
List<QuestionItemObject> options = new ArrayList<>(8);
|
// 选项内容
|
QuestionItemObject option = new QuestionItemObject();
|
option.setPrefix(excelQuestion.getOptionName());
|
option.setContent(excelQuestion.getOptionValue());
|
options.add(option);
|
// 循环选项
|
while (Boolean.TRUE) {
|
// 判断是否是最后一条
|
if (i + 1 == data.size()) {
|
break;
|
}
|
QuestionImportVO nextQuestion = data.get(1 + i);
|
if (nextQuestion.intact()) {
|
break;
|
}
|
QuestionItemObject nextOption = new QuestionItemObject();
|
nextOption.setPrefix(nextQuestion.getOptionName());
|
nextOption.setContent(nextQuestion.getOptionValue());
|
options.add(nextOption);
|
i++;
|
}
|
// 保存题目内容
|
QuestionObject questionObject = new QuestionObject();
|
questionObject.setQuestionItemObjects(options);
|
questionObject.setAnalyze(excelQuestion.getAnalyze());
|
questionObject.setTitleContent(excelQuestion.getTitle());
|
questionObject.setCorrect(excelQuestion.getCorrect());
|
question.setTitle(excelQuestion.getTitle());
|
question.setContent(JSON.toJSONString(questionObject));
|
question.setQuestionType(QuestionTypeEnum.get(excelQuestion.getQuestionType()));
|
// 答案(多选需要用、分割保存字符串到数据库)
|
String[] corrects = excelQuestion.getCorrect().split("、");
|
if (corrects.length > 1) {
|
question.setCorrect(String.join(",", corrects));
|
} else {
|
question.setCorrect(excelQuestion.getCorrect());
|
}
|
// 难度
|
question.setDifficult(excelQuestion.getDifficult());
|
// 创建人
|
question.setCreateUser(2);
|
question.setStatus(StatusEnum.ENABLE);
|
question.setCreateTime(new Date());
|
question.setDeleted(0);
|
question.setQuestionType(QuestionTypeEnum.get(questionType));
|
// 根据科目名称获取id
|
QuestionImportVO finalExcelQuestion = excelQuestion;
|
question.setSubjectId(subjects.stream().filter(subject -> subject.getName().equals(finalExcelQuestion.getSubject())).findFirst().get().getId());
|
questions.add(question);
|
if (i + 1 == data.size() || data.get(i + 1).intact()) {
|
break;
|
}
|
i++;
|
}
|
}
|
}
|
};
|
EasyExcel.read(file.getInputStream(), QuestionImportVO.class, new CurrencyDataListener(consumer)).sheet("模板").doRead();
|
// 保存题目
|
return Result.ok(saveBatch(questions));
|
}
|
|
@Override
|
@SneakyThrows
|
public void importTemplate(HttpServletResponse response) {
|
String fileName = URLEncoder.encode("试卷导入模板", "UTF-8").replaceAll("\\+", "%20");
|
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
|
|
// 构建模板样例数据
|
List<QuestionImportVO> data = new ArrayList<>(8);
|
QuestionImportVO questionImportVO = new QuestionImportVO();
|
questionImportVO.setQuestionType("单选题");
|
questionImportVO.setSubject("语文");
|
questionImportVO.setDifficult(2);
|
questionImportVO.setCorrect("A");
|
questionImportVO.setScore(2);
|
questionImportVO.setAnalyze("A是对的");
|
questionImportVO.setTitle("这是一道测试题目,使用该模板请删除或替换这道题");
|
questionImportVO.setOptionName("A");
|
questionImportVO.setOptionValue("选我");
|
data.add(questionImportVO);
|
|
QuestionImportVO questionImport1 = new QuestionImportVO();
|
questionImport1.setOptionName("B");
|
questionImport1.setOptionValue("选B");
|
data.add(questionImport1);
|
|
QuestionImportVO questionImport2 = new QuestionImportVO();
|
questionImport2.setOptionName("C");
|
questionImport2.setOptionValue("选C");
|
data.add(questionImport2);
|
|
QuestionImportVO questionImport3 = new QuestionImportVO();
|
questionImport3.setOptionName("D");
|
questionImport3.setOptionValue("选D");
|
data.add(questionImport3);
|
|
// 查出所有的课目(excel下拉数据)
|
List<Subject> subjects = subjectService.list();
|
List<String> subjectNameList = subjects.stream().map(Subject::getName).collect(Collectors.toList());
|
EasyExcel.write(response.getOutputStream(), QuestionImportVO.class)
|
.sheet("模板")
|
.registerWriteHandler(new SelectExcel(subjectNameList))
|
.registerWriteHandler(new FixedMergeCellStrategy(2, 4, Arrays.asList(0, 1, 2, 5, 6, 7, 8)))
|
.doWrite(data);
|
}
|
|
}
|