【新增】 1、xlsx,pptx对应关系方法 2、简单处理xlsx与pptx 原始xml
This commit is contained in:
@@ -0,0 +1,75 @@
|
|||||||
|
package pc.exam.pp.module.judgement.controller.admin.Wps;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import pc.exam.pp.framework.common.enums.CommonStatusEnum;
|
||||||
|
import pc.exam.pp.framework.common.pojo.CommonResult;
|
||||||
|
import pc.exam.pp.framework.common.util.object.BeanUtils;
|
||||||
|
import pc.exam.pp.module.judgement.controller.admin.Wps.vo.*;
|
||||||
|
import pc.exam.pp.module.judgement.dal.dataobject.wpspptx.WpsPptxLinkDO;
|
||||||
|
import pc.exam.pp.module.judgement.service.wps_pptx.WpsPptxLinkService;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static pc.exam.pp.framework.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
|
@Tag(name = "管理后台 - wps_pptx")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/wps/pptx")
|
||||||
|
@Validated
|
||||||
|
public class PptxController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private WpsPptxLinkService wpsPptxLinkService;
|
||||||
|
|
||||||
|
@PostMapping("create")
|
||||||
|
@Operation(summary = "创建wps_pptx")
|
||||||
|
public CommonResult<Long> createPptx(@Valid @RequestBody PptxSaveReqVO createReqVO) {
|
||||||
|
Long pptxId = wpsPptxLinkService.createPptx(createReqVO);
|
||||||
|
return success(pptxId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("update")
|
||||||
|
@Operation(summary = "更新wps_pptx")
|
||||||
|
public CommonResult<Boolean> updatePptx(@Valid @RequestBody PptxSaveReqVO updateReqVO) {
|
||||||
|
wpsPptxLinkService.updatePptx(updateReqVO);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("delete")
|
||||||
|
@Operation(summary = "删除wps_pptx")
|
||||||
|
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||||
|
public CommonResult<Boolean> deletePptx(@RequestParam("id") Long id) {
|
||||||
|
wpsPptxLinkService.deletePptx(id);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/list")
|
||||||
|
@Operation(summary = "获取wps_pptx列表")
|
||||||
|
public CommonResult<List<PptxRespVO>> getPptxList(PptxListReqVO reqVO) {
|
||||||
|
List<WpsPptxLinkDO> list = wpsPptxLinkService.getPptxList(reqVO);
|
||||||
|
return success(BeanUtils.toBean(list, PptxRespVO.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping(value = {"/list-all-simple", "/simple-list"})
|
||||||
|
@Operation(summary = "获取wps_pptx精简信息列表", description = "只包含被开启的wps_pptx,主要用于前端的下拉选项")
|
||||||
|
public CommonResult<List<PptxSimpleRespVO>> getSimplePptxList() {
|
||||||
|
List<WpsPptxLinkDO> list = wpsPptxLinkService.getPptxList(
|
||||||
|
new PptxListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus()));
|
||||||
|
return success(BeanUtils.toBean(list, PptxSimpleRespVO.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/get")
|
||||||
|
@Operation(summary = "获得wps_pptx信息")
|
||||||
|
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||||
|
public CommonResult<PptxRespVO> getPptx(@RequestParam("id") Long id) {
|
||||||
|
WpsPptxLinkDO pptx = wpsPptxLinkService.getPptx(id);
|
||||||
|
return success(BeanUtils.toBean(pptx, PptxRespVO.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -70,7 +70,7 @@ public class WordController {
|
|||||||
@GetMapping("/get")
|
@GetMapping("/get")
|
||||||
@Operation(summary = "获得wps_word信息")
|
@Operation(summary = "获得wps_word信息")
|
||||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||||
public CommonResult<WordRespVO> getDept(@RequestParam("id") Long id) {
|
public CommonResult<WordRespVO> getWord(@RequestParam("id") Long id) {
|
||||||
WpsWordLinkDO word = wpsWordLinkService.getWord(id);
|
WpsWordLinkDO word = wpsWordLinkService.getWord(id);
|
||||||
return success(BeanUtils.toBean(word, WordRespVO.class));
|
return success(BeanUtils.toBean(word, WordRespVO.class));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
package pc.exam.pp.module.judgement.controller.admin.Wps;
|
package pc.exam.pp.module.judgement.controller.admin.Wps;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
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.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
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.service.wps_excel.JudgementWpsExcelService;
|
||||||
|
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;
|
||||||
|
import pc.exam.pp.module.judgement.utils.wps_excel.vo.XlsxVO;
|
||||||
|
import pc.exam.pp.module.judgement.utils.wps_pptx.vo.PptxVO;
|
||||||
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;
|
||||||
@@ -15,41 +20,44 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* wps word
|
* wps word
|
||||||
* rwb
|
* rwb
|
||||||
|
* @author REN
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/tool/wps")
|
@RequestMapping("/tool/wps")
|
||||||
@Tag( name = "wps相关操作")
|
@Tag( name = "wps相关操作")
|
||||||
@Validated
|
@Validated
|
||||||
public class WpsWordController {
|
public class WpsController {
|
||||||
|
|
||||||
@Autowired
|
@Resource
|
||||||
private JudgementWpsWordService judgementWpsWordService;
|
JudgementWpsWordService judgementWpsWordService;
|
||||||
// @Resource
|
@Resource
|
||||||
// JudgementWpsExcelService judgementWpsExcelService;
|
JudgementWpsPptxService judgementWpsPptxService;
|
||||||
|
@Resource
|
||||||
|
JudgementWpsExcelService judgementWpsExcelService;
|
||||||
/**
|
/**
|
||||||
* wps word
|
* wps word
|
||||||
* @return 判分
|
* @return 判分
|
||||||
*/
|
*/
|
||||||
@GetMapping("/run_wps_word")
|
@GetMapping("/run_wps_word")
|
||||||
public CommonResult<List<WordVO>> run_wps_word(String path) throws Exception {
|
public CommonResult<List<WordVO>> run_wps_word(String path) throws Exception {
|
||||||
return CommonResult.success(judgementWpsWordService.ProgrammingWpsWord(path));
|
return CommonResult.success(judgementWpsWordService.programmingWpsWord(path));
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* wps pptx
|
* wps pptx
|
||||||
* @return 判分
|
* @return 判分
|
||||||
*/
|
*/
|
||||||
@GetMapping("/run_wps_word")
|
@GetMapping("/run_wps_pptx")
|
||||||
public CommonResult<String> run_wps_pptx(String path) throws Exception {
|
public CommonResult<List<PptxVO>> run_wps_pptx(String path) throws Exception {
|
||||||
return CommonResult.success(judgementWpsWordService.ProgrammingWpsPptx(path));
|
return CommonResult.success(judgementWpsPptxService.programmingWpsPptx(path));
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* wps word
|
* wps xlsx
|
||||||
* @return 判分
|
* @return 判分
|
||||||
*/
|
*/
|
||||||
// @GetMapping("/run_wps_excel")
|
@GetMapping("/run_wps_xlsx")
|
||||||
// public CommonResult<String> run_wps_excel(String path) throws Exception {
|
public CommonResult<List<XlsxVO>> run_wps_xlsx(String path) {
|
||||||
// return CommonResult.success(judgementWpsExcelService.ProgrammingWpsExcel(path));
|
return CommonResult.success(judgementWpsExcelService.programmingWpsExcel(path));
|
||||||
// }
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
package pc.exam.pp.module.judgement.controller.admin.Wps;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import pc.exam.pp.framework.common.enums.CommonStatusEnum;
|
||||||
|
import pc.exam.pp.framework.common.pojo.CommonResult;
|
||||||
|
import pc.exam.pp.framework.common.util.object.BeanUtils;
|
||||||
|
import pc.exam.pp.module.judgement.controller.admin.Wps.vo.*;
|
||||||
|
import pc.exam.pp.module.judgement.dal.dataobject.wpsxlsx.WpsXlsxLinkDO;
|
||||||
|
import pc.exam.pp.module.judgement.service.wps_excel.WpsXlsxLinkService;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static pc.exam.pp.framework.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
|
@Tag(name = "管理后台 - wps_xlsx")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/wps/xlsx")
|
||||||
|
@Validated
|
||||||
|
public class XlsxController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private WpsXlsxLinkService wpsXlsxLinkService;
|
||||||
|
|
||||||
|
@PostMapping("create")
|
||||||
|
@Operation(summary = "创建wps_xlsx")
|
||||||
|
public CommonResult<Long> createXlsx(@Valid @RequestBody XlsxSaveReqVO createReqVO) {
|
||||||
|
Long xlsxId = wpsXlsxLinkService.createXlsx(createReqVO);
|
||||||
|
return success(xlsxId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("update")
|
||||||
|
@Operation(summary = "更新wps_xlsx")
|
||||||
|
public CommonResult<Boolean> updateXlsx(@Valid @RequestBody XlsxSaveReqVO updateReqVO) {
|
||||||
|
wpsXlsxLinkService.updateXlsx(updateReqVO);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("delete")
|
||||||
|
@Operation(summary = "删除wps_xlsx")
|
||||||
|
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||||
|
public CommonResult<Boolean> deleteXlsx(@RequestParam("id") Long id) {
|
||||||
|
wpsXlsxLinkService.deleteXlsx(id);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/list")
|
||||||
|
@Operation(summary = "获取wps_xlsx列表")
|
||||||
|
public CommonResult<List<XlsxRespVO>> getXlsxList(XlsxListReqVO reqVO) {
|
||||||
|
List<WpsXlsxLinkDO> list = wpsXlsxLinkService.getXlsxList(reqVO);
|
||||||
|
return success(BeanUtils.toBean(list, XlsxRespVO.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping(value = {"/list-all-simple", "/simple-list"})
|
||||||
|
@Operation(summary = "获取wps_xlsx精简信息列表", description = "只包含被开启的wps_xlsx,主要用于前端的下拉选项")
|
||||||
|
public CommonResult<List<XlsxSimpleRespVO>> getSimpleXlsxList() {
|
||||||
|
List<WpsXlsxLinkDO> list = wpsXlsxLinkService.getXlsxList(
|
||||||
|
new XlsxListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus()));
|
||||||
|
return success(BeanUtils.toBean(list, XlsxSimpleRespVO.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/get")
|
||||||
|
@Operation(summary = "获得wps_xlsx信息")
|
||||||
|
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||||
|
public CommonResult<XlsxRespVO> getPptx(@RequestParam("id") Long id) {
|
||||||
|
WpsXlsxLinkDO xlsx = wpsXlsxLinkService.getXlsx(id);
|
||||||
|
return success(BeanUtils.toBean(xlsx, XlsxRespVO.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package pc.exam.pp.module.judgement.controller.admin.Wps.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - WpsWord对应关系 Request VO")
|
||||||
|
@Data
|
||||||
|
public class PptxListReqVO {
|
||||||
|
|
||||||
|
@Schema(description = "节点名称模糊匹配", example = "芋道")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
|
||||||
|
private Integer status;
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
private Integer type;
|
||||||
|
|
||||||
|
private Integer belongTo;
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package pc.exam.pp.module.judgement.controller.admin.Wps.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - 节点信息 Response VO")
|
||||||
|
@Data
|
||||||
|
public class PptxRespVO {
|
||||||
|
|
||||||
|
@Schema(description = "节点编号", example = "1024")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "节点名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "父节点 ID", example = "1024")
|
||||||
|
private Long parentId;
|
||||||
|
|
||||||
|
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
|
private Integer sort;
|
||||||
|
|
||||||
|
@Schema(description = "节点方法")
|
||||||
|
private String nodeFunction;
|
||||||
|
|
||||||
|
@Schema(description = "转中文")
|
||||||
|
private String toChinese;
|
||||||
|
|
||||||
|
@Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式")
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
private Integer type;
|
||||||
|
private Integer belongTo;
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package pc.exam.pp.module.judgement.controller.admin.Wps.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
import lombok.Data;
|
||||||
|
import pc.exam.pp.framework.common.enums.CommonStatusEnum;
|
||||||
|
import pc.exam.pp.framework.common.validation.InEnum;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - 节点创建/修改 Request VO")
|
||||||
|
@Data
|
||||||
|
public class PptxSaveReqVO {
|
||||||
|
|
||||||
|
@Schema(description = "节点编号", example = "1024")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "节点名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
|
||||||
|
@NotBlank(message = "节点名称不能为空")
|
||||||
|
@Size(max = 30, message = "节点名称长度不能超过 30 个字符")
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
private Integer type;
|
||||||
|
private Integer belongTo;
|
||||||
|
|
||||||
|
@Schema(description = "父节点 ID", example = "1024")
|
||||||
|
private Long parentId;
|
||||||
|
|
||||||
|
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
|
@NotNull(message = "显示顺序不能为空")
|
||||||
|
private Integer sort;
|
||||||
|
|
||||||
|
@Schema(description = "节点方法")
|
||||||
|
private String nodeFunction;
|
||||||
|
|
||||||
|
@Schema(description = "转中文")
|
||||||
|
private String toChinese;
|
||||||
|
|
||||||
|
@Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||||
|
@NotNull(message = "状态不能为空")
|
||||||
|
@InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package pc.exam.pp.module.judgement.controller.admin.Wps.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - 节点精简信息 Response VO")
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class PptxSimpleRespVO {
|
||||||
|
|
||||||
|
@Schema(description = "节点编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "节点名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "父节点 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
|
private Long parentId;
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
private Integer type;
|
||||||
|
private Integer belongTo;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package pc.exam.pp.module.judgement.controller.admin.Wps.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - WpsWord对应关系 Request VO")
|
||||||
|
@Data
|
||||||
|
public class XlsxListReqVO {
|
||||||
|
|
||||||
|
@Schema(description = "节点名称模糊匹配", example = "芋道")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
|
||||||
|
private Integer status;
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
private Integer type;
|
||||||
|
|
||||||
|
private Integer belongTo;
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package pc.exam.pp.module.judgement.controller.admin.Wps.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - 节点信息 Response VO")
|
||||||
|
@Data
|
||||||
|
public class XlsxRespVO {
|
||||||
|
|
||||||
|
@Schema(description = "节点编号", example = "1024")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "节点名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "父节点 ID", example = "1024")
|
||||||
|
private Long parentId;
|
||||||
|
|
||||||
|
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
|
private Integer sort;
|
||||||
|
|
||||||
|
@Schema(description = "节点方法")
|
||||||
|
private String nodeFunction;
|
||||||
|
|
||||||
|
@Schema(description = "转中文")
|
||||||
|
private String toChinese;
|
||||||
|
|
||||||
|
@Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式")
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
private Integer type;
|
||||||
|
private Integer belongTo;
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package pc.exam.pp.module.judgement.controller.admin.Wps.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
import lombok.Data;
|
||||||
|
import pc.exam.pp.framework.common.enums.CommonStatusEnum;
|
||||||
|
import pc.exam.pp.framework.common.validation.InEnum;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - 节点创建/修改 Request VO")
|
||||||
|
@Data
|
||||||
|
public class XlsxSaveReqVO {
|
||||||
|
|
||||||
|
@Schema(description = "节点编号", example = "1024")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "节点名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
|
||||||
|
@NotBlank(message = "节点名称不能为空")
|
||||||
|
@Size(max = 30, message = "节点名称长度不能超过 30 个字符")
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
private Integer type;
|
||||||
|
private Integer belongTo;
|
||||||
|
|
||||||
|
@Schema(description = "父节点 ID", example = "1024")
|
||||||
|
private Long parentId;
|
||||||
|
|
||||||
|
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
|
@NotNull(message = "显示顺序不能为空")
|
||||||
|
private Integer sort;
|
||||||
|
|
||||||
|
@Schema(description = "节点方法")
|
||||||
|
private String nodeFunction;
|
||||||
|
|
||||||
|
@Schema(description = "转中文")
|
||||||
|
private String toChinese;
|
||||||
|
|
||||||
|
@Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||||
|
@NotNull(message = "状态不能为空")
|
||||||
|
@InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package pc.exam.pp.module.judgement.controller.admin.Wps.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - 节点精简信息 Response VO")
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class XlsxSimpleRespVO {
|
||||||
|
|
||||||
|
@Schema(description = "节点编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "节点名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "父节点 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
|
private Long parentId;
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
private Integer type;
|
||||||
|
private Integer belongTo;
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
package pc.exam.pp.module.judgement.dal.dataobject.wpspptx;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import pc.exam.pp.framework.common.enums.CommonStatusEnum;
|
||||||
|
import pc.exam.pp.framework.tenant.core.db.TenantBaseDO;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wps pptx关系对应表
|
||||||
|
*
|
||||||
|
* @author REN
|
||||||
|
*/
|
||||||
|
@TableName("wps_pptx_link")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class WpsPptxLinkDO extends TenantBaseDO {
|
||||||
|
|
||||||
|
public static final Long PARENT_ID_ROOT = 0L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门ID
|
||||||
|
*/
|
||||||
|
@TableId
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 部门名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 父部门ID
|
||||||
|
*
|
||||||
|
* 关联 {@link #id}
|
||||||
|
*/
|
||||||
|
private Long parentId;
|
||||||
|
/**
|
||||||
|
* 显示顺序
|
||||||
|
*/
|
||||||
|
private Integer sort;
|
||||||
|
/**
|
||||||
|
* 节点功能
|
||||||
|
*/
|
||||||
|
private String nodeFunction;
|
||||||
|
/**
|
||||||
|
* 中文描述
|
||||||
|
*/
|
||||||
|
private String toChinese;
|
||||||
|
/**
|
||||||
|
* 状态
|
||||||
|
*
|
||||||
|
* 枚举 {@link CommonStatusEnum}
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
private Integer type;
|
||||||
|
private String belongTo;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private List<WpsPptxLinkDO> children = new ArrayList<>();
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
package pc.exam.pp.module.judgement.dal.dataobject.wpsxlsx;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import pc.exam.pp.framework.common.enums.CommonStatusEnum;
|
||||||
|
import pc.exam.pp.framework.tenant.core.db.TenantBaseDO;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wps xlsx关系对应表
|
||||||
|
*
|
||||||
|
* @author REN
|
||||||
|
*/
|
||||||
|
@TableName("wps_xlsx_link")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class WpsXlsxLinkDO extends TenantBaseDO {
|
||||||
|
|
||||||
|
public static final Long PARENT_ID_ROOT = 0L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门ID
|
||||||
|
*/
|
||||||
|
@TableId
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 部门名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 父部门ID
|
||||||
|
*
|
||||||
|
* 关联 {@link #id}
|
||||||
|
*/
|
||||||
|
private Long parentId;
|
||||||
|
/**
|
||||||
|
* 显示顺序
|
||||||
|
*/
|
||||||
|
private Integer sort;
|
||||||
|
/**
|
||||||
|
* 节点功能
|
||||||
|
*/
|
||||||
|
private String nodeFunction;
|
||||||
|
/**
|
||||||
|
* 中文描述
|
||||||
|
*/
|
||||||
|
private String toChinese;
|
||||||
|
/**
|
||||||
|
* 状态
|
||||||
|
*
|
||||||
|
* 枚举 {@link CommonStatusEnum}
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
private Integer type;
|
||||||
|
private String belongTo;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private List<WpsXlsxLinkDO> children = new ArrayList<>();
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package pc.exam.pp.module.judgement.dal.mysql.wpspptx;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import pc.exam.pp.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
|
import pc.exam.pp.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
|
import pc.exam.pp.module.judgement.controller.admin.Wps.vo.PptxListReqVO;
|
||||||
|
import pc.exam.pp.module.judgement.dal.dataobject.wpspptx.WpsPptxLinkDO;
|
||||||
|
import pc.exam.pp.module.judgement.utils.tree.vo.TreeVO;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface WpsPptxLinkMapper extends BaseMapperX<WpsPptxLinkDO> {
|
||||||
|
|
||||||
|
default List<WpsPptxLinkDO> selectList(PptxListReqVO reqVO) {
|
||||||
|
return selectList(new LambdaQueryWrapperX<WpsPptxLinkDO>()
|
||||||
|
.likeIfPresent(WpsPptxLinkDO::getName, reqVO.getName())
|
||||||
|
.eq(reqVO.getBelongTo() != null, WpsPptxLinkDO::getBelongTo, reqVO.getBelongTo())
|
||||||
|
.eqIfPresent(WpsPptxLinkDO::getStatus, reqVO.getStatus()));
|
||||||
|
}
|
||||||
|
|
||||||
|
default WpsPptxLinkDO selectByParentIdAndName(Long parentId, String name) {
|
||||||
|
return selectOne(WpsPptxLinkDO::getParentId, parentId, WpsPptxLinkDO::getName, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
default Long selectCountByParentId(Long parentId) {
|
||||||
|
return selectCount(WpsPptxLinkDO::getParentId, parentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
default List<WpsPptxLinkDO> selectListByParentId(Collection<Long> parentIds) {
|
||||||
|
return selectList(WpsPptxLinkDO::getParentId, parentIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<TreeVO> selectTreeListByNodeFunction();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package pc.exam.pp.module.judgement.dal.mysql.wpsxlsx;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import pc.exam.pp.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
|
import pc.exam.pp.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
|
import pc.exam.pp.module.judgement.controller.admin.Wps.vo.XlsxListReqVO;
|
||||||
|
import pc.exam.pp.module.judgement.dal.dataobject.wpsxlsx.WpsXlsxLinkDO;
|
||||||
|
import pc.exam.pp.module.judgement.utils.tree.vo.TreeVO;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface WpsXlsxLinkMapper extends BaseMapperX<WpsXlsxLinkDO> {
|
||||||
|
|
||||||
|
default List<WpsXlsxLinkDO> selectList(XlsxListReqVO reqVO) {
|
||||||
|
return selectList(new LambdaQueryWrapperX<WpsXlsxLinkDO>()
|
||||||
|
.likeIfPresent(WpsXlsxLinkDO::getName, reqVO.getName())
|
||||||
|
.eq(reqVO.getBelongTo() != null, WpsXlsxLinkDO::getBelongTo, reqVO.getBelongTo())
|
||||||
|
.eqIfPresent(WpsXlsxLinkDO::getStatus, reqVO.getStatus()));
|
||||||
|
}
|
||||||
|
|
||||||
|
default WpsXlsxLinkDO selectByParentIdAndName(Long parentId, String name) {
|
||||||
|
return selectOne(WpsXlsxLinkDO::getParentId, parentId, WpsXlsxLinkDO::getName, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
default Long selectCountByParentId(Long parentId) {
|
||||||
|
return selectCount(WpsXlsxLinkDO::getParentId, parentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
default List<WpsXlsxLinkDO> selectListByParentId(Collection<Long> parentIds) {
|
||||||
|
return selectList(WpsXlsxLinkDO::getParentId, parentIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<TreeVO> selectTreeListByNodeFunction();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package pc.exam.pp.module.judgement.service.wps_excel;
|
|||||||
|
|
||||||
|
|
||||||
import pc.exam.pp.module.exam.dal.dataobject.ExamQuestion;
|
import pc.exam.pp.module.exam.dal.dataobject.ExamQuestion;
|
||||||
|
import pc.exam.pp.module.judgement.utils.wps_excel.vo.XlsxVO;
|
||||||
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.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
@@ -21,5 +22,5 @@ public interface JudgementWpsExcelService {
|
|||||||
* @return 文件内得考点及描述
|
* @return 文件内得考点及描述
|
||||||
* @throws Exception 异常
|
* @throws Exception 异常
|
||||||
*/
|
*/
|
||||||
public String ProgrammingWpsExcel(String path) throws FileNotFoundException;
|
List<XlsxVO> programmingWpsExcel(String path);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,18 +4,26 @@ package pc.exam.pp.module.judgement.service.wps_excel;
|
|||||||
|
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
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.vo.WordListReqVO;
|
||||||
|
import pc.exam.pp.module.judgement.controller.admin.Wps.vo.XlsxListReqVO;
|
||||||
|
import pc.exam.pp.module.judgement.dal.dataobject.wpsxlsx.WpsXlsxLinkDO;
|
||||||
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.dal.mysql.wpsxlsx.WpsXlsxLinkMapper;
|
||||||
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_excel.WpsExcelUtils;
|
import pc.exam.pp.module.judgement.utils.wps_excel.WpsExcelUtils;
|
||||||
|
import pc.exam.pp.module.judgement.utils.wps_excel.vo.XlsxVO;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class JudgementWpsExcelServiceImpl implements JudgementWpsExcelService {
|
public class JudgementWpsExcelServiceImpl implements JudgementWpsExcelService {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
WpsWordLinkMapper wpsWordLinkMapper;
|
WpsXlsxLinkMapper wpsXlsxLinkMapper;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
AutoToolsService autoToolsService;
|
AutoToolsService autoToolsService;
|
||||||
@@ -24,21 +32,19 @@ public class JudgementWpsExcelServiceImpl implements JudgementWpsExcelService {
|
|||||||
ConfigService configService;
|
ConfigService configService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String ProgrammingWpsExcel(String path) throws FileNotFoundException {
|
public List<XlsxVO> programmingWpsExcel(String path) {
|
||||||
// // 1、获取文件临时下载路径
|
// 1、获取文件临时下载路径
|
||||||
// ConfigDO config = configService.getConfigByKey("file_down_path");
|
ConfigDO config = configService.getConfigByKey("file_down_path");
|
||||||
// // 2、下载文件并返回文件完整路径
|
// 2、下载文件并返回文件完整路径
|
||||||
// String pathName = autoToolsService.downloadStudentFile(path, config.getValue());
|
String pathName = autoToolsService.downloadStudentFile(path, config.getValue());
|
||||||
// // 3、创建word考点tree
|
// 3、创建xlsx考点tree
|
||||||
// WordListReqVO wordListReqVO = new WordListReqVO();
|
XlsxListReqVO xlsxListReqVO = new XlsxListReqVO();
|
||||||
// wordListReqVO.setBelongTo(0);
|
xlsxListReqVO.setBelongTo(0);
|
||||||
// List<WpsWordLinkDO> list = wpsWordLinkMapper.selectList(wordListReqVO);
|
List<WpsXlsxLinkDO> xlsxList = wpsXlsxLinkMapper.selectList(xlsxListReqVO);
|
||||||
// // 4、docx文件读取并返回考点及说明信息
|
List<XlsxVO> margins1 = WpsExcelUtils.wpsExcel(pathName, xlsxList);
|
||||||
path = "D:\\Code\\exam\\word\\202504171100_wps表格处理\\202504171100_wps表格处理\\885\\ET_001_319\\结果素材\\文档.xlsx";
|
|
||||||
String margins1 = WpsExcelUtils.wps_excel(path);
|
|
||||||
// // 5、已经读取完得考点删除源文件
|
// // 5、已经读取完得考点删除源文件
|
||||||
// File file = new File(pathName);
|
File file = new File(pathName);
|
||||||
// file.delete();
|
file.delete();
|
||||||
return margins1;
|
return margins1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,115 @@
|
|||||||
|
package pc.exam.pp.module.judgement.service.wps_excel;
|
||||||
|
|
||||||
|
import pc.exam.pp.framework.common.util.collection.CollectionUtils;
|
||||||
|
import pc.exam.pp.module.judgement.controller.admin.Wps.vo.PptxListReqVO;
|
||||||
|
import pc.exam.pp.module.judgement.controller.admin.Wps.vo.PptxSaveReqVO;
|
||||||
|
import pc.exam.pp.module.judgement.controller.admin.Wps.vo.XlsxListReqVO;
|
||||||
|
import pc.exam.pp.module.judgement.controller.admin.Wps.vo.XlsxSaveReqVO;
|
||||||
|
import pc.exam.pp.module.judgement.dal.dataobject.wpspptx.WpsPptxLinkDO;
|
||||||
|
import pc.exam.pp.module.judgement.dal.dataobject.wpsxlsx.WpsXlsxLinkDO;
|
||||||
|
import pc.exam.pp.module.judgement.utils.tree.vo.TreeVO;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点 Service 接口
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public interface WpsXlsxLinkService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建节点
|
||||||
|
*
|
||||||
|
* @param createReqVO 节点信息
|
||||||
|
* @return 节点编号
|
||||||
|
*/
|
||||||
|
Long createXlsx(XlsxSaveReqVO createReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新节点
|
||||||
|
*
|
||||||
|
* @param updateReqVO 节点信息
|
||||||
|
*/
|
||||||
|
void updateXlsx(XlsxSaveReqVO updateReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除节点
|
||||||
|
*
|
||||||
|
* @param id 节点编号
|
||||||
|
*/
|
||||||
|
void deleteXlsx(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得节点信息
|
||||||
|
*
|
||||||
|
* @param id 节点编号
|
||||||
|
* @return 节点信息
|
||||||
|
*/
|
||||||
|
WpsXlsxLinkDO getXlsx(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得节点信息数组
|
||||||
|
*
|
||||||
|
* @param ids 节点编号数组
|
||||||
|
* @return 节点信息数组
|
||||||
|
*/
|
||||||
|
List<WpsXlsxLinkDO> getXlsxList(Collection<Long> ids);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 筛选节点列表
|
||||||
|
*
|
||||||
|
* @param reqVO 筛选条件请求 VO
|
||||||
|
* @return 节点列表
|
||||||
|
*/
|
||||||
|
List<WpsXlsxLinkDO> getXlsxList(XlsxListReqVO reqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得指定编号的节点 Map
|
||||||
|
*
|
||||||
|
* @param ids 节点编号数组
|
||||||
|
* @return 节点 Map
|
||||||
|
*/
|
||||||
|
default Map<Long, WpsXlsxLinkDO> getXlsxMap(Collection<Long> ids) {
|
||||||
|
List<WpsXlsxLinkDO> list = getXlsxList(ids);
|
||||||
|
return CollectionUtils.convertMap(list, WpsXlsxLinkDO::getId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得指定节点的所有子节点
|
||||||
|
*
|
||||||
|
* @param id 节点编号
|
||||||
|
* @return 子节点列表
|
||||||
|
*/
|
||||||
|
default List<WpsXlsxLinkDO> getChildXlsxList(Long id) {
|
||||||
|
return getChildXlsxList(Collections.singleton(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得指定节点的所有子节点
|
||||||
|
*
|
||||||
|
* @param ids 节点编号数组
|
||||||
|
* @return 子节点列表
|
||||||
|
*/
|
||||||
|
List<WpsXlsxLinkDO> getChildXlsxList(Collection<Long> ids);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得所有子节点,从缓存中
|
||||||
|
*
|
||||||
|
* @param id 父节点编号
|
||||||
|
* @return 子节点列表
|
||||||
|
*/
|
||||||
|
Set<Long> getChildXlsxIdListFromCache(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验节点们是否有效。如下情况,视为无效:
|
||||||
|
* 1. 节点编号不存在
|
||||||
|
* 2. 节点被禁用
|
||||||
|
*
|
||||||
|
* @param ids 角色编号数组
|
||||||
|
*/
|
||||||
|
void validateXlsxList(Collection<Long> ids);
|
||||||
|
|
||||||
|
List<TreeVO> getXlsxTreeList();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,228 @@
|
|||||||
|
package pc.exam.pp.module.judgement.service.wps_excel;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import pc.exam.pp.framework.common.enums.CommonStatusEnum;
|
||||||
|
import pc.exam.pp.framework.common.util.object.BeanUtils;
|
||||||
|
import pc.exam.pp.framework.datapermission.core.annotation.DataPermission;
|
||||||
|
import pc.exam.pp.framework.tenant.core.aop.TenantIgnore;
|
||||||
|
import pc.exam.pp.module.judgement.controller.admin.Wps.vo.XlsxListReqVO;
|
||||||
|
import pc.exam.pp.module.judgement.controller.admin.Wps.vo.XlsxSaveReqVO;
|
||||||
|
import pc.exam.pp.module.judgement.dal.dataobject.wpspptx.WpsPptxLinkDO;
|
||||||
|
import pc.exam.pp.module.judgement.dal.dataobject.wpsxlsx.WpsXlsxLinkDO;
|
||||||
|
import pc.exam.pp.module.judgement.dal.mysql.wpsxlsx.WpsXlsxLinkMapper;
|
||||||
|
import pc.exam.pp.module.judgement.utils.tree.vo.TreeVO;
|
||||||
|
import pc.exam.pp.module.system.dal.redis.RedisKeyConstants;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import static pc.exam.pp.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
import static pc.exam.pp.framework.common.util.collection.CollectionUtils.convertSet;
|
||||||
|
import static pc.exam.pp.module.system.enums.ErrorCodeConstants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点 Service 实现类
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Validated
|
||||||
|
@Slf4j
|
||||||
|
public class WpsXlsxLinkServiceImpl implements WpsXlsxLinkService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private WpsXlsxLinkMapper wpsXlsxLinkMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@CacheEvict(cacheNames = RedisKeyConstants.WPS_XLSX_CHILDREN_ID_LIST,
|
||||||
|
allEntries = true) // allEntries 清空所有缓存,因为操作一个节点,涉及到多个缓存
|
||||||
|
public Long createXlsx(XlsxSaveReqVO createReqVO) {
|
||||||
|
if (createReqVO.getParentId() == null) {
|
||||||
|
createReqVO.setParentId(WpsPptxLinkDO.PARENT_ID_ROOT);
|
||||||
|
}
|
||||||
|
// 校验父节点的有效性
|
||||||
|
validateParentXlsx(null, createReqVO.getParentId());
|
||||||
|
// 校验节点名的唯一性
|
||||||
|
validateXlsxNameUnique(null, createReqVO.getParentId(), createReqVO.getName());
|
||||||
|
|
||||||
|
// 插入节点
|
||||||
|
WpsXlsxLinkDO wpsXlsxLinkDO = BeanUtils.toBean(createReqVO, WpsXlsxLinkDO.class);
|
||||||
|
wpsXlsxLinkMapper.insert(wpsXlsxLinkDO);
|
||||||
|
return wpsXlsxLinkDO.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@CacheEvict(cacheNames = RedisKeyConstants.WPS_XLSX_CHILDREN_ID_LIST,
|
||||||
|
allEntries = true) // allEntries 清空所有缓存,因为操作一个节点,涉及到多个缓存
|
||||||
|
public void updateXlsx(XlsxSaveReqVO updateReqVO) {
|
||||||
|
if (updateReqVO.getParentId() == null) {
|
||||||
|
updateReqVO.setParentId(WpsPptxLinkDO.PARENT_ID_ROOT);
|
||||||
|
}
|
||||||
|
// 校验自己存在
|
||||||
|
validateXlsxExists(updateReqVO.getId());
|
||||||
|
// 校验父节点的有效性
|
||||||
|
validateParentXlsx(updateReqVO.getId(), updateReqVO.getParentId());
|
||||||
|
// 校验节点名的唯一性
|
||||||
|
validateXlsxNameUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName());
|
||||||
|
|
||||||
|
// 更新节点
|
||||||
|
WpsXlsxLinkDO updateObj = BeanUtils.toBean(updateReqVO, WpsXlsxLinkDO.class);
|
||||||
|
wpsXlsxLinkMapper.updateById(updateObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@CacheEvict(cacheNames = RedisKeyConstants.WPS_XLSX_CHILDREN_ID_LIST,
|
||||||
|
allEntries = true) // allEntries 清空所有缓存,因为操作一个节点,涉及到多个缓存
|
||||||
|
public void deleteXlsx(Long id) {
|
||||||
|
// 校验是否存在
|
||||||
|
validateXlsxExists(id);
|
||||||
|
// 校验是否有子节点
|
||||||
|
if (wpsXlsxLinkMapper.selectCountByParentId(id) > 0) {
|
||||||
|
throw exception(XLSX_NOT_FOUND);
|
||||||
|
}
|
||||||
|
// 删除节点
|
||||||
|
wpsXlsxLinkMapper.deleteById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void validateXlsxExists(Long id) {
|
||||||
|
if (id == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
WpsXlsxLinkDO wpsXlsxLinkDO = wpsXlsxLinkMapper.selectById(id);
|
||||||
|
if (wpsXlsxLinkDO == null) {
|
||||||
|
throw exception(XLSX_NOT_FOUND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void validateParentXlsx(Long id, Long parentId) {
|
||||||
|
if (parentId == null || WpsXlsxLinkDO.PARENT_ID_ROOT.equals(parentId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 1. 不能设置自己为父节点
|
||||||
|
if (Objects.equals(id, parentId)) {
|
||||||
|
throw exception(DEPT_PARENT_ERROR);
|
||||||
|
}
|
||||||
|
// 2. 父节点不存在
|
||||||
|
WpsXlsxLinkDO parentXlsx = wpsXlsxLinkMapper.selectById(parentId);
|
||||||
|
if (parentXlsx == null) {
|
||||||
|
throw exception(XLSX_PARENT_NOT_EXITS);
|
||||||
|
}
|
||||||
|
// 3. 递归校验父节点,如果父节点是自己的子节点,则报错,避免形成环路
|
||||||
|
// id 为空,说明新增,不需要考虑环路
|
||||||
|
if (id == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < Short.MAX_VALUE; i++) {
|
||||||
|
// 3.1 校验环路
|
||||||
|
parentId = parentXlsx.getParentId();
|
||||||
|
if (Objects.equals(id, parentId)) {
|
||||||
|
throw exception(XLSX_PARENT_IS_CHILD);
|
||||||
|
}
|
||||||
|
// 3.2 继续递归下一级父节点
|
||||||
|
if (parentId == null || WpsPptxLinkDO.PARENT_ID_ROOT.equals(parentId)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
parentXlsx = wpsXlsxLinkMapper.selectById(parentId);
|
||||||
|
if (parentXlsx == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void validateXlsxNameUnique(Long id, Long parentId, String name) {
|
||||||
|
WpsXlsxLinkDO wpsXlsxLinkDO = wpsXlsxLinkMapper.selectByParentIdAndName(parentId, name);
|
||||||
|
if (wpsXlsxLinkDO == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 如果 id 为空,说明不用比较是否为相同 id 的节点
|
||||||
|
if (id == null) {
|
||||||
|
throw exception(XLSX_NAME_DUPLICATE);
|
||||||
|
}
|
||||||
|
if (ObjectUtil.notEqual(wpsXlsxLinkDO.getId(), id)) {
|
||||||
|
throw exception(XLSX_NAME_DUPLICATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WpsXlsxLinkDO getXlsx(Long id) {
|
||||||
|
return wpsXlsxLinkMapper.selectById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<WpsXlsxLinkDO> getXlsxList(Collection<Long> ids) {
|
||||||
|
if (CollUtil.isEmpty(ids)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
return wpsXlsxLinkMapper.selectBatchIds(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<WpsXlsxLinkDO> getXlsxList(XlsxListReqVO reqVO) {
|
||||||
|
List<WpsXlsxLinkDO> list = wpsXlsxLinkMapper.selectList(reqVO);
|
||||||
|
list.sort(Comparator.comparing(WpsXlsxLinkDO::getSort));
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<WpsXlsxLinkDO> getChildXlsxList(Collection<Long> ids) {
|
||||||
|
List<WpsXlsxLinkDO> children = new LinkedList<>();
|
||||||
|
// 遍历每一层
|
||||||
|
Collection<Long> parentIds = ids;
|
||||||
|
// 使用 Short.MAX_VALUE 避免 bug 场景下,存在死循环
|
||||||
|
for (int i = 0; i < Short.MAX_VALUE; i++) {
|
||||||
|
// 查询当前层,所有的子节点
|
||||||
|
List<WpsXlsxLinkDO> xlsxs = wpsXlsxLinkMapper.selectListByParentId(parentIds);
|
||||||
|
// 1. 如果没有子节点,则结束遍历
|
||||||
|
if (CollUtil.isEmpty(xlsxs)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// 2. 如果有子节点,继续遍历
|
||||||
|
children.addAll(xlsxs);
|
||||||
|
parentIds = convertSet(xlsxs, WpsXlsxLinkDO::getId);
|
||||||
|
}
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@DataPermission(enable = false) // 禁用数据权限,避免建立不正确的缓存
|
||||||
|
@Cacheable(cacheNames = RedisKeyConstants.WPS_XLSX_CHILDREN_ID_LIST, key = "#id")
|
||||||
|
public Set<Long> getChildXlsxIdListFromCache(Long id) {
|
||||||
|
List<WpsXlsxLinkDO> children = getChildXlsxList(id);
|
||||||
|
return convertSet(children, WpsXlsxLinkDO::getId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void validateXlsxList(Collection<Long> ids) {
|
||||||
|
if (CollUtil.isEmpty(ids)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 获得科室信息
|
||||||
|
Map<Long, WpsXlsxLinkDO> xlsxMap = getXlsxMap(ids);
|
||||||
|
// 校验
|
||||||
|
ids.forEach(id -> {
|
||||||
|
WpsXlsxLinkDO xlsx = xlsxMap.get(id);
|
||||||
|
if (xlsx == null) {
|
||||||
|
throw exception(XLSX_NOT_FOUND);
|
||||||
|
}
|
||||||
|
if (!CommonStatusEnum.ENABLE.getStatus().equals(xlsx.getStatus())) {
|
||||||
|
throw exception(XLSX_NOT_ENABLE, xlsx.getName());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@TenantIgnore
|
||||||
|
public List<TreeVO> getXlsxTreeList() {
|
||||||
|
return wpsXlsxLinkMapper.selectTreeListByNodeFunction();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package pc.exam.pp.module.judgement.service.wps_pptx;
|
||||||
|
|
||||||
|
import pc.exam.pp.module.judgement.utils.wps_pptx.vo.PptxVO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author REN
|
||||||
|
*/
|
||||||
|
public interface JudgementWpsPptxService {
|
||||||
|
|
||||||
|
List<PptxVO> programmingWpsPptx(String path) throws Exception;
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package pc.exam.pp.module.judgement.service.wps_pptx;
|
||||||
|
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import pc.exam.pp.module.infra.dal.dataobject.config.ConfigDO;
|
||||||
|
import pc.exam.pp.module.infra.service.config.ConfigService;
|
||||||
|
import pc.exam.pp.module.judgement.controller.admin.Wps.vo.PptxListReqVO;
|
||||||
|
import pc.exam.pp.module.judgement.dal.dataobject.wpspptx.WpsPptxLinkDO;
|
||||||
|
import pc.exam.pp.module.judgement.dal.mysql.wpspptx.WpsPptxLinkMapper;
|
||||||
|
import pc.exam.pp.module.judgement.service.auto_tools.AutoToolsService;
|
||||||
|
import pc.exam.pp.module.judgement.utils.wps_pptx.WpsPptxUtils;
|
||||||
|
import pc.exam.pp.module.judgement.utils.wps_pptx.vo.PptxVO;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author REN
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class JudgementWpsPptxServiceImpl implements JudgementWpsPptxService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
AutoToolsService autoToolsService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
ConfigService configService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
WpsPptxLinkMapper wpsPptxLinkMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PptxVO> programmingWpsPptx(String path) throws Exception {
|
||||||
|
|
||||||
|
// 1、获取文件临时下载路径
|
||||||
|
ConfigDO config = configService.getConfigByKey("file_down_path");
|
||||||
|
// 2、下载文件并返回文件完整路径
|
||||||
|
String pathName = autoToolsService.downloadStudentFile(path, config.getValue());
|
||||||
|
// 3、创建pptx考点tree
|
||||||
|
PptxListReqVO pptxListReqVO = new PptxListReqVO();
|
||||||
|
pptxListReqVO.setBelongTo(0);
|
||||||
|
// 3-1、查询段落的标签
|
||||||
|
List<WpsPptxLinkDO> paragraphList = wpsPptxLinkMapper.selectList(pptxListReqVO);
|
||||||
|
// 4、docx文件读取并返回考点及说明信息
|
||||||
|
List<PptxVO> margins1 = WpsPptxUtils.wpsPptx(pathName, paragraphList);
|
||||||
|
// 5、已经读取完得考点删除源文件
|
||||||
|
File file = new File(pathName);
|
||||||
|
file.delete();
|
||||||
|
return margins1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
package pc.exam.pp.module.judgement.service.wps_pptx;
|
||||||
|
|
||||||
|
import pc.exam.pp.framework.common.util.collection.CollectionUtils;
|
||||||
|
import pc.exam.pp.module.judgement.controller.admin.Wps.vo.PptxListReqVO;
|
||||||
|
import pc.exam.pp.module.judgement.controller.admin.Wps.vo.PptxSaveReqVO;
|
||||||
|
import pc.exam.pp.module.judgement.dal.dataobject.wpspptx.WpsPptxLinkDO;
|
||||||
|
import pc.exam.pp.module.judgement.utils.tree.vo.TreeVO;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点 Service 接口
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public interface WpsPptxLinkService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建节点
|
||||||
|
*
|
||||||
|
* @param createReqVO 节点信息
|
||||||
|
* @return 节点编号
|
||||||
|
*/
|
||||||
|
Long createPptx(PptxSaveReqVO createReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新节点
|
||||||
|
*
|
||||||
|
* @param updateReqVO 节点信息
|
||||||
|
*/
|
||||||
|
void updatePptx(PptxSaveReqVO updateReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除节点
|
||||||
|
*
|
||||||
|
* @param id 节点编号
|
||||||
|
*/
|
||||||
|
void deletePptx(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得节点信息
|
||||||
|
*
|
||||||
|
* @param id 节点编号
|
||||||
|
* @return 节点信息
|
||||||
|
*/
|
||||||
|
WpsPptxLinkDO getPptx(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得节点信息数组
|
||||||
|
*
|
||||||
|
* @param ids 节点编号数组
|
||||||
|
* @return 节点信息数组
|
||||||
|
*/
|
||||||
|
List<WpsPptxLinkDO> getPptxList(Collection<Long> ids);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 筛选节点列表
|
||||||
|
*
|
||||||
|
* @param reqVO 筛选条件请求 VO
|
||||||
|
* @return 节点列表
|
||||||
|
*/
|
||||||
|
List<WpsPptxLinkDO> getPptxList(PptxListReqVO reqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得指定编号的节点 Map
|
||||||
|
*
|
||||||
|
* @param ids 节点编号数组
|
||||||
|
* @return 节点 Map
|
||||||
|
*/
|
||||||
|
default Map<Long, WpsPptxLinkDO> getPptxMap(Collection<Long> ids) {
|
||||||
|
List<WpsPptxLinkDO> list = getPptxList(ids);
|
||||||
|
return CollectionUtils.convertMap(list, WpsPptxLinkDO::getId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得指定节点的所有子节点
|
||||||
|
*
|
||||||
|
* @param id 节点编号
|
||||||
|
* @return 子节点列表
|
||||||
|
*/
|
||||||
|
default List<WpsPptxLinkDO> getChildPptxList(Long id) {
|
||||||
|
return getChildPptxList(Collections.singleton(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得指定节点的所有子节点
|
||||||
|
*
|
||||||
|
* @param ids 节点编号数组
|
||||||
|
* @return 子节点列表
|
||||||
|
*/
|
||||||
|
List<WpsPptxLinkDO> getChildPptxList(Collection<Long> ids);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得所有子节点,从缓存中
|
||||||
|
*
|
||||||
|
* @param id 父节点编号
|
||||||
|
* @return 子节点列表
|
||||||
|
*/
|
||||||
|
Set<Long> getChildPptxIdListFromCache(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验节点们是否有效。如下情况,视为无效:
|
||||||
|
* 1. 节点编号不存在
|
||||||
|
* 2. 节点被禁用
|
||||||
|
*
|
||||||
|
* @param ids 角色编号数组
|
||||||
|
*/
|
||||||
|
void validatePptxList(Collection<Long> ids);
|
||||||
|
|
||||||
|
List<TreeVO> getPptxTreeList();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,227 @@
|
|||||||
|
package pc.exam.pp.module.judgement.service.wps_pptx;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import pc.exam.pp.framework.common.enums.CommonStatusEnum;
|
||||||
|
import pc.exam.pp.framework.common.util.object.BeanUtils;
|
||||||
|
import pc.exam.pp.framework.datapermission.core.annotation.DataPermission;
|
||||||
|
import pc.exam.pp.framework.tenant.core.aop.TenantIgnore;
|
||||||
|
import pc.exam.pp.module.judgement.controller.admin.Wps.vo.PptxListReqVO;
|
||||||
|
import pc.exam.pp.module.judgement.controller.admin.Wps.vo.PptxSaveReqVO;
|
||||||
|
import pc.exam.pp.module.judgement.dal.dataobject.wpspptx.WpsPptxLinkDO;
|
||||||
|
import pc.exam.pp.module.judgement.dal.mysql.wpspptx.WpsPptxLinkMapper;
|
||||||
|
import pc.exam.pp.module.judgement.utils.tree.vo.TreeVO;
|
||||||
|
import pc.exam.pp.module.system.dal.redis.RedisKeyConstants;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import static pc.exam.pp.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
import static pc.exam.pp.framework.common.util.collection.CollectionUtils.convertSet;
|
||||||
|
import static pc.exam.pp.module.system.enums.ErrorCodeConstants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点 Service 实现类
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Validated
|
||||||
|
@Slf4j
|
||||||
|
public class WpsPptxLinkServiceImpl implements WpsPptxLinkService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private WpsPptxLinkMapper wpsPptxLinkMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@CacheEvict(cacheNames = RedisKeyConstants.WPS_PPTX_CHILDREN_ID_LIST,
|
||||||
|
allEntries = true) // allEntries 清空所有缓存,因为操作一个节点,涉及到多个缓存
|
||||||
|
public Long createPptx(PptxSaveReqVO createReqVO) {
|
||||||
|
if (createReqVO.getParentId() == null) {
|
||||||
|
createReqVO.setParentId(WpsPptxLinkDO.PARENT_ID_ROOT);
|
||||||
|
}
|
||||||
|
// 校验父节点的有效性
|
||||||
|
validateParentPptx(null, createReqVO.getParentId());
|
||||||
|
// 校验节点名的唯一性
|
||||||
|
validatePptxNameUnique(null, createReqVO.getParentId(), createReqVO.getName());
|
||||||
|
|
||||||
|
// 插入节点
|
||||||
|
WpsPptxLinkDO wpsPptxLinkDO = BeanUtils.toBean(createReqVO, WpsPptxLinkDO.class);
|
||||||
|
wpsPptxLinkMapper.insert(wpsPptxLinkDO);
|
||||||
|
return wpsPptxLinkDO.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@CacheEvict(cacheNames = RedisKeyConstants.WPS_PPTX_CHILDREN_ID_LIST,
|
||||||
|
allEntries = true) // allEntries 清空所有缓存,因为操作一个节点,涉及到多个缓存
|
||||||
|
public void updatePptx(PptxSaveReqVO updateReqVO) {
|
||||||
|
if (updateReqVO.getParentId() == null) {
|
||||||
|
updateReqVO.setParentId(WpsPptxLinkDO.PARENT_ID_ROOT);
|
||||||
|
}
|
||||||
|
// 校验自己存在
|
||||||
|
validatePptxExists(updateReqVO.getId());
|
||||||
|
// 校验父节点的有效性
|
||||||
|
validateParentPptx(updateReqVO.getId(), updateReqVO.getParentId());
|
||||||
|
// 校验节点名的唯一性
|
||||||
|
validatePptxNameUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName());
|
||||||
|
|
||||||
|
// 更新节点
|
||||||
|
WpsPptxLinkDO updateObj = BeanUtils.toBean(updateReqVO, WpsPptxLinkDO.class);
|
||||||
|
wpsPptxLinkMapper.updateById(updateObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@CacheEvict(cacheNames = RedisKeyConstants.WPS_PPTX_CHILDREN_ID_LIST,
|
||||||
|
allEntries = true) // allEntries 清空所有缓存,因为操作一个节点,涉及到多个缓存
|
||||||
|
public void deletePptx(Long id) {
|
||||||
|
// 校验是否存在
|
||||||
|
validatePptxExists(id);
|
||||||
|
// 校验是否有子节点
|
||||||
|
if (wpsPptxLinkMapper.selectCountByParentId(id) > 0) {
|
||||||
|
throw exception(WORD_NOT_FOUND);
|
||||||
|
}
|
||||||
|
// 删除节点
|
||||||
|
wpsPptxLinkMapper.deleteById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void validatePptxExists(Long id) {
|
||||||
|
if (id == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
WpsPptxLinkDO wpsPptxLinkDO = wpsPptxLinkMapper.selectById(id);
|
||||||
|
if (wpsPptxLinkDO == null) {
|
||||||
|
throw exception(PPTX_NOT_FOUND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void validateParentPptx(Long id, Long parentId) {
|
||||||
|
if (parentId == null || WpsPptxLinkDO.PARENT_ID_ROOT.equals(parentId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 1. 不能设置自己为父节点
|
||||||
|
if (Objects.equals(id, parentId)) {
|
||||||
|
throw exception(PPTX_PARENT_ERROR);
|
||||||
|
}
|
||||||
|
// 2. 父节点不存在
|
||||||
|
WpsPptxLinkDO parentPptx = wpsPptxLinkMapper.selectById(parentId);
|
||||||
|
if (parentPptx == null) {
|
||||||
|
throw exception(PPTX_PARENT_NOT_EXITS);
|
||||||
|
}
|
||||||
|
// 3. 递归校验父节点,如果父节点是自己的子节点,则报错,避免形成环路
|
||||||
|
// id 为空,说明新增,不需要考虑环路
|
||||||
|
if (id == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < Short.MAX_VALUE; i++) {
|
||||||
|
// 3.1 校验环路
|
||||||
|
parentId = parentPptx.getParentId();
|
||||||
|
if (Objects.equals(id, parentId)) {
|
||||||
|
throw exception(PPTX_PARENT_IS_CHILD);
|
||||||
|
}
|
||||||
|
// 3.2 继续递归下一级父节点
|
||||||
|
if (parentId == null || WpsPptxLinkDO.PARENT_ID_ROOT.equals(parentId)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
parentPptx = wpsPptxLinkMapper.selectById(parentId);
|
||||||
|
if (parentPptx == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void validatePptxNameUnique(Long id, Long parentId, String name) {
|
||||||
|
WpsPptxLinkDO wpsPptxLinkDO = wpsPptxLinkMapper.selectByParentIdAndName(parentId, name);
|
||||||
|
if (wpsPptxLinkDO == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 如果 id 为空,说明不用比较是否为相同 id 的节点
|
||||||
|
if (id == null) {
|
||||||
|
throw exception(PPTX_NAME_DUPLICATE);
|
||||||
|
}
|
||||||
|
if (ObjectUtil.notEqual(wpsPptxLinkDO.getId(), id)) {
|
||||||
|
throw exception(PPTX_NAME_DUPLICATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WpsPptxLinkDO getPptx(Long id) {
|
||||||
|
return wpsPptxLinkMapper.selectById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<WpsPptxLinkDO> getPptxList(Collection<Long> ids) {
|
||||||
|
if (CollUtil.isEmpty(ids)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
return wpsPptxLinkMapper.selectBatchIds(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<WpsPptxLinkDO> getPptxList(PptxListReqVO reqVO) {
|
||||||
|
List<WpsPptxLinkDO> list = wpsPptxLinkMapper.selectList(reqVO);
|
||||||
|
list.sort(Comparator.comparing(WpsPptxLinkDO::getSort));
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<WpsPptxLinkDO> getChildPptxList(Collection<Long> ids) {
|
||||||
|
List<WpsPptxLinkDO> children = new LinkedList<>();
|
||||||
|
// 遍历每一层
|
||||||
|
Collection<Long> parentIds = ids;
|
||||||
|
// 使用 Short.MAX_VALUE 避免 bug 场景下,存在死循环
|
||||||
|
for (int i = 0; i < Short.MAX_VALUE; i++) {
|
||||||
|
// 查询当前层,所有的子节点
|
||||||
|
List<WpsPptxLinkDO> pptxs = wpsPptxLinkMapper.selectListByParentId(parentIds);
|
||||||
|
// 1. 如果没有子节点,则结束遍历
|
||||||
|
if (CollUtil.isEmpty(pptxs)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// 2. 如果有子节点,继续遍历
|
||||||
|
children.addAll(pptxs);
|
||||||
|
parentIds = convertSet(pptxs, WpsPptxLinkDO::getId);
|
||||||
|
}
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@DataPermission(enable = false) // 禁用数据权限,避免建立不正确的缓存
|
||||||
|
@Cacheable(cacheNames = RedisKeyConstants.WPS_PPTX_CHILDREN_ID_LIST, key = "#id")
|
||||||
|
public Set<Long> getChildPptxIdListFromCache(Long id) {
|
||||||
|
List<WpsPptxLinkDO> children = getChildPptxList(id);
|
||||||
|
return convertSet(children, WpsPptxLinkDO::getId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void validatePptxList(Collection<Long> ids) {
|
||||||
|
if (CollUtil.isEmpty(ids)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 获得科室信息
|
||||||
|
Map<Long, WpsPptxLinkDO> PptxMap = getPptxMap(ids);
|
||||||
|
// 校验
|
||||||
|
ids.forEach(id -> {
|
||||||
|
WpsPptxLinkDO Pptx = PptxMap.get(id);
|
||||||
|
if (Pptx == null) {
|
||||||
|
throw exception(PPTX_NOT_FOUND);
|
||||||
|
}
|
||||||
|
if (!CommonStatusEnum.ENABLE.getStatus().equals(Pptx.getStatus())) {
|
||||||
|
throw exception(PPTX_NOT_ENABLE, Pptx.getName());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@TenantIgnore
|
||||||
|
public List<TreeVO> getPptxTreeList() {
|
||||||
|
return wpsPptxLinkMapper.selectTreeListByNodeFunction();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -21,7 +21,9 @@ public interface JudgementWpsWordService {
|
|||||||
* @return 文件内得考点及描述
|
* @return 文件内得考点及描述
|
||||||
* @throws Exception 异常
|
* @throws Exception 异常
|
||||||
*/
|
*/
|
||||||
public List<WordVO> ProgrammingWpsWord(String path) throws Exception;
|
List<WordVO> programmingWpsWord(String path) throws Exception;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 读取考生文件,与题型中要求进行判断
|
* 读取考生文件,与题型中要求进行判断
|
||||||
@@ -31,5 +33,5 @@ public interface JudgementWpsWordService {
|
|||||||
* @return 得分
|
* @return 得分
|
||||||
* @throws Exception 异常
|
* @throws Exception 异常
|
||||||
*/
|
*/
|
||||||
public double judgementWpsWord(double sorce, String pathC, String path, ExamQuestion examQuestion) throws Exception;
|
double judgementWpsWord(double sorce, String pathC, String path, ExamQuestion examQuestion) throws Exception;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public class JudgementWpsWordServiceImpl implements JudgementWpsWordService {
|
|||||||
ConfigService configService;
|
ConfigService configService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<WordVO> ProgrammingWpsWord(String path) throws Exception {
|
public List<WordVO> programmingWpsWord(String path) throws Exception {
|
||||||
|
|
||||||
// 1、获取文件临时下载路径
|
// 1、获取文件临时下载路径
|
||||||
ConfigDO config = configService.getConfigByKey("file_down_path");
|
ConfigDO config = configService.getConfigByKey("file_down_path");
|
||||||
@@ -99,5 +99,4 @@ public class JudgementWpsWordServiceImpl implements JudgementWpsWordService {
|
|||||||
return wps_word_sorce;
|
return wps_word_sorce;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ public class WpsWordLinkServiceImpl implements WpsWordLinkService {
|
|||||||
}
|
}
|
||||||
// 1. 不能设置自己为父节点
|
// 1. 不能设置自己为父节点
|
||||||
if (Objects.equals(id, parentId)) {
|
if (Objects.equals(id, parentId)) {
|
||||||
throw exception(DEPT_PARENT_ERROR);
|
throw exception(WORD_PARENT_ERROR);
|
||||||
}
|
}
|
||||||
// 2. 父节点不存在
|
// 2. 父节点不存在
|
||||||
WpsWordLinkDO parentWord = wpsWordLinkMapper.selectById(parentId);
|
WpsWordLinkDO parentWord = wpsWordLinkMapper.selectById(parentId);
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package pc.exam.pp.module.judgement.utils.tree;
|
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.wpsword.WpsWordLinkDO;
|
import pc.exam.pp.module.judgement.dal.dataobject.wpsword.WpsWordLinkDO;
|
||||||
|
import pc.exam.pp.module.judgement.dal.dataobject.wpsxlsx.WpsXlsxLinkDO;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -32,4 +34,49 @@ public class TreeUtils {
|
|||||||
return roots;
|
return roots;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<WpsPptxLinkDO> buildTreePptx(List<WpsPptxLinkDO> flatList) {
|
||||||
|
Map<Integer, WpsPptxLinkDO> nodeMap = new HashMap<>();
|
||||||
|
List<WpsPptxLinkDO> roots = new ArrayList<>();
|
||||||
|
|
||||||
|
// 先放入 map
|
||||||
|
for (WpsPptxLinkDO node : flatList) {
|
||||||
|
nodeMap.put(Math.toIntExact(node.getId()), node);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建树关系
|
||||||
|
for (WpsPptxLinkDO node : flatList) {
|
||||||
|
if (node.getParentId() == 0) {
|
||||||
|
roots.add(node);
|
||||||
|
} else {
|
||||||
|
WpsPptxLinkDO parent = nodeMap.get(node.getParentId().intValue());
|
||||||
|
if (parent != null) {
|
||||||
|
parent.getChildren().add(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return roots;
|
||||||
|
}
|
||||||
|
public static List<WpsXlsxLinkDO> buildTreeXlsx(List<WpsXlsxLinkDO> flatList) {
|
||||||
|
Map<Integer, WpsXlsxLinkDO> nodeMap = new HashMap<>();
|
||||||
|
List<WpsXlsxLinkDO> roots = new ArrayList<>();
|
||||||
|
|
||||||
|
// 先放入 map
|
||||||
|
for (WpsXlsxLinkDO node : flatList) {
|
||||||
|
nodeMap.put(Math.toIntExact(node.getId()), node);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建树关系
|
||||||
|
for (WpsXlsxLinkDO node : flatList) {
|
||||||
|
if (node.getParentId() == 0) {
|
||||||
|
roots.add(node);
|
||||||
|
} else {
|
||||||
|
WpsXlsxLinkDO parent = nodeMap.get(node.getParentId().intValue());
|
||||||
|
if (parent != null) {
|
||||||
|
parent.getChildren().add(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return roots;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,44 +1,57 @@
|
|||||||
package pc.exam.pp.module.judgement.utils.wps_excel;
|
package pc.exam.pp.module.judgement.utils.wps_excel;
|
||||||
|
|
||||||
|
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
||||||
|
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||||
import org.apache.poi.ss.usermodel.Cell;
|
import org.apache.poi.ss.usermodel.Cell;
|
||||||
import org.apache.poi.ss.usermodel.Row;
|
import org.apache.poi.ss.usermodel.Row;
|
||||||
import org.apache.poi.ss.usermodel.Sheet;
|
import org.apache.poi.ss.usermodel.Sheet;
|
||||||
|
import org.apache.poi.xssf.usermodel.XSSFSheet;
|
||||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||||
|
import org.apache.xmlbeans.XmlCursor;
|
||||||
|
import org.apache.xmlbeans.XmlObject;
|
||||||
|
import pc.exam.pp.module.judgement.dal.dataobject.wpspptx.WpsPptxLinkDO;
|
||||||
|
import pc.exam.pp.module.judgement.dal.dataobject.wpsxlsx.WpsXlsxLinkDO;
|
||||||
|
import pc.exam.pp.module.judgement.utils.tree.TreeUtils;
|
||||||
|
import pc.exam.pp.module.judgement.utils.wps_excel.vo.XlsxVO;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author REN
|
||||||
|
*/
|
||||||
public class WpsExcelUtils {
|
public class WpsExcelUtils {
|
||||||
public static String wps_excel(String filePath) throws FileNotFoundException {
|
public static List<XlsxVO> wpsExcel(String filePath, List<WpsXlsxLinkDO> xlsxList) {
|
||||||
|
// 创建结果对象
|
||||||
|
List<XlsxVO> xlsxVos = new ArrayList<>();
|
||||||
|
// 转换数据
|
||||||
|
List<WpsXlsxLinkDO> xlsxTree = TreeUtils.buildTreeXlsx(xlsxList);
|
||||||
try (FileInputStream fis = new FileInputStream(filePath);
|
try (FileInputStream fis = new FileInputStream(filePath);
|
||||||
XSSFWorkbook workbook = new XSSFWorkbook(fis)) {
|
OPCPackage pkg = OPCPackage.open(fis);
|
||||||
|
XSSFWorkbook workbook = new XSSFWorkbook(pkg)) {
|
||||||
Sheet sheet = workbook.getSheetAt(0); // 读取第一个工作表
|
// 获取有多少个工作表
|
||||||
|
int sheetNumber = workbook.getNumberOfSheets();
|
||||||
for (Row row : sheet) {
|
for (int i = 0; i < sheetNumber; i++) {
|
||||||
for (Cell cell : row) {
|
System.out.println("第 " + (i + 1) + " 个工作表");
|
||||||
switch (cell.getCellType()) {
|
// 获取工作表内容
|
||||||
case STRING:
|
XSSFSheet sheetXss = workbook.getSheetAt(i);
|
||||||
System.out.print(cell.getStringCellValue() + "\t");
|
// 获取工作表的XML对象
|
||||||
break;
|
XmlObject worksheetXml = sheetXss.getCTWorksheet();
|
||||||
case NUMERIC:
|
try (XmlCursor cursor = worksheetXml.newCursor()) {
|
||||||
System.out.print(cell.getNumericCellValue() + "\t");
|
System.out.println(cursor.xmlText());
|
||||||
break;
|
} catch (Exception e) {
|
||||||
case BOOLEAN:
|
|
||||||
System.out.print(cell.getBooleanCellValue() + "\t");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
System.out.print("?\t");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return filePath;
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvalidFormatException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return xlsxVos;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package pc.exam.pp.module.judgement.utils.wps_excel.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class XlsxVO {
|
||||||
|
|
||||||
|
@Schema(description = "相关文本")
|
||||||
|
private String wordText;
|
||||||
|
|
||||||
|
@Schema(description = "考试考点")
|
||||||
|
private List<String> examKeynote;
|
||||||
|
|
||||||
|
@Schema(description = "考点汉化")
|
||||||
|
private List<String> keynoteChinese;
|
||||||
|
|
||||||
|
@Schema(description = "是否有样式修饰")
|
||||||
|
private Boolean isTrue;
|
||||||
|
|
||||||
|
@Schema(description = "类型")
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,182 @@
|
|||||||
|
package pc.exam.pp.module.judgement.utils.wps_pptx;
|
||||||
|
|
||||||
|
import org.apache.poi.xslf.usermodel.XMLSlideShow;
|
||||||
|
import org.apache.poi.xslf.usermodel.XSLFSlide;
|
||||||
|
import org.apache.xmlbeans.XmlCursor;
|
||||||
|
import org.apache.xmlbeans.XmlObject;
|
||||||
|
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.utils.tree.TreeUtils;
|
||||||
|
import pc.exam.pp.module.judgement.utils.wps_pptx.vo.PptxVO;
|
||||||
|
import pc.exam.pp.module.judgement.utils.wps_word.vo.WordVO;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author REN
|
||||||
|
*/
|
||||||
|
public class WpsPptxUtils {
|
||||||
|
public static List<PptxVO> wpsPptx(String filePath, List<WpsPptxLinkDO> cSldList) {
|
||||||
|
List<PptxVO> pptxVOS = new ArrayList<>();
|
||||||
|
// 转换数据
|
||||||
|
List<WpsPptxLinkDO> cSldTree = TreeUtils.buildTreePptx(cSldList);
|
||||||
|
// 1、读取文件内容
|
||||||
|
try (FileInputStream fis = new FileInputStream(filePath);
|
||||||
|
XMLSlideShow pptxXml = new XMLSlideShow(fis)) {
|
||||||
|
// 索引
|
||||||
|
int index = 0;
|
||||||
|
// 获取了所有的幻灯片
|
||||||
|
for (XSLFSlide slides : pptxXml.getSlides()){
|
||||||
|
String xmlText = slides.getXmlObject().xmlText();
|
||||||
|
// 1-1、创建最全的命名空间
|
||||||
|
Pattern pattern = Pattern.compile("xmlns:(\\w+)=\"([^\"]+)\"");
|
||||||
|
Matcher matcher = pattern.matcher(xmlText);
|
||||||
|
Map<String, String> namespaces = new HashMap<>();
|
||||||
|
while (matcher.find()) {
|
||||||
|
String prefix = matcher.group(1);
|
||||||
|
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();
|
||||||
|
// 3、获取CTDocument对象
|
||||||
|
XmlObject docXml = slides.getXmlObject();
|
||||||
|
for (WpsPptxLinkDO node : cSldTree) {
|
||||||
|
traverseTreeAndQueryXml("111", pptxVOS, node.getName(), "123", allPathx, node, docXml, new ArrayList<>(), new ArrayList<>(), index, 1);
|
||||||
|
}
|
||||||
|
index += 1;
|
||||||
|
// 2、解析文件内容
|
||||||
|
XmlObject xml = slides.getXmlObject();
|
||||||
|
System.out.println(index + "解析pptx文件内容: " + xml.xmlText());
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return pptxVOS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param type String 用来存放类型
|
||||||
|
* @param pptxVOS List<PptxVO> 用来存放结果
|
||||||
|
* @param firstTitle String 用来存放一级标题
|
||||||
|
* @param text String 用来存放文本
|
||||||
|
* @param xpath String 用来存放xpath
|
||||||
|
* @param node WpsWordLinkDO 用来存放节点
|
||||||
|
* @param currentXml XmlObject 用来存放当前xml
|
||||||
|
* @param pathSoFar List<String> 用来存放路径
|
||||||
|
* @param pathChinese List<String> 用来存放中文路径
|
||||||
|
* @param index int 用来存放索引
|
||||||
|
* @param beginIndex int 用来存放开始索引
|
||||||
|
*/
|
||||||
|
public static void traverseTreeAndQueryXml(String type, List<PptxVO> pptxVOS, String firstTitle, String text, String xpath, WpsPptxLinkDO node, XmlObject currentXml, List<String> pathSoFar, List<String> pathChinese, int index, int beginIndex) {
|
||||||
|
// 到达参数节点,构造 XPath 路径查询它的值
|
||||||
|
if (beginIndex == 1) {
|
||||||
|
xpath += "./";
|
||||||
|
}
|
||||||
|
pathSoFar.add(node.getName());
|
||||||
|
pathChinese.add(node.getToChinese() + index);
|
||||||
|
|
||||||
|
if (node.getType() == 1) {
|
||||||
|
xpath += String.join("/", pathSoFar);
|
||||||
|
try (XmlCursor cursors = currentXml.newCursor()) {
|
||||||
|
cursors.selectPath(xpath);
|
||||||
|
if (cursors.toNextSelection()) {
|
||||||
|
String textValue = cursors.getTextValue();
|
||||||
|
if (!Objects.equals(textValue, "")) {
|
||||||
|
// 查找List里面是否已经存在相应文本的数据
|
||||||
|
String finalText = text;
|
||||||
|
int listIndex = IntStream.range(0, pptxVOS.size())
|
||||||
|
.filter(i -> finalText.equals(pptxVOS.get(i).getWordText()))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(-1);
|
||||||
|
// 判断在段落内的样式,如果出现样式,向上兼容,直接再出现样式标签
|
||||||
|
// System.out.println(xpath);
|
||||||
|
if (xpath.indexOf("w:sectPr") > 0 && xpath.indexOf("w:p[") > 0) {
|
||||||
|
// 说明出现了文本页面设置,需要进行向上绑定
|
||||||
|
// 在获取当前的数组长度,获取上面的属性 遍历已经存在的数据
|
||||||
|
int tindex = 0;
|
||||||
|
for (PptxVO woVo : pptxVOS) {
|
||||||
|
// 判断标识是否为false,,代表没有进行赋值
|
||||||
|
if (!woVo.getIsTrue()) {
|
||||||
|
PptxVO pptxVO = pptxVOS.get(tindex);
|
||||||
|
pptxVO.setWordText(pptxVO.getWordText());
|
||||||
|
woVo.setIsTrue(true);
|
||||||
|
List<String> kchinese = woVo.getKeynoteChinese();
|
||||||
|
List<String> examKeynote = woVo.getExamKeynote();
|
||||||
|
examKeynote.add(String.join(" → ", pathSoFar) + ",value:" + textValue);
|
||||||
|
kchinese.add(String.join(" → ", pathChinese) + ",值:" + textValue);
|
||||||
|
pptxVO.setKeynoteChinese(kchinese);
|
||||||
|
pptxVO.setExamKeynote(examKeynote);
|
||||||
|
pptxVO.setType(type);
|
||||||
|
pptxVOS.set(tindex, woVo);
|
||||||
|
}
|
||||||
|
tindex += 1;
|
||||||
|
}
|
||||||
|
} else if (listIndex < 0) {
|
||||||
|
// 如果没有查询到了
|
||||||
|
if (xpath.indexOf("w:sectPr[") > 0) {
|
||||||
|
// 页面属性
|
||||||
|
// 文本
|
||||||
|
text = "页面属性";
|
||||||
|
}
|
||||||
|
if (!Objects.equals(text, "")) {
|
||||||
|
if (!text.contains("MERGEFIELD")) {
|
||||||
|
// 给标志符
|
||||||
|
PptxVO pptxVO = new PptxVO();
|
||||||
|
pptxVO.setWordText(text);
|
||||||
|
// 创建list进行存放数据
|
||||||
|
List<String> kchinese = new ArrayList<>();
|
||||||
|
List<String> examKeynote = new ArrayList<>();
|
||||||
|
examKeynote.add(String.join(" → ", pathSoFar) + ",value:" + textValue);
|
||||||
|
kchinese.add(String.join(" → ", pathChinese) + ",值:" + textValue);
|
||||||
|
// 组合完数据后进行存放数据
|
||||||
|
pptxVO.setKeynoteChinese(kchinese);
|
||||||
|
pptxVO.setExamKeynote(examKeynote);
|
||||||
|
pptxVO.setIsTrue(false);
|
||||||
|
pptxVO.setType(type);
|
||||||
|
pptxVOS.add(pptxVO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // 如果找到了
|
||||||
|
PptxVO pptxVO = pptxVOS.get(listIndex);
|
||||||
|
List<String> kchinese = pptxVO.getKeynoteChinese();
|
||||||
|
List<String> examKeynote = pptxVO.getExamKeynote();
|
||||||
|
examKeynote.add(String.join(" → ", pathSoFar) + ",value:" + textValue);
|
||||||
|
kchinese.add(String.join(" → ", pathChinese) + ",值:" + textValue);
|
||||||
|
pptxVO.setKeynoteChinese(kchinese);
|
||||||
|
pptxVO.setExamKeynote(examKeynote);
|
||||||
|
pptxVO.setIsTrue(false);
|
||||||
|
pptxVO.setType(type);
|
||||||
|
pptxVOS.remove(listIndex);
|
||||||
|
pptxVOS.add(pptxVO);
|
||||||
|
}
|
||||||
|
// System.out.println("文本:" + text + " 参数路径:" + String.join(" → ", pathChinese) + ",值:" + text_value);
|
||||||
|
}
|
||||||
|
cursors.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (WpsPptxLinkDO child : node.getChildren()) {
|
||||||
|
traverseTreeAndQueryXml(type, pptxVOS, firstTitle, text, xpath, child, currentXml, new ArrayList<>(pathSoFar), new ArrayList<>(pathChinese), index,2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pathSoFar.remove(pathSoFar.size() - 1);
|
||||||
|
pathChinese.remove(pathChinese.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package pc.exam.pp.module.judgement.utils.wps_pptx.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class PptxVO {
|
||||||
|
|
||||||
|
@Schema(description = "相关文本")
|
||||||
|
private String wordText;
|
||||||
|
|
||||||
|
@Schema(description = "考试考点")
|
||||||
|
private List<String> examKeynote;
|
||||||
|
|
||||||
|
@Schema(description = "考点汉化")
|
||||||
|
private List<String> keynoteChinese;
|
||||||
|
|
||||||
|
@Schema(description = "是否有样式修饰")
|
||||||
|
private Boolean isTrue;
|
||||||
|
|
||||||
|
@Schema(description = "类型")
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -17,6 +17,11 @@ import java.util.stream.IntStream;
|
|||||||
public class WpsWordUtils {
|
public class WpsWordUtils {
|
||||||
/**
|
/**
|
||||||
* 获取文档段落W:P标签得数量,判断出一个有多少段
|
* 获取文档段落W:P标签得数量,判断出一个有多少段
|
||||||
|
* @param filePath 文件路径
|
||||||
|
* @param paragraphList 段落列表
|
||||||
|
* @param anchorList 锚点列表
|
||||||
|
* @return List<WordVO>
|
||||||
|
* @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, List<WpsWordLinkDO> paragraphList, List<WpsWordLinkDO> anchorList) throws Exception {
|
||||||
List<WordVO> wordVO = new ArrayList<>();
|
List<WordVO> wordVO = new ArrayList<>();
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="pc.exam.pp.module.judgement.dal.mysql.wpspptx.WpsPptxLinkMapper">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
|
||||||
|
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
|
||||||
|
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
|
||||||
|
文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
|
||||||
|
-->
|
||||||
|
<resultMap id="NodeResultMap" type="pc.exam.pp.module.judgement.utils.tree.vo.TreeVO">
|
||||||
|
<id property="id" column="id" jdbcType="BIGINT"/>
|
||||||
|
<result property="name" column="name" jdbcType="VARCHAR"/>
|
||||||
|
<result property="parentId" column="parent_id" jdbcType="BIGINT"/>
|
||||||
|
<result property="nodeFunction" column="node_function" jdbcType="VARCHAR"/>
|
||||||
|
<result property="toChinese" column="to_chinese" jdbcType="VARCHAR"/>
|
||||||
|
<result property="type" column="type" jdbcType="TINYINT"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
|
||||||
|
<select id="selectTreeListByNodeFunction" resultMap="NodeResultMap">
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
wps_pptx_link
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="pc.exam.pp.module.judgement.dal.mysql.wpsword.WpsWordLinkMapper">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
|
||||||
|
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
|
||||||
|
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
|
||||||
|
文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
|
||||||
|
-->
|
||||||
|
<resultMap id="NodeResultMap" type="pc.exam.pp.module.judgement.utils.tree.vo.TreeVO">
|
||||||
|
<id property="id" column="id" jdbcType="BIGINT"/>
|
||||||
|
<result property="name" column="name" jdbcType="VARCHAR"/>
|
||||||
|
<result property="parentId" column="parent_id" jdbcType="BIGINT"/>
|
||||||
|
<result property="nodeFunction" column="node_function" jdbcType="VARCHAR"/>
|
||||||
|
<result property="toChinese" column="to_chinese" jdbcType="VARCHAR"/>
|
||||||
|
<result property="type" column="type" jdbcType="TINYINT"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
|
||||||
|
<select id="selectTreeListByNodeFunction" resultMap="NodeResultMap">
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
wps_word_link
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="pc.exam.pp.module.judgement.dal.mysql.wpsxlsx.WpsXlsxLinkMapper">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
|
||||||
|
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
|
||||||
|
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
|
||||||
|
文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
|
||||||
|
-->
|
||||||
|
<resultMap id="NodeResultMap" type="pc.exam.pp.module.judgement.utils.tree.vo.TreeVO">
|
||||||
|
<id property="id" column="id" jdbcType="BIGINT"/>
|
||||||
|
<result property="name" column="name" jdbcType="VARCHAR"/>
|
||||||
|
<result property="parentId" column="parent_id" jdbcType="BIGINT"/>
|
||||||
|
<result property="nodeFunction" column="node_function" jdbcType="VARCHAR"/>
|
||||||
|
<result property="toChinese" column="to_chinese" jdbcType="VARCHAR"/>
|
||||||
|
<result property="type" column="type" jdbcType="TINYINT"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
|
||||||
|
<select id="selectTreeListByNodeFunction" resultMap="NodeResultMap">
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
wps_xlsx_link
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
@@ -184,6 +184,24 @@ public interface ErrorCodeConstants {
|
|||||||
ErrorCode WORD_NOT_ENABLE = new ErrorCode(1_002_030_006, "WORD节点({})不处于开启状态,不允许选择");
|
ErrorCode WORD_NOT_ENABLE = new ErrorCode(1_002_030_006, "WORD节点({})不处于开启状态,不允许选择");
|
||||||
ErrorCode WORD_PARENT_IS_CHILD = new ErrorCode(1_002_030_007, "不能设置自己的子WORD节点为父WORD节点");
|
ErrorCode WORD_PARENT_IS_CHILD = new ErrorCode(1_002_030_007, "不能设置自己的子WORD节点为父WORD节点");
|
||||||
|
|
||||||
|
// ========== WpsPptx 1-002-031-000 ==========
|
||||||
|
ErrorCode PPTX_NAME_DUPLICATE = new ErrorCode(1_002_031_000, "已经存在该名字的PPTX节点");
|
||||||
|
ErrorCode PPTX_PARENT_NOT_EXITS = new ErrorCode(1_002_031_001,"父级PPTX节点不存在");
|
||||||
|
ErrorCode PPTX_NOT_FOUND = new ErrorCode(1_002_031_002, "当前PPTX节点不存在");
|
||||||
|
ErrorCode PPTX_EXITS_CHILDREN = new ErrorCode(1_002_031_003, "存在子PPTX节点,无法删除");
|
||||||
|
ErrorCode PPTX_PARENT_ERROR = new ErrorCode(1_002_031_004, "不能设置自己为父PPTX节点");
|
||||||
|
ErrorCode PPTX_NOT_ENABLE = new ErrorCode(1_002_031_006, "PPTX节点({})不处于开启状态,不允许选择");
|
||||||
|
ErrorCode PPTX_PARENT_IS_CHILD = new ErrorCode(1_002_031_007, "不能设置自己的子PPTX节点为父PPTX节点");
|
||||||
|
|
||||||
|
// ========== WpsXlsx 1-002-032-000 ==========
|
||||||
|
ErrorCode XLSX_NAME_DUPLICATE = new ErrorCode(1_002_032_000, "已经存在该名字的XLSX节点");
|
||||||
|
ErrorCode XLSX_PARENT_NOT_EXITS = new ErrorCode(1_002_032_001,"父级XLSX节点不存在");
|
||||||
|
ErrorCode XLSX_NOT_FOUND = new ErrorCode(1_002_032_002, "当前XLSX节点不存在");
|
||||||
|
ErrorCode XLSX_EXITS_CHILDREN = new ErrorCode(1_002_032_003, "存在子XLSX节点,无法删除");
|
||||||
|
ErrorCode XLSX_PARENT_ERROR = new ErrorCode(1_002_032_004, "不能设置自己为父XLSX节点");
|
||||||
|
ErrorCode XLSX_NOT_ENABLE = new ErrorCode(1_002_032_006, "XLSX节点({})不处于开启状态,不允许选择");
|
||||||
|
ErrorCode XLSX_PARENT_IS_CHILD = new ErrorCode(1_002_032_007, "不能设置自己的子XLSX节点为父XLSX节点");
|
||||||
|
|
||||||
|
|
||||||
ErrorCode MONITOR_NOT_EXISTS = new ErrorCode(1_003_301_001, "找不到值!");
|
ErrorCode MONITOR_NOT_EXISTS = new ErrorCode(1_003_301_001, "找不到值!");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,20 @@ public interface RedisKeyConstants {
|
|||||||
* VALUE 数据类型:String 子WPS_WORD编号集合
|
* VALUE 数据类型:String 子WPS_WORD编号集合
|
||||||
*/
|
*/
|
||||||
String WPS_WORD_CHILDREN_ID_LIST = "wps_word_children_ids";
|
String WPS_WORD_CHILDREN_ID_LIST = "wps_word_children_ids";
|
||||||
|
/**
|
||||||
|
* 指定WPS_PPTX的所有子WPS_PPTX编号数组的缓存
|
||||||
|
* <p>
|
||||||
|
* KEY 格式:wps_pptx_children_ids:{id}
|
||||||
|
* VALUE 数据类型:String 子WPS_PPTX编号集合
|
||||||
|
*/
|
||||||
|
String WPS_PPTX_CHILDREN_ID_LIST = "wps_pptx_children_ids";
|
||||||
|
/**
|
||||||
|
* 指定WPS_XLSX的所有子WPS_XLSX编号数组的缓存
|
||||||
|
* <p>
|
||||||
|
* KEY 格式:wps_xlsx_children_ids:{id}
|
||||||
|
* VALUE 数据类型:String 子WPS_XLSX编号集合
|
||||||
|
*/
|
||||||
|
String WPS_XLSX_CHILDREN_ID_LIST = "wps_xlsx_children_ids";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 角色的缓存
|
* 角色的缓存
|
||||||
|
|||||||
Reference in New Issue
Block a user