@@ -2,8 +2,9 @@ package pc.exam.pp.module.exam.service.paper;
import cn.afterturn.easypoi.word.WordExportUtil ;
import com.alibaba.excel.util.StringUtils ;
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.springframework.beans.factory.annotation.Autowired ;
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.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.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.PaperPageVo ;
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.utils.uuid.IdUtils ;
import java.io.ByteArrayOutputStream ;
import java.io.File ;
import java.io.FileOutputStream ;
import java.io.UnsupportedEncodingException ;
import java.net.URLEncoder ;
import java.sql.Time ;
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 ;
@@ -466,63 +474,227 @@ public class EducationPaperServiceImpl implements IEducationPaperService
@Override
public void downloadWord ( String [ ] paperIds , HttpServletResponse response ) throws Exception {
String zipFileName = " 试卷.zip " ;
String paperId1 = paperIds [ 0 ] ;
EducationPaper educationPaper = educationPaperMapper . selectEducationPaperByPaperId ( paperId1 ) ;
String taskId = educationPaper . getTaskId ( ) ;
EducationPaperParam educationPaperParam = educationPaperParamMapper . selectEducationPaperParamByTaskId ( taskId ) ;
List < EducationPaperScheme > educationPaperSchemes = educationPaperSchemeMapper . selectEducationPaperTaskByTaskId ( taskId ) ;
// 设置响应头
response . setContentType ( " application/zip " ) ;
response . setHeader ( " Content-Disposition " , " attachment;filename= " + URLEncoder . encode ( zipFileName , " UTF-8 " ) ) ;
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 + + ) {
if ( i < chineseNumbers . length ) {
educationPaperSchemes . get ( i ) . setUpperCase ( ( chineseNumbers [ i ] ) ) ;
} else {
// 超过十个后可以追加逻辑,比如用“第十一”、“第十二”……
educationPaperSchemes . get ( i ) . setUpperCase ( " 第 " + ( i + 1 ) + " 项 " ) ;
String [ ] chineseNumbers = { " 一 " , " 二 " , " 三 " , " 四 " , " 五 " , " 六 " , " 七 " , " 八 " , " 九 " , " 十 " , " 十一 " , " 十二 " , " 十三 " , " 十四 " , " 十五 " , " 十六 " , " 十七 " , " 十八 " , " 十九 " , " 二十 " } ;
for ( int i = 0 ; i < educationPaperSchemes . size ( ) ; i + + ) {
if ( i < chineseNumbers . length ) {
educationPaperSchemes . get ( i ) . setUpperCase ( chineseNumbers [ i ] ) ;
} 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 ( ) ;
//获取模板文档
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 ) {
} catch ( Exception e ) {
e . printStackTrace ( ) ;
System . out . println ( " 错误 " + e . getMessage ( ) ) ;
System . out . println ( " 错误: " + e . getMessage ( ) ) ;
}
}
@Override
public List < PaperIdAndNum > selectPaperIdAndNumByTaskId ( String taskId ) {
return educationPaperMapper . selectPaperIdAndNumByTaskId ( taskId ) ;