【修改】生成笔试试卷和试卷答案后端
This commit is contained in:
@@ -0,0 +1,19 @@
|
|||||||
|
package pc.exam.pp.module.exam.controller.admin.paper.dto;
|
||||||
|
|
||||||
|
import jdk.dynalink.linker.LinkerServices;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import pc.exam.pp.module.exam.dal.dataobject.ExamQuestionAnswer;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class PaperQueWordDto {
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
private List<ExamQuestionAnswer> answerList;
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,23 @@
|
|||||||
|
package pc.exam.pp.module.exam.controller.admin.paper.dto;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class PaperWordDto {
|
||||||
|
//大写的一二三
|
||||||
|
private String upperNum;
|
||||||
|
//题型
|
||||||
|
private String type;
|
||||||
|
//每小题多少分
|
||||||
|
private String score;
|
||||||
|
//共计多少分
|
||||||
|
private String totalScore;
|
||||||
|
//题目
|
||||||
|
private List<PaperQueWordDto> que;
|
||||||
|
}
|
@@ -74,7 +74,7 @@ public class EducationPaperScheme
|
|||||||
private String subtotalScore;
|
private String subtotalScore;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 试卷呆鹅题号
|
* 试卷大写题号
|
||||||
*/
|
*/
|
||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
private String upperCase;
|
private String upperCase;
|
||||||
|
@@ -2,8 +2,9 @@ package pc.exam.pp.module.exam.service.paper;
|
|||||||
|
|
||||||
|
|
||||||
import cn.afterturn.easypoi.word.WordExportUtil;
|
import cn.afterturn.easypoi.word.WordExportUtil;
|
||||||
|
import com.alibaba.excel.util.StringUtils;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.apache.poi.xwpf.usermodel.XWPFDocument;
|
import org.apache.poi.xwpf.usermodel.*;
|
||||||
import org.checkerframework.checker.units.qual.A;
|
import org.checkerframework.checker.units.qual.A;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -13,6 +14,8 @@ import pc.exam.pp.framework.tenant.core.aop.TenantIgnore;
|
|||||||
import pc.exam.pp.framework.tenant.core.context.TenantContextHolder;
|
import pc.exam.pp.framework.tenant.core.context.TenantContextHolder;
|
||||||
import pc.exam.pp.module.exam.controller.admin.paper.dto.EducationPaperStuDto;
|
import pc.exam.pp.module.exam.controller.admin.paper.dto.EducationPaperStuDto;
|
||||||
import pc.exam.pp.module.exam.controller.admin.paper.dto.PaperIdAndNum;
|
import pc.exam.pp.module.exam.controller.admin.paper.dto.PaperIdAndNum;
|
||||||
|
import pc.exam.pp.module.exam.controller.admin.paper.dto.PaperQueWordDto;
|
||||||
|
import pc.exam.pp.module.exam.controller.admin.paper.dto.PaperWordDto;
|
||||||
import pc.exam.pp.module.exam.controller.admin.paper.vo.ExamPaperVo;
|
import pc.exam.pp.module.exam.controller.admin.paper.vo.ExamPaperVo;
|
||||||
import pc.exam.pp.module.exam.controller.admin.paper.vo.PaperPageVo;
|
import pc.exam.pp.module.exam.controller.admin.paper.vo.PaperPageVo;
|
||||||
import pc.exam.pp.module.exam.controller.admin.paper.vo.StuInfoPaper;
|
import pc.exam.pp.module.exam.controller.admin.paper.vo.StuInfoPaper;
|
||||||
@@ -22,11 +25,16 @@ import pc.exam.pp.module.exam.dal.mysql.question.ExamQuestionMapper;
|
|||||||
import pc.exam.pp.module.exam.dal.mysql.question.SysFileMapper;
|
import pc.exam.pp.module.exam.dal.mysql.question.SysFileMapper;
|
||||||
import pc.exam.pp.module.exam.utils.uuid.IdUtils;
|
import pc.exam.pp.module.exam.utils.uuid.IdUtils;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.sql.Time;
|
import java.sql.Time;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
import static pc.exam.pp.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
import static pc.exam.pp.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||||
|
|
||||||
@@ -466,63 +474,227 @@ public class EducationPaperServiceImpl implements IEducationPaperService
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void downloadWord(String[] paperIds, HttpServletResponse response) throws Exception {
|
public void downloadWord(String[] paperIds, HttpServletResponse response) throws Exception {
|
||||||
|
String zipFileName = "试卷.zip";
|
||||||
|
|
||||||
String paperId1 = paperIds[0];
|
// 设置响应头
|
||||||
EducationPaper educationPaper = educationPaperMapper.selectEducationPaperByPaperId(paperId1);
|
response.setContentType("application/zip");
|
||||||
String taskId = educationPaper.getTaskId();
|
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(zipFileName, "UTF-8"));
|
||||||
EducationPaperParam educationPaperParam = educationPaperParamMapper.selectEducationPaperParamByTaskId(taskId);
|
|
||||||
List<EducationPaperScheme> educationPaperSchemes = educationPaperSchemeMapper.selectEducationPaperTaskByTaskId(taskId);
|
|
||||||
|
|
||||||
String[] chineseNumbers = {"一", "二", "三", "四", "五", "六", "七", "八", "九", "十","十一","十二","十三","十四","十五","十六","十七","十八","十九","二十"};
|
try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
|
||||||
|
for (String paperId1 : paperIds) {
|
||||||
|
EducationPaper educationPaper = educationPaperMapper.selectEducationPaperByPaperId(paperId1);
|
||||||
|
String taskId = educationPaper.getTaskId();
|
||||||
|
EducationPaperTask educationPaperTask = educationPaperTaskMapper.selectEducationPaperTaskByTaskId(taskId);
|
||||||
|
String taskSpecialty = educationPaperTask.getTaskSpecialty();
|
||||||
|
EducationPaperParam educationPaperParam = educationPaperParamMapper.selectEducationPaperParamByTaskId(taskId);
|
||||||
|
List<EducationPaperScheme> educationPaperSchemes = educationPaperSchemeMapper.selectEducationPaperTaskByTaskId(taskId);
|
||||||
|
|
||||||
for (int i = 0; i < educationPaperSchemes.size(); i++) {
|
String[] chineseNumbers = {"一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十"};
|
||||||
if (i < chineseNumbers.length) {
|
|
||||||
educationPaperSchemes.get(i).setUpperCase((chineseNumbers[i]));
|
for (int i = 0; i < educationPaperSchemes.size(); i++) {
|
||||||
} else {
|
if (i < chineseNumbers.length) {
|
||||||
// 超过十个后可以追加逻辑,比如用“第十一”、“第十二”……
|
educationPaperSchemes.get(i).setUpperCase(chineseNumbers[i]);
|
||||||
educationPaperSchemes.get(i).setUpperCase("第" + (i + 1) + "项");
|
} else {
|
||||||
|
educationPaperSchemes.get(i).setUpperCase("第" + (i + 1) + "项");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String wordpath = "/word/试卷.docx";
|
||||||
|
String answerpath = "/word/参考答案.docx";
|
||||||
|
String homeDir = System.getProperty("user.dir");
|
||||||
|
String wordRealpath = homeDir + wordpath;
|
||||||
|
|
||||||
|
String answerRealpath=homeDir+answerpath;
|
||||||
|
File realPath = new File(wordRealpath);
|
||||||
|
File realAnswerPath = new File(answerRealpath);
|
||||||
|
Time time = educationPaperParam.getExamTime();
|
||||||
|
int hours = time.getHours();
|
||||||
|
int minutes = time.getMinutes();
|
||||||
|
int totalMinutes = hours * 60 + minutes;
|
||||||
|
|
||||||
|
List<String> quIds = educationPaperQuMapper.selectPaperQuByPaperId(educationPaper.getPaperId());
|
||||||
|
List<ExamQuestion> examQuestionList = examQuestionMapper.selectExamQuestionListByQuIds(quIds);
|
||||||
|
|
||||||
|
List<PaperWordDto> paperWordList = new ArrayList<>();
|
||||||
|
|
||||||
|
for (EducationPaperScheme educationPaperScheme : educationPaperSchemes) {
|
||||||
|
PaperWordDto paperWordDto = new PaperWordDto();
|
||||||
|
paperWordDto.setUpperNum(educationPaperScheme.getUpperCase());
|
||||||
|
paperWordDto.setType(educationPaperScheme.getSpName());
|
||||||
|
paperWordDto.setScore(educationPaperScheme.getQuScores());
|
||||||
|
paperWordDto.setTotalScore(educationPaperScheme.getSubtotalScore());
|
||||||
|
|
||||||
|
String type = paperWordDto.getType();
|
||||||
|
List<PaperQueWordDto> queList = examQuestionList.stream()
|
||||||
|
.filter(q -> type.equals(q.getSubjectName()))
|
||||||
|
.map(q -> {
|
||||||
|
PaperQueWordDto dto = new PaperQueWordDto();
|
||||||
|
dto.setContent(q.getContent());
|
||||||
|
if ("选择题".equals(q.getSubjectName())) {
|
||||||
|
dto.setAnswerList(q.getAnswerList());
|
||||||
|
}
|
||||||
|
return dto;
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
paperWordDto.setQue(queList);
|
||||||
|
paperWordList.add(paperWordDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> params = new HashMap<>();
|
||||||
|
params.put("paperNum", educationPaper.getNum());
|
||||||
|
params.put("paperTime", totalMinutes);
|
||||||
|
params.put("paperScore", educationPaper.getPaperScore());
|
||||||
|
params.put("specialty", taskSpecialty);
|
||||||
|
XWPFDocument word = WordExportUtil.exportWord07(realPath.getPath(), params);
|
||||||
|
|
||||||
|
XWPFDocument wordAnswer = WordExportUtil.exportWord07(realAnswerPath.getPath(), params);
|
||||||
|
|
||||||
|
|
||||||
|
int columnCount = paperWordList.size();
|
||||||
|
//写入表格
|
||||||
|
XWPFTable table = word.createTable(3, 2 + columnCount);
|
||||||
|
table.getRow(0).getCell(0).setText("总 分");
|
||||||
|
table.getRow(0).getCell(1).setText("题号");
|
||||||
|
for (int i = 0; i < columnCount; i++) {
|
||||||
|
table.getRow(0).getCell(2 + i).setText(paperWordList.get(i).getUpperNum());
|
||||||
|
}
|
||||||
|
table.getRow(1).getCell(0).setText("登分人");
|
||||||
|
table.getRow(1).getCell(1).setText("题分");
|
||||||
|
for (int i = 0; i < columnCount; i++) {
|
||||||
|
table.getRow(1).getCell(2 + i).setText(String.valueOf(paperWordList.get(i).getTotalScore()));
|
||||||
|
}
|
||||||
|
table.getRow(2).getCell(0).setText("复查人");
|
||||||
|
table.getRow(2).getCell(1).setText("得分");
|
||||||
|
for (int i = 0; i < columnCount; i++) {
|
||||||
|
table.getRow(2).getCell(2 + i).setText("");
|
||||||
|
}
|
||||||
|
//写入试卷内容
|
||||||
|
for (PaperWordDto item : paperWordList) {
|
||||||
|
String typeName = item.getType(); // 题型名,如 “单选题”、“多选题”等
|
||||||
|
|
||||||
|
|
||||||
|
XWPFParagraph paragraph = word.createParagraph();
|
||||||
|
XWPFRun run = paragraph.createRun();
|
||||||
|
String line = item.getUpperNum() + "、" + item.getType() +
|
||||||
|
"(每小题" + item.getScore() + "分,共" + item.getTotalScore() + "分)";
|
||||||
|
run.setText(line);
|
||||||
|
run.setFontSize(12);
|
||||||
|
run.setBold(true);
|
||||||
|
paragraph.setSpacingAfter(200);
|
||||||
|
|
||||||
|
List<PaperQueWordDto> que = item.getQue();
|
||||||
|
if (que != null && !que.isEmpty()) {
|
||||||
|
Map<String, StringBuilder> answerMap = new LinkedHashMap<>(); // 参考答案
|
||||||
|
int index = 1;
|
||||||
|
|
||||||
|
|
||||||
|
for (PaperQueWordDto paperQueWordDto : que) {
|
||||||
|
XWPFParagraph queParagraph = word.createParagraph();
|
||||||
|
XWPFRun queRun = queParagraph.createRun();
|
||||||
|
String rawContent = paperQueWordDto.getContent();
|
||||||
|
String plainText = rawContent.replaceAll("<[^>]*>", "");
|
||||||
|
String content = index + "、" + plainText;
|
||||||
|
|
||||||
|
queRun.setText(content);
|
||||||
|
queRun.setFontSize(11);
|
||||||
|
queParagraph.setSpacingAfter(100);
|
||||||
|
|
||||||
|
List<ExamQuestionAnswer> answerList = paperQueWordDto.getAnswerList();
|
||||||
|
//写入选择题选项
|
||||||
|
if (answerList != null && !answerList.isEmpty()) {
|
||||||
|
char option = 'A';
|
||||||
|
StringBuilder correctOptions = new StringBuilder();
|
||||||
|
for (ExamQuestionAnswer examQuestionAnswer : answerList) {
|
||||||
|
XWPFParagraph optionParagraph = word.createParagraph();
|
||||||
|
XWPFRun optionRun = optionParagraph.createRun();
|
||||||
|
String optionContent = option + ". " + examQuestionAnswer.getContent();
|
||||||
|
optionRun.setText(optionContent);
|
||||||
|
optionRun.setFontSize(10);
|
||||||
|
optionParagraph.setSpacingAfter(50);
|
||||||
|
|
||||||
|
if ("0".equals(examQuestionAnswer.getIsRight())) {
|
||||||
|
correctOptions.append(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
option++;
|
||||||
|
}
|
||||||
|
// 添加到对应题型的答案集中
|
||||||
|
answerMap
|
||||||
|
.computeIfAbsent(typeName, k -> new StringBuilder())
|
||||||
|
.append(index).append("、").append(correctOptions).append("\n");
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
if (!answerMap.isEmpty()) {
|
||||||
|
XWPFParagraph answerTitlePara = wordAnswer.createParagraph();
|
||||||
|
XWPFRun titleRun = answerTitlePara.createRun();
|
||||||
|
titleRun.setText("参考答案:");
|
||||||
|
titleRun.setBold(true);
|
||||||
|
titleRun.setFontSize(12);
|
||||||
|
answerTitlePara.setSpacingAfter(200);
|
||||||
|
|
||||||
|
for (Map.Entry<String, StringBuilder> entry : answerMap.entrySet()) {
|
||||||
|
String type = entry.getKey();
|
||||||
|
StringBuilder answers = entry.getValue();
|
||||||
|
|
||||||
|
// 写题型标题
|
||||||
|
XWPFParagraph typePara = wordAnswer.createParagraph();
|
||||||
|
XWPFRun typeRun = typePara.createRun();
|
||||||
|
typeRun.setText(type); // 如:单选题、多选题
|
||||||
|
typeRun.setBold(true);
|
||||||
|
typeRun.setFontSize(11);
|
||||||
|
typePara.setSpacingAfter(100);
|
||||||
|
|
||||||
|
// 写具体答案,按行写入,每行一个段落
|
||||||
|
String[] lines = answers.toString().split("\n");
|
||||||
|
for (String li : lines) {
|
||||||
|
XWPFParagraph para = wordAnswer.createParagraph();
|
||||||
|
XWPFRun runanswer = para.createRun();
|
||||||
|
runanswer.setText(li);
|
||||||
|
runanswer.setFontSize(11);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
// 写试卷 Word
|
||||||
|
ByteArrayOutputStream wordOut = new ByteArrayOutputStream();
|
||||||
|
word.write(wordOut);
|
||||||
|
String paperNo = educationPaper.getNum();
|
||||||
|
String entryName = paperNo + "/试卷.docx";
|
||||||
|
// 写入 Zip 中:每份 Word 为压缩包中的一个文件
|
||||||
|
ZipEntry zipEntry = new ZipEntry(entryName);
|
||||||
|
zipOut.putNextEntry(zipEntry);
|
||||||
|
zipOut.write(wordOut.toByteArray());
|
||||||
|
zipOut.closeEntry();
|
||||||
|
|
||||||
|
|
||||||
|
// 写答案 Word
|
||||||
|
ByteArrayOutputStream answerOut = new ByteArrayOutputStream();
|
||||||
|
wordAnswer.write(answerOut);
|
||||||
|
String answerEntryName = paperNo + "/参考答案.docx";
|
||||||
|
ZipEntry answerEntry = new ZipEntry(answerEntryName);
|
||||||
|
zipOut.putNextEntry(answerEntry);
|
||||||
|
zipOut.write(answerOut.toByteArray());
|
||||||
|
zipOut.closeEntry();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
zipOut.flush();
|
||||||
|
|
||||||
//获取模板文档
|
} catch (Exception e) {
|
||||||
String wordpath="/word/试卷1.docx";
|
|
||||||
String homeDir = System.getProperty("user.dir");
|
|
||||||
String wordrealpath=homeDir +wordpath;
|
|
||||||
File realPath = new File(wordrealpath);
|
|
||||||
//准备数据
|
|
||||||
Map<String,Object> params =new HashMap<>();
|
|
||||||
|
|
||||||
params.put("paperNum",educationPaper.getNum());
|
|
||||||
//获得考试时常
|
|
||||||
Time time = educationPaperParam.getExamTime();
|
|
||||||
int hours = time.getHours();
|
|
||||||
int minutes = time.getMinutes();
|
|
||||||
int totalMinutes = hours * 60 + minutes;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
params.put("paperTime",totalMinutes);
|
|
||||||
params.put("paperScore",educationPaper.getPaperScore());
|
|
||||||
params.put("Schemes",educationPaperSchemes);
|
|
||||||
XWPFDocument word = WordExportUtil.exportWord07(realPath.getPath(),params);
|
|
||||||
System.out.println("wordxwpdf"+word);
|
|
||||||
String filename = educationPaper.getNum()+".docx";
|
|
||||||
|
|
||||||
response.setHeader("Content-disposition","attachment;filename:"+new String(filename.getBytes(),"UTF-8"));
|
|
||||||
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
|
||||||
System.out.println("文件"+filename);
|
|
||||||
word.write(response.getOutputStream());
|
|
||||||
|
|
||||||
}catch(Exception e) {
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
System.out.println("错误"+e.getMessage());
|
System.out.println("错误:" + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<PaperIdAndNum> selectPaperIdAndNumByTaskId(String taskId) {
|
public List<PaperIdAndNum> selectPaperIdAndNumByTaskId(String taskId) {
|
||||||
return educationPaperMapper.selectPaperIdAndNumByTaskId(taskId);
|
return educationPaperMapper.selectPaperIdAndNumByTaskId(taskId);
|
||||||
|
BIN
word/参考答案.docx
Normal file
BIN
word/参考答案.docx
Normal file
Binary file not shown.
BIN
word/试卷.docx
BIN
word/试卷.docx
Binary file not shown.
Reference in New Issue
Block a user