【新增】生成笔试试卷,细节修改

This commit is contained in:
YOHO\20373
2025-05-26 20:13:16 +08:00
32 changed files with 892 additions and 185 deletions

View File

@@ -127,7 +127,61 @@
<groupId>org.apache.tika</groupId> <groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId> <!-- 文件客户端:文件类型的识别 --> <artifactId>tika-core</artifactId> <!-- 文件客户端:文件类型的识别 -->
</dependency> </dependency>
<!-- Apache POI 相关 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>4.4.0</version>
<exclusions>
<exclusion>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-imaging</artifactId>
<version>1.0-alpha3</version> <!-- 使用最新版本 -->
</dependency>
<!-- Adobe 官方 XMPCore 库 -->
<dependency>
<groupId>com.adobe.xmp</groupId>
<artifactId>xmpcore</artifactId>
<version>6.1.11</version> <!-- 最新稳定版 -->
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -123,12 +123,12 @@ public class EducationPaperController
} }
/** /**
* 根据方案获取试卷 * 根据方案获取试卷下拉
*/ */
@GetMapping(value = "/getPaperByTaskId") @GetMapping(value = "/getPaperByTaskId")
public CommonResult getPaperByTaskId(@RequestParam(value = "taskId") String taskId) public CommonResult getPaperByTaskId(@RequestParam(value = "taskId") String taskId)
{ {
return CommonResult.success(educationPaperService.selectPaperByTaskId(taskId)); return CommonResult.success(educationPaperService.selectPaperIdAndNumByTaskId(taskId));
} }
@@ -216,4 +216,17 @@ public class EducationPaperController
return CommonResult.success(pageResult); return CommonResult.success(pageResult);
} }
/**
* 下载试卷
* @param paperIds
* @return
*/
@GetMapping("/addUpload/{paperIds}")
public void downLoad(@PathVariable String[] paperIds, HttpServletResponse response) throws Exception {
educationPaperService.downloadWord(paperIds,response);
}
} }

View File

@@ -0,0 +1,13 @@
package pc.exam.pp.module.exam.controller.admin.paper.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PaperIdAndNum {
private String num;
private String paperId;
}

View File

@@ -73,6 +73,11 @@ public class EducationPaperScheme
// @Excel(name = "小计分数") // @Excel(name = "小计分数")
private String subtotalScore; private String subtotalScore;
/**
* 试卷呆鹅题号
*/
@TableField(exist = false)
private String upperCase;
} }

View File

@@ -2,6 +2,7 @@ package pc.exam.pp.module.exam.dal.mysql.paper;
import java.util.List; import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
@@ -9,6 +10,7 @@ import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.framework.mybatis.core.mapper.BaseMapperX; import pc.exam.pp.framework.mybatis.core.mapper.BaseMapperX;
import pc.exam.pp.framework.mybatis.core.query.LambdaQueryWrapperX; import pc.exam.pp.framework.mybatis.core.query.LambdaQueryWrapperX;
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.vo.PaperPageVo; import pc.exam.pp.module.exam.controller.admin.paper.vo.PaperPageVo;
import pc.exam.pp.module.exam.controller.admin.paper.vo.PaperTaskPageVo; import pc.exam.pp.module.exam.controller.admin.paper.vo.PaperTaskPageVo;
import pc.exam.pp.module.exam.dal.dataobject.EducationPaper; import pc.exam.pp.module.exam.dal.dataobject.EducationPaper;
@@ -93,7 +95,7 @@ public interface EducationPaperMapper extends BaseMapperX<EducationPaper>
String selectTaskIdByPaperId(String paperId); String selectTaskIdByPaperId(String paperId);
List<String> selectPaperByTaskId(String taskId); List<String> selectPaperByTaskId(String taskId);
public int updateEducationByids(@Param("strings")List<String> strings); public int updateEducationByids(@Param("strings")List<String> strings);
@@ -129,5 +131,8 @@ public interface EducationPaperMapper extends BaseMapperX<EducationPaper>
.eq(EducationPaper::getStatus, 0) .eq(EducationPaper::getStatus, 0)
); );
} }
List<PaperIdAndNum> selectPaperIdAndNumByTaskId(String taskId);
} }

View File

@@ -1,6 +1,9 @@
package pc.exam.pp.module.exam.service.paper; package pc.exam.pp.module.exam.service.paper;
import cn.afterturn.easypoi.word.WordExportUtil;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
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;
@@ -9,6 +12,7 @@ import pc.exam.pp.framework.security.core.util.SecurityFrameworkUtils;
import pc.exam.pp.framework.tenant.core.aop.TenantIgnore; 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.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;
@@ -18,6 +22,10 @@ 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.File;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.sql.Time;
import java.util.*; import java.util.*;
import static pc.exam.pp.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static pc.exam.pp.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@@ -456,6 +464,70 @@ public class EducationPaperServiceImpl implements IEducationPaperService
} }
@Override
public void downloadWord(String[] paperIds, HttpServletResponse response) throws Exception {
String paperId1 = paperIds[0];
EducationPaper educationPaper = educationPaperMapper.selectEducationPaperByPaperId(paperId1);
String taskId = educationPaper.getTaskId();
EducationPaperParam educationPaperParam = educationPaperParamMapper.selectEducationPaperParamByTaskId(taskId);
List<EducationPaperScheme> educationPaperSchemes = educationPaperSchemeMapper.selectEducationPaperTaskByTaskId(taskId);
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/试卷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();
System.out.println("错误"+e.getMessage());
}
}
@Override
public List<PaperIdAndNum> selectPaperIdAndNumByTaskId(String taskId) {
return educationPaperMapper.selectPaperIdAndNumByTaskId(taskId);
}
} }

View File

@@ -1,14 +1,18 @@
package pc.exam.pp.module.exam.service.paper; package pc.exam.pp.module.exam.service.paper;
import jakarta.servlet.http.HttpServletResponse;
import pc.exam.pp.framework.common.pojo.PageResult; import pc.exam.pp.framework.common.pojo.PageResult;
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.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.dal.dataobject.PaperListResponseVo; import pc.exam.pp.module.exam.dal.dataobject.PaperListResponseVo;
import pc.exam.pp.module.exam.dal.dataobject.EducationPaper; import pc.exam.pp.module.exam.dal.dataobject.EducationPaper;
import java.io.UnsupportedEncodingException;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* 试卷Service接口 * 试卷Service接口
@@ -92,5 +96,11 @@ public interface IEducationPaperService
PageResult<EducationPaperStuDto> selectStuEducationPaperList(PaperPageVo paperPageVo); PageResult<EducationPaperStuDto> selectStuEducationPaperList(PaperPageVo paperPageVo);
ExamPaperVo stuInfoPaper(String taskid); ExamPaperVo stuInfoPaper(String taskid);
void downloadWord(String[] paperIds, HttpServletResponse response) throws Exception;
List<PaperIdAndNum> selectPaperIdAndNumByTaskId(String taskId);
} }

View File

@@ -21,6 +21,11 @@
<result property="tenantId" column="tenant_id" /> <result property="tenantId" column="tenant_id" />
</resultMap> </resultMap>
<resultMap type="EducationPaper" id="PaperIdAndNumResult">
<result property="paperId" column="paper_id" />
<result property="num" column="num" />
</resultMap>
<resultMap type="ExamQuestion" id="ExamQuestionResult"> <resultMap type="ExamQuestion" id="ExamQuestionResult">
<result property="quId" column="qu_id" /> <result property="quId" column="qu_id" />
@@ -119,6 +124,9 @@ select task_id from education_paper where paper_id=#{paperId}
<select id="selectCountPaperList" resultType="java.lang.Integer"> <select id="selectCountPaperList" resultType="java.lang.Integer">
select count(*) from education_paper select count(*) from education_paper
</select> </select>
<select id="selectPaperIdAndNumByTaskId" resultMap="PaperIdAndNumResult">
select paper_id ,num from education_paper where task_id=#{taskId} and deleted ='0'
</select>
<insert id="insertEducationPaper" parameterType="EducationPaper"> <insert id="insertEducationPaper" parameterType="EducationPaper">

View File

@@ -42,7 +42,7 @@
where scheme_id = #{schemeId} where scheme_id = #{schemeId}
</select> </select>
<select id="selectEducationPaperTaskByTaskId" resultMap="EducationPaperSchemeResult"> <select id="selectEducationPaperTaskByTaskId" resultMap="EducationPaperSchemeResult">
select * from education_paper_scheme where task_id =#{taskid} select * from education_paper_scheme where task_id =#{taskid} order by sort asc
</select> </select>
<insert id="insertEducationPaperScheme" parameterType="EducationPaperScheme"> <insert id="insertEducationPaperScheme" parameterType="EducationPaperScheme">

View File

@@ -75,4 +75,11 @@ public class WordController {
return success(BeanUtils.toBean(word, WordRespVO.class)); return success(BeanUtils.toBean(word, WordRespVO.class));
} }
@GetMapping("/listInfo")
@Operation(summary = "获取wps_word子数据列表")
public CommonResult<List<WordRespVO>> getWordInfoList(WordListReqVO reqVO) {
List<WpsWordLinkDO> list = wpsWordLinkService.getWordInfoList(reqVO);
return success(BeanUtils.toBean(list, WordRespVO.class));
}
} }

View File

@@ -4,10 +4,10 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import pc.exam.pp.framework.common.pojo.CommonResult; import pc.exam.pp.framework.common.pojo.CommonResult;
import pc.exam.pp.module.judgement.controller.admin.Wps.dto.WpsWordJudgementDto;
import pc.exam.pp.module.judgement.controller.admin.Wps.dto.WpsWordReqDto;
import pc.exam.pp.module.judgement.service.wps_excel.JudgementWpsExcelService; import pc.exam.pp.module.judgement.service.wps_excel.JudgementWpsExcelService;
import pc.exam.pp.module.judgement.service.wps_pptx.JudgementWpsPptxService; import pc.exam.pp.module.judgement.service.wps_pptx.JudgementWpsPptxService;
import pc.exam.pp.module.judgement.service.wps_word.JudgementWpsWordService; import pc.exam.pp.module.judgement.service.wps_word.JudgementWpsWordService;
@@ -16,6 +16,7 @@ import pc.exam.pp.module.judgement.utils.wps_excel.vo.xlsx_all.XlsxAllDataReqVo;
import pc.exam.pp.module.judgement.utils.wps_excel.vo.xlsx_drawing.XlsxInfoVo; import pc.exam.pp.module.judgement.utils.wps_excel.vo.xlsx_drawing.XlsxInfoVo;
import pc.exam.pp.module.judgement.utils.wps_excel.vo.xlsx_style.XlsxStyleVO; import pc.exam.pp.module.judgement.utils.wps_excel.vo.xlsx_style.XlsxStyleVO;
import pc.exam.pp.module.judgement.utils.wps_pptx.vo.PptxVO; import pc.exam.pp.module.judgement.utils.wps_pptx.vo.PptxVO;
import pc.exam.pp.module.judgement.utils.wps_word.vo.WordInfoReqVo;
import pc.exam.pp.module.judgement.utils.wps_word.vo.WordVO; import pc.exam.pp.module.judgement.utils.wps_word.vo.WordVO;
import java.util.List; import java.util.List;
@@ -28,7 +29,7 @@ import java.util.List;
@RestController @RestController
@RequestMapping("/tool/wps") @RequestMapping("/tool/wps")
@Tag( name = "wps相关操作") @Tag( name = "测试判分 - wps相关操作")
@Validated @Validated
public class WpsController { public class WpsController {
@@ -42,25 +43,26 @@ public class WpsController {
* wps word * wps word
* @return 判分 * @return 判分
*/ */
@GetMapping("/run_wps_word") @PostMapping("/runWpsWordInfo")
public CommonResult<List<WordVO>> run_wps_word(String path) throws Exception { public CommonResult<List<WpsWordJudgementDto>> runWpsWordInfo(@RequestBody List<WpsWordReqDto> wordReqDto) throws Exception {
return CommonResult.success(judgementWpsWordService.programmingWpsWord(path)); return CommonResult.success(judgementWpsWordService.programmingInfo(wordReqDto));
}
/**
* wps pptx
* @return 判分
*/
@GetMapping("/run_wps_pptx")
public CommonResult<List<PptxVO>> run_wps_pptx(String path) throws Exception {
return CommonResult.success(judgementWpsPptxService.programmingWpsPptx(path));
}
/**
* wps xlsx
* @return 判分
*/
@GetMapping("/run_wps_xlsx")
public CommonResult<List<XlsxInfoVo>> run_wps_xlsx(String path) throws Exception {
return CommonResult.success(judgementWpsExcelService.programmingWpsExcel(path));
} }
/**
* wps word
* @return 判分
*/
@GetMapping("/runWpsWord")
public CommonResult<List<WordInfoReqVo>> runWpsWord(String path) throws Exception {
return CommonResult.success(judgementWpsWordService.programmingWpsWord(path));
}
// /**
// * wps xlsx
// * @return 判分
// */
// @GetMapping("/run_wps_xlsx")
// public CommonResult<List<XlsxInfoVo>> run_wps_xlsx(String path) throws Exception {
// return CommonResult.success(judgementWpsExcelService.programmingWpsExcel(path));
// }
} }

View File

@@ -0,0 +1,14 @@
package pc.exam.pp.module.judgement.controller.admin.Wps.dto;
import lombok.Data;
/**
* @author REN
*/
@Data
public class WpsWordChineseFunctionDto {
private String chineseName;
private String function;
}

View File

@@ -0,0 +1,12 @@
package pc.exam.pp.module.judgement.controller.admin.Wps.dto;
import lombok.Data;
/**
* @author REN
*/
@Data
public class WpsWordJudgementDto {
private String function;
private String contentIn;
}

View File

@@ -0,0 +1,19 @@
package pc.exam.pp.module.judgement.controller.admin.Wps.dto;
import lombok.Data;
import java.util.List;
/**
* @author REN
*/
@Data
public class WpsWordReqDto {
private String chineseName;
private String englishName;
private String filePath;
private String type;
private List<WpsWordChineseFunctionDto> function;
}

View File

@@ -17,5 +17,7 @@ public class WordListReqVO {
*/ */
private Integer type; private Integer type;
private String nodeFunction;
private Integer belongTo; private Integer belongTo;
} }

View File

@@ -24,6 +24,9 @@ import pc.exam.pp.module.judgement.service.wps_word.JudgementWpsWordService;
import java.util.List; import java.util.List;
/**
* @author REN
*/
@RestController @RestController
@RequestMapping("/tool") @RequestMapping("/tool")
@Tag( name = "测试判分") @Tag( name = "测试判分")
@@ -53,7 +56,7 @@ public class AutoToolsController {
@GetMapping("/getTest") @GetMapping("/getTest")
public double gets(StuPaperReqVo stuPaperReqVo) throws Exception { public double gets(StuPaperReqVo stuPaperReqVo) throws Exception {
ExamQuestion examQuestion = examQuestionService.selectExamQuestionByQuId(stuPaperReqVo.getPaperId()); ExamQuestion examQuestion = examQuestionService.selectExamQuestionByQuId(stuPaperReqVo.getPaperId());
return judgementWpsWordService.judgementWpsWord(15.0, "D:\\", "D:\\文档.docx", examQuestion); return judgementWpsWordService.judgementWpsWord(15.0, "D:\\", "D:\\stu\\wps_word\\9f7d8f5d7c68cc2bfd03a23c19045efe7ba13a4bebeb833abece146908bcd0c6.docx", examQuestion);
} }
@GetMapping("/getTests") @GetMapping("/getTests")
public double getss(StuPaperReqVo stuPaperReqVo) throws Exception { public double getss(StuPaperReqVo stuPaperReqVo) throws Exception {

View File

@@ -17,6 +17,7 @@ public interface WpsWordLinkMapper extends BaseMapperX<WpsWordLinkDO> {
return selectList(new LambdaQueryWrapperX<WpsWordLinkDO>() return selectList(new LambdaQueryWrapperX<WpsWordLinkDO>()
.likeIfPresent(WpsWordLinkDO::getName, reqVO.getName()) .likeIfPresent(WpsWordLinkDO::getName, reqVO.getName())
.eq(reqVO.getBelongTo() != null, WpsWordLinkDO::getBelongTo, reqVO.getBelongTo()) .eq(reqVO.getBelongTo() != null, WpsWordLinkDO::getBelongTo, reqVO.getBelongTo())
.eq(reqVO.getNodeFunction() != null, WpsWordLinkDO::getNodeFunction, reqVO.getNodeFunction())
.eqIfPresent(WpsWordLinkDO::getStatus, reqVO.getStatus())); .eqIfPresent(WpsWordLinkDO::getStatus, reqVO.getStatus()));
} }
@@ -24,6 +25,15 @@ public interface WpsWordLinkMapper extends BaseMapperX<WpsWordLinkDO> {
return selectOne(WpsWordLinkDO::getParentId, parentId, WpsWordLinkDO::getName, name); return selectOne(WpsWordLinkDO::getParentId, parentId, WpsWordLinkDO::getName, name);
} }
default WpsWordLinkDO selectByNodeFunction(String nodeFunction) {
return selectOne(WpsWordLinkDO::getNodeFunction, nodeFunction);
}
default List<WpsWordLinkDO> selectInfoList(Long id) {
return selectList(new LambdaQueryWrapperX<WpsWordLinkDO>()
.eqIfPresent(WpsWordLinkDO::getParentId, id));
}
default Long selectCountByParentId(Long parentId) { default Long selectCountByParentId(Long parentId) {
return selectCount(WpsWordLinkDO::getParentId, parentId); return selectCount(WpsWordLinkDO::getParentId, parentId);
} }

View File

@@ -113,7 +113,7 @@ public class JudgementServiceImpl implements JudgementService
// 如果使用程序编译,进行程序编译 // 如果使用程序编译,进行程序编译
LogFileUtils.writeLine("✅ 正在使用-std=c99进行编译..."); LogFileUtils.writeLine("✅ 正在使用-std=c99进行编译...");
// 使用C99 运行并得出结果 // 使用C99 运行并得出结果
String code_return = JudgementCUtils.run_code(code,null,"-std=c99", "编译通过运行"); String code_return = JudgementCUtils.run_code(pathC,code,null,"-std=c99", "编译通过运行");
if (!code_return.contains("error")) { if (!code_return.contains("error")) {
// 编译没有报错,加上编译分数 // 编译没有报错,加上编译分数
totalScore += pass_score; totalScore += pass_score;
@@ -133,7 +133,7 @@ public class JudgementServiceImpl implements JudgementService
LogFileUtils.writeLine("✅ 使用测试用例进行判分..."); LogFileUtils.writeLine("✅ 使用测试用例进行判分...");
for (ExamQuestionAnswer examQuestionAnswer : examQuestion.getAnswerList()) { for (ExamQuestionAnswer examQuestionAnswer : examQuestion.getAnswerList()) {
// 使用C99 运行并得出结果 // 使用C99 运行并得出结果
String code_return = JudgementCUtils.run_code(code, examQuestionAnswer.getContentIn(),"-std=c99",null); String code_return = JudgementCUtils.run_code(pathC,code, examQuestionAnswer.getContentIn(),"-std=c99",null);
String actual = code_return.trim(); String actual = code_return.trim();
String expected = examQuestionAnswer.getContent().trim(); String expected = examQuestionAnswer.getContent().trim();
if (actual.equals(expected)) { if (actual.equals(expected)) {

View File

@@ -3,6 +3,9 @@ package pc.exam.pp.module.judgement.service.wps_word;
import pc.exam.pp.module.exam.dal.dataobject.ExamQuestion; import pc.exam.pp.module.exam.dal.dataobject.ExamQuestion;
import pc.exam.pp.module.judgement.controller.admin.Wps.dto.WpsWordJudgementDto;
import pc.exam.pp.module.judgement.controller.admin.Wps.dto.WpsWordReqDto;
import pc.exam.pp.module.judgement.utils.wps_word.vo.WordInfoReqVo;
import pc.exam.pp.module.judgement.utils.wps_word.vo.WordVO; import pc.exam.pp.module.judgement.utils.wps_word.vo.WordVO;
import java.math.BigDecimal; import java.math.BigDecimal;
@@ -21,8 +24,9 @@ public interface JudgementWpsWordService {
* @return 文件内得考点及描述 * @return 文件内得考点及描述
* @throws Exception 异常 * @throws Exception 异常
*/ */
List<WordVO> programmingWpsWord(String path) throws Exception; List<WordInfoReqVo> programmingWpsWord(String path) throws Exception;
List<WpsWordJudgementDto> programmingInfo(List<WpsWordReqDto> wpsWordReqDtos) throws Exception;
/** /**

View File

@@ -9,14 +9,19 @@ import pc.exam.pp.module.exam.dal.dataobject.ExamQuestionAnswer;
import pc.exam.pp.module.exam.utils.file.LogFileUtils; import pc.exam.pp.module.exam.utils.file.LogFileUtils;
import pc.exam.pp.module.infra.dal.dataobject.config.ConfigDO; import pc.exam.pp.module.infra.dal.dataobject.config.ConfigDO;
import pc.exam.pp.module.infra.service.config.ConfigService; import pc.exam.pp.module.infra.service.config.ConfigService;
import pc.exam.pp.module.judgement.controller.admin.Wps.dto.WpsWordChineseFunctionDto;
import pc.exam.pp.module.judgement.controller.admin.Wps.dto.WpsWordJudgementDto;
import pc.exam.pp.module.judgement.controller.admin.Wps.dto.WpsWordReqDto;
import pc.exam.pp.module.judgement.controller.admin.Wps.vo.WordListReqVO; import pc.exam.pp.module.judgement.controller.admin.Wps.vo.WordListReqVO;
import pc.exam.pp.module.judgement.dal.dataobject.wpsword.WpsWordLinkDO; import pc.exam.pp.module.judgement.dal.dataobject.wpsword.WpsWordLinkDO;
import pc.exam.pp.module.judgement.dal.mysql.wpsword.WpsWordLinkMapper; import pc.exam.pp.module.judgement.dal.mysql.wpsword.WpsWordLinkMapper;
import pc.exam.pp.module.judgement.service.auto_tools.AutoToolsService; import pc.exam.pp.module.judgement.service.auto_tools.AutoToolsService;
import pc.exam.pp.module.judgement.utils.wps_word.WpsWordUtils; import pc.exam.pp.module.judgement.utils.wps_word.WpsWordUtils;
import pc.exam.pp.module.judgement.utils.wps_word.vo.WordInfoReqVo;
import pc.exam.pp.module.judgement.utils.wps_word.vo.WordVO; import pc.exam.pp.module.judgement.utils.wps_word.vo.WordVO;
import java.io.File; import java.io.File;
import java.util.ArrayList;
import java.util.List; import java.util.List;
@Service @Service
@@ -32,61 +37,82 @@ public class JudgementWpsWordServiceImpl implements JudgementWpsWordService {
ConfigService configService; ConfigService configService;
@Override @Override
public List<WordVO> programmingWpsWord(String path) throws Exception { public List<WordInfoReqVo> programmingWpsWord(String path) throws Exception {
// 1、获取文件临时下载路径 // 1、获取文件临时下载路径
ConfigDO config = configService.getConfigByKey("file_down_path"); ConfigDO config = configService.getConfigByKey("file_down_wps_word_path");
// 2、下载文件并返回文件完整路径 // 2、下载文件并返回文件完整路径
String pathName = autoToolsService.downloadStudentFile(path, config.getValue()); String pathName = autoToolsService.downloadStudentFile(path, config.getValue());
// 3、创建word考点tree // 3、创建word考点tree
WordListReqVO wordListReqVO = new WordListReqVO(); // WordListReqVO wordListReqVO = new WordListReqVO();
wordListReqVO.setBelongTo(0); // wordListReqVO.setBelongTo(0);
// 3-1、查询段落的标签 // // 3-1、查询段落的标签
List<WpsWordLinkDO> paragraphList = wpsWordLinkMapper.selectList(wordListReqVO); // List<WpsWordLinkDO> paragraphList = wpsWordLinkMapper.selectList(wordListReqVO);
// 3-2、查询锚点的标签 // // 3-2、查询锚点的标签
wordListReqVO.setBelongTo(3); // wordListReqVO.setBelongTo(3);
List<WpsWordLinkDO> anchorList = wpsWordLinkMapper.selectList(wordListReqVO); // List<WpsWordLinkDO> anchorList = wpsWordLinkMapper.selectList(wordListReqVO);
// 4、docx文件读取并返回考点及说明信息 // 4、docx文件读取并返回考点及说明信息
List<WordVO> margins = WpsWordUtils.wps_word(pathName, paragraphList, anchorList); List<WordInfoReqVo> margins = WpsWordUtils.wpWord(pathName);
// 5、已经读取完得考点删除源文件 // 5、已经读取完得考点删除源文件
File file = new File(pathName); // File file = new File(pathName);
file.delete(); // file.delete();
return margins; return margins;
} }
@Override
public List<WpsWordJudgementDto> programmingInfo(List<WpsWordReqDto> wordReqDto) throws Exception {
// List<WpsWordChineseFunctionDto> functionList = new ArrayList<>();
// for (String function : wordReqDto.getFunction()) {
// WpsWordChineseFunctionDto functionDto = new WpsWordChineseFunctionDto();
// functionDto.setFunction(function);
// WpsWordLinkDO wpsWordLinkDO = wpsWordLinkMapper.selectByNodeFunction(function);
// functionDto.setChineseName(wpsWordLinkDO.getToChinese());
// functionList.add(functionDto);
// }
List<WpsWordJudgementDto> judgementDtos = WpsWordUtils.getWordInfo(wordReqDto);
return judgementDtos;
}
@Override @Override
public double judgementWpsWord(double sorce, String pathC, String path, ExamQuestion examQuestion) throws Exception { public double judgementWpsWord(double sorce, String pathC, String path, ExamQuestion examQuestion) throws Exception {
// 创建log文件txt用于记录 // 创建log文件txt用于记录
File pathCDir = new File(pathC); LogFileUtils.createFile(pathC + "/WPS_Word判分过程.txt");
File parentDir = pathCDir.getParentFile();
// 拼接同级目录下的目标文件路径
String targetFilePath = new File(parentDir, "WPS_Word判分过程.txt").getPath();
LogFileUtils.createFile(targetFilePath);
LogFileUtils.writeLine("✅ 开始WPS_Word判分"); LogFileUtils.writeLine("✅ 开始WPS_Word判分");
double wps_word_sorce = 0; double wps_word_sorce = 0;
// 1、查询Word考点tree
WordListReqVO wordListReqVO = new WordListReqVO();
wordListReqVO.setBelongTo(0);
// 3-1、查询段落的标签
List<WpsWordLinkDO> paragraphList = wpsWordLinkMapper.selectList(wordListReqVO);
// 3-2、查询锚点的标签
wordListReqVO.setBelongTo(3);
List<WpsWordLinkDO> anchorList = wpsWordLinkMapper.selectList(wordListReqVO);
// 2、docx文件读取并返回考点及说明信息 // 2、docx文件读取并返回考点及说明信息
List<WordVO> margins = WpsWordUtils.wps_word(path, paragraphList, anchorList); // List<WordVO> margins = WpsWordUtils.wps_word(path);
// 3、获取答案得组成 // 3、获取答案得组成
List<ExamQuestionAnswer> answerList = examQuestion.getAnswerList(); List<ExamQuestionAnswer> answerList = examQuestion.getAnswerList();
// 4、进行关联判断 // 4、进行关联判断
for (ExamQuestionAnswer examQuestionAnswer : answerList) { for (ExamQuestionAnswer examQuestionAnswer : answerList) {
// 拆分数据、
String[] wordInfos = examQuestionAnswer.getContent().split("-/");
String[] chineseName = examQuestionAnswer.getContentIn().split("-");
// 创建拼接数据
// 只取三层结构
List<WpsWordReqDto> wordReqDto = new ArrayList<>();
WpsWordReqDto wpsWordReqDto = new WpsWordReqDto();
wpsWordReqDto.setChineseName(chineseName[0]);
wpsWordReqDto.setEnglishName(wordInfos[0]);
wpsWordReqDto.setType(wordInfos[0]);
wpsWordReqDto.setFilePath(path);
List<WpsWordChineseFunctionDto> functionList = new ArrayList<>();
for (int i = 1; i < 3; i++) {
WpsWordChineseFunctionDto functionDto = new WpsWordChineseFunctionDto();
functionDto.setFunction("/" + wordInfos[i]);
functionDto.setChineseName(chineseName[i]);
functionList.add(functionDto);
}
wpsWordReqDto.setFunction(functionList);
wordReqDto.add(wpsWordReqDto);
List<WpsWordJudgementDto> judgementDtos = WpsWordUtils.getWordInfo(wordReqDto);
boolean flag = false; boolean flag = false;
double one_sorce = 0; double one_sorce = 0;
for (WordVO wordVO : margins) { for (WpsWordJudgementDto wordJudgementDto : judgementDtos) {
if (wordVO.getExamKeynote() != null) { if (wordJudgementDto.getFunction() != null) {
// for (String str : wordJudgementDto.getFunction()) {
for (String str : wordVO.getExamKeynote()) {
int index = 0; int index = 0;
if ((index+str).equals(examQuestionAnswer.getContent())) { if (wordJudgementDto.getFunction().equals(examQuestionAnswer.getContent())) {
flag = true; flag = true;
// 得分 根据权重进行得分 每个选项分值 = 总分 / 总权重 // 得分 根据权重进行得分 每个选项分值 = 总分 / 总权重
@@ -98,7 +124,7 @@ public class JudgementWpsWordServiceImpl implements JudgementWpsWordService {
} }
break; break;
} }
} // }
} }
} }
wps_word_sorce += one_sorce; wps_word_sorce += one_sorce;

View File

@@ -61,6 +61,14 @@ public interface WpsWordLinkService {
*/ */
List<WpsWordLinkDO> getWordList(WordListReqVO reqVO); List<WpsWordLinkDO> getWordList(WordListReqVO reqVO);
/**
* 筛选节点列表
*
* @param reqVO 筛选条件请求 VO
* @return 节点列表
*/
List<WpsWordLinkDO> getWordInfoList(WordListReqVO reqVO);
/** /**
* 获得指定编号的节点 Map * 获得指定编号的节点 Map
* *

View File

@@ -170,6 +170,27 @@ public class WpsWordLinkServiceImpl implements WpsWordLinkService {
return list; return list;
} }
@Override
public List<WpsWordLinkDO> getWordInfoList(WordListReqVO reqVO) {
List<WpsWordLinkDO> wordList = new ArrayList<>();
WpsWordLinkDO data = wpsWordLinkMapper.selectByNodeFunction(reqVO.getNodeFunction());
if (data == null) {
return Collections.emptyList();
}
List<WpsWordLinkDO> wpsWordLinkDOS = wpsWordLinkMapper.selectInfoList(data.getId());
// 在依次判断是否还有子数据
for (WpsWordLinkDO wpsWordLinkDO : wpsWordLinkDOS) {
wordList.add(wpsWordLinkDO);
List<WpsWordLinkDO> datas = wpsWordLinkMapper.selectInfoList(wpsWordLinkDO.getId());
if (datas != null) {
for (WpsWordLinkDO wpsWordLinkDO1 : datas) {
wordList.add(wpsWordLinkDO1);
}
}
}
return wordList;
}
@Override @Override
public List<WpsWordLinkDO> getChildWordList(Collection<Long> ids) { public List<WpsWordLinkDO> getChildWordList(Collection<Long> ids) {
List<WpsWordLinkDO> children = new LinkedList<>(); List<WpsWordLinkDO> children = new LinkedList<>();

View File

@@ -66,18 +66,20 @@ public class JudgementCUtils
* @param standard 编译版本 C99 * @param standard 编译版本 C99
* @return 运行结果 * @return 运行结果
*/ */
public static String run_code(String code, String input, String standard, String text) { public static String run_code(String pathC, String code, String input, String standard, String text) {
try { try {
boolean hasInput = code.contains("scanf") || code.contains("fgets") || code.contains("getchar"); boolean hasInput = code.contains("scanf") || code.contains("fgets") || code.contains("getchar");
System.out.println(System.getenv("PATH")); System.out.println(System.getenv("PATH"));
String programC = pathC + "/program.c";
String programOut = pathC + "/program.out";
// 写入 C 源码到文件 // 写入 C 源码到文件
File file = new File("program.c"); File file = new File(programC);
try (FileWriter writer = new FileWriter(file)) { try (FileWriter writer = new FileWriter(file)) {
writer.write(code); writer.write(code);
} }
// 编译代码 // 编译代码
ProcessBuilder compileBuilder = new ProcessBuilder("gcc", standard, "program.c", "-o", "program.out"); ProcessBuilder compileBuilder = new ProcessBuilder("gcc", standard, programC, "-o", programOut);
compileBuilder.redirectErrorStream(true); compileBuilder.redirectErrorStream(true);
Process compileProcess = compileBuilder.start(); Process compileProcess = compileBuilder.start();
@@ -91,7 +93,7 @@ public class JudgementCUtils
int compileResult = compileProcess.waitFor(); int compileResult = compileProcess.waitFor();
String outputLower = compileOutput.toString().toLowerCase(); String outputLower = compileOutput.toString().toLowerCase();
if (outputLower.contains("error:") || !Files.exists(Paths.get("program.out"))) { if (outputLower.contains("error:") || !Files.exists(Paths.get(programOut))) {
// LogFileUtils.writeLine("❌ 编译失败:"); // LogFileUtils.writeLine("❌ 编译失败:");
// LogFileUtils.writeLine(compileOutput.toString()); // LogFileUtils.writeLine(compileOutput.toString());
return "编译失败,输出:\n" + compileOutput.toString(); return "编译失败,输出:\n" + compileOutput.toString();

View File

@@ -3,6 +3,7 @@ package pc.exam.pp.module.judgement.utils.tree;
import pc.exam.pp.module.judgement.dal.dataobject.wpspptx.WpsPptxLinkDO; import pc.exam.pp.module.judgement.dal.dataobject.wpspptx.WpsPptxLinkDO;
import pc.exam.pp.module.judgement.dal.dataobject.wpsword.WpsWordLinkDO; import pc.exam.pp.module.judgement.dal.dataobject.wpsword.WpsWordLinkDO;
import pc.exam.pp.module.judgement.dal.dataobject.wpsxlsx.WpsXlsxLinkDO; import pc.exam.pp.module.judgement.dal.dataobject.wpsxlsx.WpsXlsxLinkDO;
import pc.exam.pp.module.judgement.utils.wps_word.vo.WordInfoReqVo;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@@ -11,6 +12,28 @@ import java.util.Map;
public class TreeUtils { public class TreeUtils {
// public static List<WordInfoReqVo> buildTreeWordInfo(List<WordInfoReqVo> flatList) {
// Map<Integer, WordInfoReqVo> nodeMap = new HashMap<>();
// List<WordInfoReqVo> roots = new ArrayList<>();
// // 先放入 map
// for (WordInfoReqVo node : flatList) {
// nodeMap.put(Math.toIntExact(node.getId()), node);
// }
//
// // 构建树关系
// for (WordInfoReqVo node : flatList) {
// if (node.getParentId() == 0) {
// roots.add(node);
// } else {
// WordInfoReqVo parent = nodeMap.get(node.getParentId().intValue());
// if (parent != null) {
// parent.getChildren().add(node);
// }
// }
// }
// return roots;
// }
public static List<WpsWordLinkDO> buildTree(List<WpsWordLinkDO> flatList) { public static List<WpsWordLinkDO> buildTree(List<WpsWordLinkDO> flatList) {
Map<Integer, WpsWordLinkDO> nodeMap = new HashMap<>(); Map<Integer, WpsWordLinkDO> nodeMap = new HashMap<>();
List<WpsWordLinkDO> roots = new ArrayList<>(); List<WpsWordLinkDO> roots = new ArrayList<>();

View File

@@ -0,0 +1,35 @@
package pc.exam.pp.module.judgement.utils.wps_word;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@SuppressWarnings("all")
public class WpsWordNameSpaces {
public static String getNameSpace(String xmlString) {
// 2、创建最全的命名空间
Pattern pattern = Pattern.compile("xmlns:(\\w+)=\"([^\"]+)\"");
Matcher matcher = pattern.matcher(xmlString);
Map<String, String> namespaces = new HashMap<>();
while (matcher.find()) {
// 如 w, wp, a
String prefix = matcher.group(1);
// 如 http://schemas.openxmlformats.org/...
String uri = matcher.group(2);
namespaces.put(prefix, uri);
}
StringBuilder xpathBuilder = new StringBuilder();
namespaces.forEach((prefix, uri) ->
xpathBuilder.append("declare namespace ")
.append(prefix)
.append("='")
.append(uri)
.append("' ")
);
// 2-1、获取出来最全的命名空间
String allPathx = xpathBuilder.toString();
return allPathx;
}
}

View File

@@ -1,20 +1,272 @@
package pc.exam.pp.module.judgement.utils.wps_word; package pc.exam.pp.module.judgement.utils.wps_word;
import jakarta.annotation.Resource;
import org.apache.poi.xwpf.usermodel.*; import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlCursor; import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*; import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import pc.exam.pp.module.judgement.controller.admin.Wps.dto.WpsWordChineseFunctionDto;
import pc.exam.pp.module.judgement.controller.admin.Wps.dto.WpsWordJudgementDto;
import pc.exam.pp.module.judgement.controller.admin.Wps.dto.WpsWordReqDto;
import pc.exam.pp.module.judgement.dal.dataobject.wpsword.WpsWordLinkDO; import pc.exam.pp.module.judgement.dal.dataobject.wpsword.WpsWordLinkDO;
import pc.exam.pp.module.judgement.utils.tree.TreeUtils; import pc.exam.pp.module.judgement.utils.wps_word.vo.*;
import pc.exam.pp.module.judgement.utils.wps_word.vo.WordVO; import pc.exam.pp.module.judgement.utils.zipfile.ZipXmlUtils;
import javax.xml.namespace.QName;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.util.*; import java.util.*;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.IntStream; import java.util.stream.IntStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
* @author REN
*/
public class WpsWordUtils { public class WpsWordUtils {
public static String getStringRandom() {
String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
StringBuilder sb = new StringBuilder();
// 生成指定长度的随机字符字符串
for (int i = 0; i < 10; i++) {
int randomIndex = random.nextInt(characters.length());
// 随机字符
sb.append(characters.charAt(randomIndex));
}
return sb.toString();
}
public static List<WpsWordJudgementDto> getWordInfo(List<WpsWordReqDto> wpsWordReqDtos) throws Exception {
// 创建返回数组
List<WpsWordJudgementDto> judgementList = new ArrayList<>();
// 创建文件路径数组
List<Map<String, String>> filePathList = new ArrayList<>();
for (WpsWordReqDto wpsWordReqDto : wpsWordReqDtos) {
try (ZipFile zipFile = new ZipFile(wpsWordReqDto.getFilePath())) {
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
String entryName = entry.getName();
if (entryName.startsWith("word/_rels") && entryName.endsWith(".xml.rels")) {
String xmlContent = ZipXmlUtils.readZipEntry(zipFile, entryName);
XmlObject xmlObject = XmlObject.Factory.parse(xmlContent);
XmlCursor cursor = xmlObject.newCursor();
cursor.selectPath("declare namespace r='http://schemas.openxmlformats.org/package/2006/relationships' .//r:Relationships/r:Relationship");
// 存放数据
while (cursor.toNextSelection()) {
Map<String, String> map = new HashMap<>();
String rId = cursor.getAttributeText(new QName("Id"));
String target = cursor.getAttributeText(new QName("Target"));
map.put(rId, target);
filePathList.add(map);
}
}
}
XWPFDocument document = new XWPFDocument(new FileInputStream(wpsWordReqDto.getFilePath()));
XmlObject docXml = document.getDocument();
XmlCursor cursor = docXml.newCursor();
String nameSpace = WpsWordNameSpaces.getNameSpace(cursor.xmlText());
// 需要联合查询数据查询位置xml来获取准确的文件
// 开始查询标签
// 1、段落
if (wpsWordReqDto.getEnglishName().contains("w:p")) {
StringBuilder function = new StringBuilder();
StringBuilder functionAll = new StringBuilder();
StringBuilder chineseName = new StringBuilder();
for (WpsWordChineseFunctionDto functions : wpsWordReqDto.getFunction()) {
function.append(functions.getFunction());
functionAll.append("-").append(functions.getFunction());
chineseName.append(functions.getChineseName()).append("-");
}
WpsWordJudgementDto judgement = new WpsWordJudgementDto();
// 1-1、创建新的数据组
XmlCursor wpCursor = cursor.newCursor();
wpCursor.selectPath(nameSpace + "(//" + wpsWordReqDto.getEnglishName() + function);
if (wpCursor.toNextSelection()) {
String value = wpCursor.getTextValue();
judgement.setContentIn(wpsWordReqDto.getChineseName() + "-" + chineseName + value);
judgement.setFunction(wpsWordReqDto.getEnglishName() + functionAll + "-/" + value);
// 查询指定值,返回固定的文本
judgementList.add(judgement);
} else {
System.out.println("没有找到:" + chineseName);
}
}
List<XWPFHeader> headers = document.getHeaderList();
List<XWPFFooter> footers = document.getFooterList();
// 2、节
if (wpsWordReqDto.getType().contains("sectPr")) {
// 先要获取ID
XmlCursor sectPrCursor = docXml.newCursor();
String[] strTypes = new String[]{"/w:headerReference","/w:footerReference"};
boolean exists = Arrays.asList(strTypes).contains(wpsWordReqDto.getFunction().get(0).getFunction());
if (exists) {
sectPrCursor.selectPath(nameSpace + "//" + wpsWordReqDto.getEnglishName() + wpsWordReqDto.getFunction().get(0).getFunction());
String rId = "";
String type = "";
List<WordHeaderFooterVo> headerFooterVos = new ArrayList<>();
while (sectPrCursor.toNextSelection()) {
rId = sectPrCursor.getAttributeText(new QName("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "id"));
type = sectPrCursor.getAttributeText(new QName("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "type"));
WordHeaderFooterVo headerFooterVo = new WordHeaderFooterVo();
headerFooterVo.setRid(rId);
headerFooterVo.setType(type);
headerFooterVo.setXmlType(wpsWordReqDto.getFunction().get(0).getFunction());
headerFooterVos.add(headerFooterVo);
}
String fileName = "";
for (Map<String, String> str : filePathList) {
// 页眉页脚
for (WordHeaderFooterVo headerVo : headerFooterVos) {
if (str.containsKey(headerVo.getRid())) {
fileName = str.get(headerVo.getRid());
if (headerVo.getXmlType().contains("headerReference")) {
for (XWPFHeader header : headers) {
if (header.getPackagePart().getPartName().getName().contains(fileName)) {
// 2-1、针对不同的进行排查
String chineseType = Objects.equals(headerVo.getType(), "default") ? "奇数页" : Objects.equals(headerVo.getType(), "even") ? "偶数页" : "";
WpsWordJudgementDto judgement = new WpsWordJudgementDto();
List<XWPFParagraph> headerpar = header.getParagraphs();
XmlCursor headerXml = headerpar.get(0).getCTP().newCursor();
headerXml.selectPath(nameSpace + "./" + wpsWordReqDto.getFunction().get(1).getFunction());
if (headerXml.toNextSelection()) {
String value = headerXml.getTextValue();
judgement.setContentIn(wpsWordReqDto.getChineseName()+"-"+wpsWordReqDto.getFunction().get(0).getChineseName()+ "-"+ chineseType +"-" +wpsWordReqDto.getFunction().get(1).getChineseName()+"-"+value);
judgement.setFunction(wpsWordReqDto.getEnglishName()+"-"+wpsWordReqDto.getFunction().get(0).getFunction()+"-" +wpsWordReqDto.getFunction().get(1).getFunction()+"-/"+value+ "-"+ headerVo.getType());
judgementList.add(judgement);
}
}
}
} else if (headerVo.getXmlType().contains("footerReference")) {
for (XWPFFooter footer : footers) {
if (footer.getPackagePart().getPartName().getName().contains(fileName)) {
// 2-1、针对不同的进行排查
String chineseType = Objects.equals(headerVo.getType(), "default") ? "奇数页" : Objects.equals(headerVo.getType(), "even") ? "偶数页" : "";
WpsWordJudgementDto judgement = new WpsWordJudgementDto();
List<XWPFParagraph> foorerpar = footer.getParagraphs();
XmlCursor headerXml = foorerpar.get(0).getCTP().newCursor();
headerXml.selectPath(nameSpace + "./" + wpsWordReqDto.getFunction().get(1).getFunction());
if (headerXml.toNextSelection()) {
String value = headerXml.getTextValue();
judgement.setContentIn(wpsWordReqDto.getChineseName()+"-"+wpsWordReqDto.getFunction().get(0).getChineseName()+ "-"+ chineseType +"-" +wpsWordReqDto.getFunction().get(1).getChineseName()+"-"+value);
judgement.setFunction(wpsWordReqDto.getEnglishName()+"-"+wpsWordReqDto.getFunction().get(0).getFunction()+"-" +wpsWordReqDto.getFunction().get(1).getFunction()+"-/"+value+ "-"+ headerVo.getType());
judgementList.add(judgement);
}
}
}
}
}
}
}
} else {
// 需要查询主页面的方法
XmlCursor sectPrXsml = docXml.newCursor();
sectPrXsml.selectPath(nameSpace + "(//" + wpsWordReqDto.getEnglishName() + wpsWordReqDto.getFunction().get(0).getFunction() + wpsWordReqDto.getFunction().get(1).getFunction());
if (sectPrXsml.toNextSelection()) {
String value = sectPrXsml.getTextValue();
WpsWordJudgementDto judgement = new WpsWordJudgementDto();
judgement.setContentIn(wpsWordReqDto.getChineseName()+"-"+wpsWordReqDto.getFunction().get(0).getChineseName() +"-" +wpsWordReqDto.getFunction().get(1).getChineseName()+"-/"+value);
judgement.setFunction(wpsWordReqDto.getEnglishName()+"-"+wpsWordReqDto.getFunction().get(0).getFunction()+"-" +wpsWordReqDto.getFunction().get(1).getFunction()+"-/" + value);
judgementList.add(judgement);
}
}
}
//尾注
// endnoteReference
// 查询所有对应的中文
}
}
return judgementList;
}
public static void setWordInfo(String chineseName, String englishName, String selectName, String filePath, String id, String parentId, List<WordInfoReqVo> wordInfoReqVos) throws Exception {
WordInfoReqVo wordInfos = new WordInfoReqVo();
wordInfos.setName(chineseName);
wordInfos.setEnglishName(englishName);
wordInfos.setFilePath(filePath);
wordInfos.setId(id);
wordInfos.setSelectName(selectName);
wordInfos.setParentId(parentId);
wordInfoReqVos.add(wordInfos);
}
public static List<WordInfoReqVo> wpWord(String filePath) throws Exception {
List<WordInfoReqVo> wordInfoReqVos = new ArrayList<>();
XWPFDocument document = new XWPFDocument(new FileInputStream(filePath));
String xmlString = XmlUtil.getDocumentXml(document);
String namespace = WpsWordNameSpaces.getNameSpace(xmlString);
XmlObject docXml = document.getDocument();
// 1、获取文档段落W:P标签得数量判断出一个有多少段
XmlCursor wpCursor = docXml.newCursor();
String wpPath = namespace + "/w:document/w:body/w:p";
wpCursor.selectPath(wpPath);
int wpIndex = 0;
// 段落
String firstIdWp = getStringRandom();
setWordInfo("段落", "w:p", "w:p", filePath, firstIdWp, "0", wordInfoReqVos);
List<WordSecondInfoVo> wordSecondWp = new ArrayList<>();
while (wpCursor.toNextSelection()) {
wpIndex ++;
// 段落属性
if (!wpCursor.xmlText().contains("w:sectPr")) {
// 获取文本
XmlCursor wpTextXml = wpCursor.newCursor();
wpTextXml.selectPath(namespace + ".//w:r/w:t");
if (wpTextXml.toNextSelection()) {
String secondIdWp = getStringRandom();
String text = wpTextXml.getTextValue();
setWordInfo("段落" + wpIndex + ":" + text, "w:p)[" + wpIndex + "]", "w:pPr", filePath, secondIdWp, firstIdWp, wordInfoReqVos);
// 使用 。 判断句子
String[] texts = text.split("");
int textsIndex = 0;
for (String s : texts) {
String thirdIdWp = getStringRandom();
textsIndex ++;
setWordInfo("句子" + textsIndex + ":" + s, "w:p)[" + wpIndex + "]", "w:r", filePath, thirdIdWp, secondIdWp, wordInfoReqVos);
}
}
}
}
// 2、页面
XmlCursor wSectPrCursor = docXml.newCursor();
String wSectPrPath = namespace + "//w:sectPr";
wSectPrCursor.selectPath(wSectPrPath);
int wSectPrIndex = 0;
String firstIdSectPr = getStringRandom();
setWordInfo("页面", "w:sectPr", "w:sectPr", filePath, firstIdSectPr, "", wordInfoReqVos);
List<WordSecondInfoVo> wordSecondWSectPr = new ArrayList<>();
while (wSectPrCursor.toNextSelection()) {
wSectPrIndex ++;
String secondIdSectPr = getStringRandom();
setWordInfo("" + wSectPrIndex, "w:sectPr)[" + wSectPrIndex + "]", "w:sectPr", filePath, secondIdSectPr, firstIdSectPr, wordInfoReqVos);
}
// 3、图形
XmlCursor wDrawingCursor = docXml.newCursor();
String wDrawingPath = namespace + "//w:drawing";
wDrawingCursor.selectPath(wDrawingPath);
int wDrawingIndex = 0;
String firstIdDrawing = getStringRandom();
setWordInfo("图形", "w:drawing", "w:drawing", filePath, firstIdDrawing, "", wordInfoReqVos);
while (wDrawingCursor.toNextSelection()) {
wDrawingIndex ++;
String secondIdDrawing = getStringRandom();
XmlCursor wDrawingXml = wDrawingCursor.newCursor();
System.out.println(wDrawingXml.xmlText());
wDrawingXml.selectPath(namespace + ".//wp:anchor/wp:docPr/@name");
if (wDrawingXml.toNextSelection()) {
setWordInfo("图形" + wDrawingIndex + ":" + wDrawingXml.getTextValue(), "w:drawing)[" + wDrawingIndex + "]", "w:drawing", filePath, secondIdDrawing, firstIdDrawing, wordInfoReqVos);
}
}
return wordInfoReqVos;
}
/** /**
* 获取文档段落W:P标签得数量判断出一个有多少段 * 获取文档段落W:P标签得数量判断出一个有多少段
* @param filePath 文件路径 * @param filePath 文件路径
@@ -23,7 +275,7 @@ public class WpsWordUtils {
* @return List<WordVO> * @return List<WordVO>
* @throws Exception Exception * @throws Exception Exception
*/ */
public static List<WordVO> wps_word(String filePath, List<WpsWordLinkDO> paragraphList, List<WpsWordLinkDO> anchorList) throws Exception { public static List<WordVO> wps_word(String filePath) throws Exception {
List<WordVO> wordVO = new ArrayList<>(); List<WordVO> wordVO = new ArrayList<>();
int count = 0; int count = 0;
// 1、路径初始化 // 1、路径初始化
@@ -39,7 +291,7 @@ public class WpsWordUtils {
// 如 w, wp, a // 如 w, wp, a
String prefix = matcher.group(1); String prefix = matcher.group(1);
// 如 http://schemas.openxmlformats.org/... // 如 http://schemas.openxmlformats.org/...
String uri = matcher.group(2); String uri = matcher.group(2);
namespaces.put(prefix, uri); namespaces.put(prefix, uri);
} }
StringBuilder xpathBuilder = new StringBuilder(); StringBuilder xpathBuilder = new StringBuilder();
@@ -55,135 +307,138 @@ public class WpsWordUtils {
// 3、获取CTDocument对象 // 3、获取CTDocument对象
XmlObject docXml = document.getDocument(); XmlObject docXml = document.getDocument();
// 3-1、段落的树数据 // 3-1、段落的树数据
List<WpsWordLinkDO> paragraphTree = TreeUtils.buildTree(paragraphList); // List<WpsWordLinkDO> paragraphTree = TreeUtils.buildTree(paragraphList);
// 3-2、锚点的树数据 // 3-2、锚点的树数据
List<WpsWordLinkDO> anchorTree = TreeUtils.buildTree(anchorList); // List<WpsWordLinkDO> anchorTree = TreeUtils.buildTree(anchorList);
// Word XML document // Word XML document
XmlObject xmlObject = document.getDocument(); XmlObject xmlObject = document.getDocument();
for (WpsWordLinkDO anchor : anchorTree) { // for (WpsWordLinkDO anchor : anchorTree) {
String xpathAnchor = allPathx + "//" + anchor.getName(); // String xpathAnchor = allPathx + "//" + anchor.getName();
XmlCursor cursorAnchor = docXml.newCursor(); // XmlCursor cursorAnchor = docXml.newCursor();
int index = 0; // int index = 0;
cursorAnchor.selectPath(xpathAnchor); // cursorAnchor.selectPath(xpathAnchor);
while (cursorAnchor.toNextSelection()) { // while (cursorAnchor.toNextSelection()) {
type = "图片"; // type = "图片";
index += 1; // index += 1;
XmlCursor cursorAnchorXml = cursorAnchor.getObject().newCursor(); // XmlCursor cursorAnchorXml = cursorAnchor.getObject().newCursor();
XmlCursor cursorAnchorText = cursorAnchor.getObject().newCursor(); // XmlCursor cursorAnchorText = cursorAnchor.getObject().newCursor();
// 首先:判断类型 1 图片2文本框 // // 首先:判断类型 1 图片2文本框
cursorAnchorXml.selectPath(allPathx + ".//wp:anchor/wp:docPr/@id"); // cursorAnchorXml.selectPath(allPathx + ".//wp:anchor/wp:docPr/@id");
String typeValue = ""; // String typeValue = "";
while (cursorAnchorXml.toNextSelection()) { // while (cursorAnchorXml.toNextSelection()) {
typeValue = cursorAnchorXml.getTextValue(); // typeValue = cursorAnchorXml.getTextValue();
} // }
String anchorName = "图片"; // String anchorName = "图片";
if (Objects.equals(typeValue, "2")) { // if (Objects.equals(typeValue, "2")) {
type = "文本框"; // type = "文本框";
System.out.println(cursorAnchorText.xmlText()); // System.out.println(cursorAnchorText.xmlText());
// 要获取文本框的文本 // // 要获取文本框的文本
cursorAnchorText.selectPath(allPathx + ".//wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:txbx"); // cursorAnchorText.selectPath(allPathx + ".//wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:txbx");
while (cursorAnchorText.toNextSelection()) { // while (cursorAnchorText.toNextSelection()) {
System.out.println(cursorAnchorText.getObject().xmlText()); // System.out.println(cursorAnchorText.getObject().xmlText());
anchorName = cursorAnchorText.getTextValue(); // anchorName = cursorAnchorText.getTextValue();
} // }
} // }
cursorAnchorText.dispose(); // cursorAnchorText.dispose();
cursorAnchorXml.dispose(); // cursorAnchorXml.dispose();
XmlObject paraObj = cursorAnchor.getObject(); // XmlObject paraObj = cursorAnchor.getObject();
for (WpsWordLinkDO root : anchor.getChildren()) { // for (WpsWordLinkDO root : anchor.getChildren()) {
traverseTreeAndQueryXml(type, wordVO, anchor.getName(), anchorName, allPathx, root, paraObj, new ArrayList<>(), new ArrayList<>(), index,1); // traverseTreeAndQueryXml(type, wordVO, anchor.getName(), anchorName, allPathx, root, paraObj, new ArrayList<>(), new ArrayList<>(), index,1);
} // }
} // }
cursorAnchor.dispose(); // cursorAnchor.dispose();
} // }
// 创建一个list存放word读取的数据段落数据 // 创建一个list存放word读取的数据段落数据
for (WpsWordLinkDO paragraph : paragraphTree) { // for (WpsWordLinkDO paragraph : paragraphTree) {
type = "段落"; type = "段落";
// 段落划分 根据w:p标签 // 段落划分 根据w:p标签
// 到达参数节点,构造 XPath 路径查询它的值 // 到达参数节点,构造 XPath 路径查询它的值
String wpPath = allPathx + "/w:document/w:body/" + paragraph.getName(); String wpPath = allPathx + "/w:document/w:body/w:p";
XmlCursor cursor = docXml.newCursor(); XmlCursor cursor = docXml.newCursor();
int index = 0; int index = 0;
cursor.selectPath(wpPath); cursor.selectPath(wpPath);
while (cursor.toNextSelection()) { while (cursor.toNextSelection()) {
String rTextName = ""; String rTextName = "";
index += 1; index += 1;
// 每一段进行赋值,进行判断 System.out.println(index);
// // 每一段进行赋值,进行判断
XmlObject paraObj = cursor.getObject(); XmlObject paraObj = cursor.getObject();
String paraText = paraObj.xmlText(); String paraText = paraObj.xmlText();
XmlCursor rCursor = paraObj.newCursor(); System.out.println(paraText);
// 想要查询指定的path // XmlCursor rCursor = paraObj.newCursor();
rCursor.selectPath(allPathx + ".//w:r/w:t"); // // 想要查询指定的path
while (rCursor.toNextSelection()) { // rCursor.selectPath(allPathx + ".//w:r/w:t");
XmlCursor rsCursor = rCursor.getObject().newCursor(); // while (rCursor.toNextSelection()) {
rTextName = rsCursor.getTextValue(); // XmlCursor rsCursor = rCursor.getObject().newCursor();
rsCursor.dispose(); // rTextName = rsCursor.getTextValue();
} // rsCursor.dispose();
rCursor.dispose(); // }
// 创建新的 // rCursor.dispose();
for (WpsWordLinkDO root : paragraph.getChildren()) { // // 创建新的
traverseTreeAndQueryXml(type, wordVO, paragraph.getName(), rTextName, allPathx, root, paraObj, new ArrayList<>(), new ArrayList<>(), index,1); // for (WpsWordLinkDO root : paragraph.getChildren()) {
} // traverseTreeAndQueryXml(type, wordVO, paragraph.getName(), rTextName, allPathx, root, paraObj, new ArrayList<>(), new ArrayList<>(), index,1);
} // }
// }
} }
// 读取页眉的方法(需要通过页眉查询,水印,页眉文字等信息) // 读取页眉的方法(需要通过页眉查询,水印,页眉文字等信息)
List<XWPFHeader> headers = document.getHeaderList(); // List<XWPFHeader> headers = document.getHeaderList();
for (XWPFHeader header : headers) { // for (XWPFHeader header : headers) {
if (!Objects.equals(header.getText(), "")) { // if (!Objects.equals(header.getText(), "")) {
headerAndFooter(header, null, wordVO); // headerAndFooter(header, null, wordVO);
} // }
// 获取底层 XML 对象 // // 获取底层 XML 对象
CTHdrFtr ctHdrFtr = header._getHdrFtr(); // ✅ 正确方法 // CTHdrFtr ctHdrFtr = header._getHdrFtr(); // ✅ 正确方法
String xpath = allPathx + "//w:hdr/w:p/w:r/w:pict"; // String xpath = allPathx + "//w:hdr/w:p/w:r/w:pict";
XmlCursor cursor = ctHdrFtr.newCursor(); // XmlCursor cursor = ctHdrFtr.newCursor();
cursor.selectPath(xpath); // cursor.selectPath(xpath);
while (cursor.toNextSelection()) { // while (cursor.toNextSelection()) {
// 查询 v:textpath 节点 // // 查询 v:textpath 节点
cursor.selectPath( // cursor.selectPath(
allPathx + // allPathx +
".//v:textpath" // ".//v:textpath"
); // );
while (cursor.toNextSelection()) { // while (cursor.toNextSelection()) {
XmlObject textpathObj = cursor.getObject(); // XmlObject textpathObj = cursor.getObject();
String xml = textpathObj.xmlText(); // String xml = textpathObj.xmlText();
WordVO attr_word = new WordVO(); // WordVO attr_word = new WordVO();
//
// 提取属性值 // // 提取属性值
String stringAttr = cursor.getAttributeText(new javax.xml.namespace.QName("string")); // String stringAttr = cursor.getAttributeText(new javax.xml.namespace.QName("string"));
String styleAttr = cursor.getAttributeText(new javax.xml.namespace.QName("style")); // String styleAttr = cursor.getAttributeText(new javax.xml.namespace.QName("style"));
attr_word.setWordText("水印"); // attr_word.setWordText("水印");
List<String> attr = new ArrayList<>(); // List<String> attr = new ArrayList<>();
attr.add("水印文字 string 属性: " + stringAttr); // attr.add("水印文字 string 属性: " + stringAttr);
attr.add("水印 style 属性: " + styleAttr); // attr.add("水印 style 属性: " + styleAttr);
attr_word.setKeynoteChinese(attr); // attr_word.setKeynoteChinese(attr);
List<String> path = new ArrayList<>(); // List<String> path = new ArrayList<>();
path.add("name:"+stringAttr); // path.add("name:"+stringAttr);
path.add("style:"+styleAttr); // path.add("style:"+styleAttr);
attr_word.setExamKeynote(path); // attr_word.setExamKeynote(path);
attr_word.setType("水印"); // attr_word.setType("水印");
wordVO.add(attr_word); // wordVO.add(attr_word);
} // }
} // }
cursor.close(); // cursor.close();
} // }
// 获取页脚 // // 获取页脚
List<XWPFFooter> footers = document.getFooterList(); // List<XWPFFooter> footers = document.getFooterList();
for (XWPFFooter footer : footers) { // for (XWPFFooter footer : footers) {
if (!Objects.equals(footer.getText(), "")) { // if (!Objects.equals(footer.getText(), "")) {
headerAndFooter(null, footer, wordVO); // headerAndFooter(null, footer, wordVO);
} // }
} // }
// 邮件合并 // // 邮件合并
List<String> email = getMailMergeFields(document); // List<String> email = getMailMergeFields(document);
if (!email.isEmpty()) { // if (!email.isEmpty()) {
// 使用了邮件合并功能 // // 使用了邮件合并功能
WordVO email_word = new WordVO(); // WordVO email_word = new WordVO();
email_word.setWordText("邮件合并"); // email_word.setWordText("邮件合并");
email_word.setExamKeynote(email); // email_word.setExamKeynote(email);
email_word.setKeynoteChinese(email); // email_word.setKeynoteChinese(email);
email_word.setType("邮件合并"); // email_word.setType("邮件合并");
wordVO.add(email_word); // wordVO.add(email_word);
} // }
return wordVO; return wordVO;
} }
// 页眉页脚 // 页眉页脚

View File

@@ -0,0 +1,11 @@
package pc.exam.pp.module.judgement.utils.wps_word.vo;
import lombok.Data;
@Data
public class WordHeaderFooterVo {
private String rid;
private String type;
private String xmlType;
}

View File

@@ -0,0 +1,30 @@
package pc.exam.pp.module.judgement.utils.wps_word.vo;
import lombok.Data;
import org.apache.xmlbeans.XmlCursor;
import pc.exam.pp.module.judgement.dal.dataobject.wpsword.WpsWordLinkDO;
import java.util.ArrayList;
import java.util.List;
/**
* @author REN
*/
@Data
public class WordInfoReqVo {
private String name;
private String englishName;
private String filePath;
private String parentId;
private String selectName;
private String id;
private List<WordInfoReqVo> children = new ArrayList<>();
}

View File

@@ -0,0 +1,13 @@
package pc.exam.pp.module.judgement.utils.wps_word.vo;
import lombok.Data;
import java.util.List;
@Data
public class WordSecondInfoVo {
private String englishName;
private String chineseName;
private List<WordThirdInfoVo> wordThirdInfoVos;
}

View File

@@ -0,0 +1,14 @@
package pc.exam.pp.module.judgement.utils.wps_word.vo;
import lombok.Data;
/**
* @author REN
*/
@Data
public class WordThirdInfoVo {
private String englishName;
private String chineseName;
}

View File

@@ -0,0 +1,16 @@
package pc.exam.pp.module.judgement.utils.zipfile;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
public class ZipXmlUtils {
public static String readZipEntry(ZipFile zipFile, String entryName) throws IOException {
ZipEntry entry = zipFile.getEntry(entryName);
if (entry == null) return null;
try (InputStream is = zipFile.getInputStream(entry)) {
return new String(is.readAllBytes());
}
}
}

BIN
word/试卷.docx Normal file

Binary file not shown.