【新增】 涵盖PPT部分考点(存在考点待开发)

This commit is contained in:
dlaren
2025-08-16 16:35:44 +08:00
parent db0d26c8bd
commit da33f0c690
10 changed files with 1701 additions and 88 deletions

View File

@@ -92,26 +92,27 @@ public class AutoWpsController {
);
return CommonResult.success(judgementWpsWordService.docxMaster(wpsDocxInfoVos, file));
}
/**
* 获取指定考点的数据
*
* @return
* @throws Exception
*/
// @PostMapping(value = "/slideMaster", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@PostMapping(value = "/slideMaster")
public CommonResult<List<JudgementSlidesVO>> slideMaster(@RequestBody List<WpsSlideInfoVo> wpsSlideInfoVos) throws Exception {
// public CommonResult<List<JudgementSlidesVO>> slideMaster(@RequestPart("data") String jsonData, @RequestPart("file") MultipartFile file) throws Exception {
// 手动解析JSON数组
// ObjectMapper objectMapper = new ObjectMapper();
// List<WpsSlideInfoVo> wpsSlideInfoVos = objectMapper.readValue(
// jsonData,
// new TypeReference<List<WpsSlideInfoVo>>() {
// }
// );
MultipartFile file = null;
@PostMapping(value = "/slideMaster", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
// @PostMapping(value = "/slideMaster")
// public CommonResult<List<JudgementSlidesVO>> slideMaster(@RequestBody List<WpsSlideInfoVo> wpsSlideInfoVos) throws Exception {
public CommonResult<List<JudgementSlidesVO>> slideMaster(@RequestPart("data") String jsonData, @RequestPart("file") MultipartFile file) throws Exception {
// 手动解析JSON数组
ObjectMapper objectMapper = new ObjectMapper();
List<WpsSlideInfoVo> wpsSlideInfoVos = objectMapper.readValue(
jsonData,
new TypeReference<List<WpsSlideInfoVo>>() {
}
);
return CommonResult.success(judgementWpsPptxService.slideMaster(wpsSlideInfoVos, file));
}
/**
* 获取指定考点的数据
*
@@ -119,17 +120,16 @@ public class AutoWpsController {
* @throws Exception
*/
@PostMapping(value = "/xlsxMaster", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public CommonResult<List<JudgementXlsxVO>> xlsxMaster(@RequestPart("data") String jsonData, @RequestPart("file") MultipartFile file,@RequestParam(value = "cell", required = false) List<String> cell) throws Exception {
public CommonResult<List<JudgementXlsxVO>> xlsxMaster(@RequestPart("data") String jsonData, @RequestPart("file") MultipartFile file, @RequestParam(value = "cell", required = false) List<String> cell) throws Exception {
// 手动解析JSON数组
ObjectMapper objectMapper = new ObjectMapper();
List<WpsXlsxInfoVo> wpsXlsxInfoVos= objectMapper.readValue(
List<WpsXlsxInfoVo> wpsXlsxInfoVos = objectMapper.readValue(
jsonData,
new TypeReference<List<WpsXlsxInfoVo>>() {
}
);
return CommonResult.success(judgementWpsExcelService.xlsxMaster(wpsXlsxInfoVos, file,cell));
return CommonResult.success(judgementWpsExcelService.xlsxMaster(wpsXlsxInfoVos, file, cell));
}
}

View File

@@ -7,12 +7,6 @@ public class WpsSlideInfoVo {
// 幻灯片位置(第几张幻灯片)
private String slideIndex;
// 形状位置只有在shape 形状(不包含图片) shapePic 形状图片
private String shapeIndex;
// 形状类型 slide 幻灯片设置 shape 形状(不包含图片) shapePic 形状图片 presentation 总幻灯片设置
private String type;
// 大类名称
private String firstName;
@@ -25,6 +19,6 @@ public class WpsSlideInfoVo {
// 考点代码
private String examCode;
// 方式方法
// 形状类型 slide 幻灯片设置 shape 形状(不包含图片) shapePic 形状图片 presentation 总幻灯片设置
private String method;
}

View File

@@ -2,15 +2,11 @@ package pc.exam.pp.module.judgement.utils.wps_pptx.pptx4j;
import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.JAXBException;
import org.apache.poi.sl.usermodel.TextParagraph;
import org.docx4j.dml.*;
import org.docx4j.jaxb.XPathBinderAssociationIsPartialException;
import org.docx4j.openpackaging.parts.PresentationML.SlidePart;
import org.pptx4j.pml.*;
import org.pptx4j.model.*;
import java.math.BigInteger;
import java.util.List;
public class ShapePage {
@@ -419,7 +415,260 @@ public class ShapePage {
// 动画 效果
public static String getAnimation(org.pptx4j.pml.Shape sp, CTSlideTiming timing) throws JAXBException, XPathBinderAssociationIsPartialException {
// public static String getAnimation(org.pptx4j.pml.Shape sp, CTSlideTiming timing) throws JAXBException, XPathBinderAssociationIsPartialException {
// // 获取形状中的ID
// if (sp == null) return "无动画";
// long spId = sp.getNvSpPr().getCNvPr().getId();
// // 获取动画效果
// CTTimeNodeList timeNodeList = timing.getTnLst();
// for (Object obj : timeNodeList.getParOrSeqOrExcl()) {
// if (obj instanceof CTTLTimeNodeParallel) {
// CTTLTimeNodeParallel par = (CTTLTimeNodeParallel) obj;
// CTTLCommonTimeNodeData node = par.getCTn();
// if (node.getChildTnLst().getParOrSeqOrExcl() != null) {
// CTTimeNodeList childTimeNodeList = node.getChildTnLst();
// for (Object object : childTimeNodeList.getParOrSeqOrExcl()) {
// if (object instanceof CTTLSetBehavior) {
// if (((CTTLSetBehavior) object).getCBhvr() != null) {
// if (((CTTLSetBehavior) object).getCBhvr().getTgtEl().getSpTgt() != null) {
// // 检查目标形状ID是否匹配
// if (((CTTLSetBehavior) object).getCBhvr().getTgtEl().getSpTgt().getSpid().equals(String.valueOf(spId))) {
// // 返回动画效果
//
// }
// }
// }
// }
// if (object instanceof CTTLTimeNodeSequence) {
// CTTLTimeNodeSequence seq = (CTTLTimeNodeSequence) object;
// CTTimeNodeList seqNodeList = seq.getCTn().getChildTnLst();
// for (Object seqObjs : seqNodeList.getParOrSeqOrExcl()) {
// if (seqObjs instanceof CTTLSetBehavior) {
// if (((CTTLSetBehavior) seqObjs).getCBhvr() != null) {
// if (((CTTLSetBehavior) seqObjs).getCBhvr().getTgtEl().getSpTgt() != null) {
// // 检查目标形状ID是否匹配
// if (((CTTLSetBehavior) seqObjs).getCBhvr().getTgtEl().getSpTgt().getSpid().equals(String.valueOf(spId))) {
// // 返回动画效果
//
// }
// }
// }
// }
// if (seqObjs instanceof CTTLTimeNodeSequence) {
// CTTLTimeNodeSequence seqObj = (CTTLTimeNodeSequence) seqObjs;
// CTTimeNodeList seqNodeLists = seqObj.getCTn().getChildTnLst();
// for (Object seqObjss : seqNodeLists.getParOrSeqOrExcl()) {
// if (seqObjss instanceof CTTLSetBehavior) {
// if (((CTTLSetBehavior) seqObjss).getCBhvr() != null) {
// if (((CTTLSetBehavior) seqObjss).getCBhvr().getTgtEl().getSpTgt() != null) {
// // 检查目标形状ID是否匹配
// if (((CTTLSetBehavior) seqObjss).getCBhvr().getTgtEl().getSpTgt().getSpid().equals(String.valueOf(spId))) {
// // 返回动画效果
//
// }
// }
// }
// }
// }
// }
// }
// }
// }
// }
//
//
// if (node.getDur() != null && !"indefinite".equals(node.getDur())) {
// return node.getDur();
// }
// System.out.println(par.getCTn());
// }
// }
// return "待开发";
// }
public static String getAnimation(org.pptx4j.pml.Shape sp, CTSlideTiming timing) {
if (sp == null || timing == null || timing.getTnLst() == null) return "无动画";
final String spId = String.valueOf(sp.getNvSpPr().getCNvPr().getId());
CTTimeNodeList root = timing.getTnLst();
// 先找进入类effect
String entrance = findFirstBehavior(root, spId, /*preferEntrance=*/true);
if (entrance != null) return entrance;
// 再找其它类型(包括 CTTLAnimateBehavior 的 ppt_x/ppt_y
String any = findFirstBehavior(root, spId, /*preferEntrance=*/false);
return any != null ? any : "无动画";
}
/* 递归遍历所有 time nodes返回首个命中的行为字符串 */
private static String findFirstBehavior(CTTimeNodeList list, String spId, boolean preferEntrance) {
if (list == null || list.getParOrSeqOrExcl() == null) return null;
for (Object raw : list.getParOrSeqOrExcl()) {
Object node = unwrap(raw);
// 1) 直接是某种行为Behavior
String desc = tryDescribeIfBehavior(node, spId, preferEntrance);
if (desc != null) return desc;
// 2) par / seq / excl进入子列表递归
CTTimeNodeList child = getChildList(node);
if (child != null) {
String got = findFirstBehavior(child, spId, preferEntrance);
if (got != null) return got;
}
}
return null;
}
/* 如果对象是某种 Behavior且目标命中当前 spId则返回描述否则返回 null */
private static String tryDescribeIfBehavior(Object obj, String spId, boolean preferEntrance) {
// 统一 unwrap
obj = unwrap(obj);
// --- 进入类效果Effect---
if (obj instanceof CTTLAnimateEffectBehavior) {
CTTLAnimateEffectBehavior b = (CTTLAnimateEffectBehavior) obj;
if (isTarget(b.getCBhvr(), spId)) {
String filter = safe(b.getFilter()); // 如 "fade"、"strips(downRight)" 等
return filter.isEmpty() ? "进入效果" : ("进入效果:" + filter);
}
}
// 非优先阶段:其它类型
if (!preferEntrance) {
// 通用 Animate (B 动画关键ppt_x / ppt_y)
if (obj instanceof CTTLAnimateBehavior) {
CTTLAnimateBehavior b = (CTTLAnimateBehavior) obj;
if (isTarget(b.getCBhvr(), spId)) {
String attr = firstAttrName(b.getCBhvr());
if ("ppt_x".equalsIgnoreCase(attr)) return "位置动画Xppt_x";
if ("ppt_y".equalsIgnoreCase(attr)) return "位置动画Yppt_y";
return attr.isEmpty() ? "数值动画Animate" : ("数值动画(" + attr + "");
}
}
if (obj instanceof CTTLAnimateMotionBehavior) {
CTTLAnimateMotionBehavior b = (CTTLAnimateMotionBehavior) obj;
if (isTarget(b.getCBhvr(), spId)) return "路径动画Motion";
}
if (obj instanceof CTTLAnimateRotationBehavior) {
CTTLAnimateRotationBehavior b = (CTTLAnimateRotationBehavior) obj;
if (isTarget(b.getCBhvr(), spId)) return "旋转动画";
}
if (obj instanceof CTTLAnimateScaleBehavior) {
CTTLAnimateScaleBehavior b = (CTTLAnimateScaleBehavior) obj;
if (isTarget(b.getCBhvr(), spId)) return "缩放动画";
}
if (obj instanceof CTTLSetBehavior) {
CTTLSetBehavior b = (CTTLSetBehavior) obj;
if (isTarget(b.getCBhvr(), spId)) {
String to = (b.getTo()!=null && b.getTo().getStrVal()!=null) ? safe(b.getTo().getStrVal().getVal()) : "";
String attr = firstAttrName(b.getCBhvr());
if (!attr.isEmpty() || !to.isEmpty()) {
return "属性设置Set" + (attr.isEmpty() ? "" : attr) + (to.isEmpty() ? "" : (" -> " + to));
}
return "属性设置Set";
}
}
if (obj instanceof CTTLAnimateColorBehavior) {
CTTLAnimateColorBehavior b = (CTTLAnimateColorBehavior) obj;
if (isTarget(b.getCBhvr(), spId)) return "颜色动画";
}
if (obj instanceof CTTLCommandBehavior) {
CTTLCommandBehavior b = (CTTLCommandBehavior) obj;
if (isTarget(b.getCBhvr(), spId)) return "命令动画Command";
}
}
return null;
}
/* 提取并返回子节点列表par/seq/excl 三种) */
private static CTTimeNodeList getChildList(Object node) {
node = unwrap(node);
if (node instanceof CTTLTimeNodeParallel) {
CTTLTimeNodeParallel n = (CTTLTimeNodeParallel) node;
return n.getCTn() != null ? n.getCTn().getChildTnLst() : null;
}
if (node instanceof CTTLTimeNodeSequence) {
CTTLTimeNodeSequence n = (CTTLTimeNodeSequence) node;
return n.getCTn() != null ? n.getCTn().getChildTnLst() : null;
}
if (node instanceof CTTLTimeNodeExclusive) {
CTTLTimeNodeExclusive n = (CTTLTimeNodeExclusive) node;
return n.getCTn() != null ? n.getCTn().getChildTnLst() : null;
}
return null;
}
/* 判断行为的目标是否命中当前形状 spId */
private static boolean isTarget(CTTLCommonBehaviorData cb, String spId) {
if (cb == null || cb.getTgtEl() == null || cb.getTgtEl().getSpTgt() == null) return false;
String tgt = cb.getTgtEl().getSpTgt().getSpid();
return String.valueOf(spId).equals(tgt);
}
/* 读第一个 attrName如 ppt_x / ppt_y / style.visibility ...*/
private static String firstAttrName(CTTLCommonBehaviorData cb) {
if (cb == null || cb.getAttrNameLst() == null) return "";
java.util.List<String> names = cb.getAttrNameLst().getAttrName();
return (names != null && !names.isEmpty()) ? safe(names.get(0)) : "";
}
/* 统一解包 JAXBElement */
private static Object unwrap(Object o) {
return (o instanceof JAXBElement) ? ((JAXBElement<?>) o).getValue() : o;
}
/* 安全字符串 */
private static String safe(String s) {
return s == null ? "" : s.trim();
}
// 动画-方向
public static String getAnimateDirection(org.pptx4j.pml.Shape sp, CTSlideTiming timing) {
String dir = getAnimation(sp, timing);
if (dir.equals("downRight")) {
return "右下";
}
if (dir.equals("downLeft")) {
return "左下";
}
if (dir.equals("upRight")) {
return "右上";
}
if (dir.equals("upLeft")) {
return "左上";
}
if (dir.equals("right")) {
return "向右";
}
if (dir.equals("left")) {
return "向左";
}
if (dir.equals("down")) {
return "向下";
}
if (dir.equals("up")) {
return "向上";
}
if (dir.equals("fromTop")) {
return "从顶部";
}
if (dir.equals("fromBottom")) {
return "从底部";
}
if (dir.equals("fromLeft")) {
return "从左侧";
}
if (dir.equals("fromRight")) {
return "从右侧";
}
return "";
}
// 动画 触发方式
public static String getAnimateTrigger(org.pptx4j.pml.Shape sp, CTSlideTiming timing) {
// 获取形状中的ID
if (sp == null) return "无动画";
long spId = sp.getNvSpPr().getCNvPr().getId();
@@ -429,27 +678,189 @@ public class ShapePage {
if (obj instanceof CTTLTimeNodeParallel) {
CTTLTimeNodeParallel par = (CTTLTimeNodeParallel) obj;
CTTLCommonTimeNodeData node = par.getCTn();
if (node.getDur() != null && !"indefinite".equals(node.getDur())) {
return node.getDur();
}
// 情况2检查子节点
// if (node.getChildTnLst() != null) {
// for (Object child : node.getChildTnLst().getParOrSeqOrExcl()) {
// if (child instanceof CTTLTimeNodeParallel) {
// String duration = getRealDuration(((CTTLTimeNodeParallel)child).getCTn());
// if (duration != null) return duration;
// }
// else if (child instanceof CTTLAnimateEffectBehavior) {
// return ((CTTLAnimateEffectBehavior)child).getDur();
// }
// // 其他类型处理...
// }
// }
System.out.println(par.getCTn());
if (node.getChildTnLst().getParOrSeqOrExcl() != null) {
CTTimeNodeList childTimeNodeList = node.getChildTnLst();
for (Object object : childTimeNodeList.getParOrSeqOrExcl()) {
if (object instanceof CTTLTimeNodeSequence) {
CTTLTimeNodeSequence seq = (CTTLTimeNodeSequence) object;
if (seq.getCTn().getStCondLst() != null) {
CTTLTimeConditionList stCondLst = seq.getCTn().getStCondLst();
for (CTTLTimeCondition o : stCondLst.getCond()) {
if (o.getEvt() != null) {
return o.getEvt().value();
}
}
} else {
CTTimeNodeList seqNodeList = seq.getCTn().getChildTnLst();
for (Object seqObj : seqNodeList.getParOrSeqOrExcl()) {
if (seqObj instanceof CTTLTimeNodeSequence) {
CTTLTimeNodeSequence seqs = (CTTLTimeNodeSequence) seqObj;
if (seqs.getCTn().getStCondLst() != null) {
CTTLTimeConditionList stCondLst = seqs.getCTn().getStCondLst();
for (CTTLTimeCondition o : stCondLst.getCond()) {
if (o.getEvt() != null) {
return o.getEvt().value();
}
}
} else {
CTTimeNodeList seqNodeLists = seqs.getCTn().getChildTnLst();
for (Object seqObjs : seqNodeLists.getParOrSeqOrExcl()) {
if (seqObjs instanceof CTTLTimeNodeSequence) {
CTTLTimeNodeSequence seqss = (CTTLTimeNodeSequence) seqObjs;
if (seqss.getCTn().getStCondLst() != null) {
CTTLTimeConditionList stCondLst = seqss.getCTn().getStCondLst();
for (CTTLTimeCondition o : stCondLst.getCond()) {
if (o.getEvt() != null) {
return o.getEvt().value();
}
}
}
}
}
}
} else {
if (seqObj instanceof CTTLTimeNodeParallel) {
CTTLTimeNodeParallel seqs = (CTTLTimeNodeParallel) seqObj;
if (seqs.getCTn().getStCondLst() != null) {
CTTLTimeConditionList stCondLst = seqs.getCTn().getStCondLst();
for (CTTLTimeCondition o : stCondLst.getCond()) {
if (o.getEvt() != null) {
return o.getEvt().value();
}
}
} else {
CTTimeNodeList seqNodeLists = seqs.getCTn().getChildTnLst();
for (Object seqObjs : seqNodeLists.getParOrSeqOrExcl()) {
if (seqObjs instanceof CTTLTimeNodeSequence) {
CTTLTimeNodeSequence seqss = (CTTLTimeNodeSequence) seqObjs;
if (seqss.getCTn().getStCondLst() != null) {
CTTLTimeConditionList stCondLst = seqss.getCTn().getStCondLst();
for (CTTLTimeCondition o : stCondLst.getCond()) {
if (o.getEvt() != null) {
return o.getEvt().value();
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
return "待开发";
return "";
}
// 动画 持续时间
public static String getAnimationDuration(org.pptx4j.pml.Shape sp, CTSlideTiming timing) {
if (sp == null || timing == null || timing.getTnLst() == null) return "无动画";
final String spId = String.valueOf(sp.getNvSpPr().getCNvPr().getId());
CTTimeNodeList root = timing.getTnLst();
// 先找“进入类效果effect
String entrance = findFirstBehavior(root, spId, /*preferEntrance=*/true);
if (entrance != null) return entrance;
// 找不到进入类再找其它类型运动、旋转、缩放、Set 等)
String any = findFirstBehavior(root, spId, /*preferEntrance=*/false);
return any != null ? any : "无动画";
}
// 动画 延迟
public static String getAnimationDelay(org.pptx4j.pml.Shape sp, CTSlideTiming timing) {
// 获取形状中的ID
if (sp == null) return "无动画";
long spId = sp.getNvSpPr().getCNvPr().getId();
// 获取动画效果
CTTimeNodeList timeNodeList = timing.getTnLst();
for (Object obj : timeNodeList.getParOrSeqOrExcl()) {
if (obj instanceof CTTLTimeNodeParallel) {
CTTLTimeNodeParallel par = (CTTLTimeNodeParallel) obj;
CTTLCommonTimeNodeData node = par.getCTn();
if (node.getChildTnLst().getParOrSeqOrExcl() != null) {
CTTimeNodeList childTimeNodeList = node.getChildTnLst();
for (Object object : childTimeNodeList.getParOrSeqOrExcl()) {
if (object instanceof CTTLTimeNodeSequence) {
CTTLTimeNodeSequence seq = (CTTLTimeNodeSequence) object;
if (seq.getCTn().getStCondLst() != null) {
CTTLTimeConditionList stCondLst = seq.getCTn().getStCondLst();
for (CTTLTimeCondition o : stCondLst.getCond()) {
if (o.getEvt() != null) {
return o.getDelay();
}
}
} else {
CTTimeNodeList seqNodeList = seq.getCTn().getChildTnLst();
for (Object seqObj : seqNodeList.getParOrSeqOrExcl()) {
if (seqObj instanceof CTTLTimeNodeSequence) {
CTTLTimeNodeSequence seqs = (CTTLTimeNodeSequence) seqObj;
if (seqs.getCTn().getStCondLst() != null) {
CTTLTimeConditionList stCondLst = seqs.getCTn().getStCondLst();
for (CTTLTimeCondition o : stCondLst.getCond()) {
if (o.getEvt() != null) {
return o.getDelay();
}
}
} else {
CTTimeNodeList seqNodeLists = seqs.getCTn().getChildTnLst();
for (Object seqObjs : seqNodeLists.getParOrSeqOrExcl()) {
if (seqObjs instanceof CTTLTimeNodeSequence) {
CTTLTimeNodeSequence seqss = (CTTLTimeNodeSequence) seqObjs;
if (seqss.getCTn().getStCondLst() != null) {
CTTLTimeConditionList stCondLst = seqss.getCTn().getStCondLst();
for (CTTLTimeCondition o : stCondLst.getCond()) {
if (o.getEvt() != null) {
return o.getDelay();
}
}
}
}
}
}
} else {
if (seqObj instanceof CTTLTimeNodeParallel) {
CTTLTimeNodeParallel seqs = (CTTLTimeNodeParallel) seqObj;
if (seqs.getCTn().getStCondLst() != null) {
CTTLTimeConditionList stCondLst = seqs.getCTn().getStCondLst();
for (CTTLTimeCondition o : stCondLst.getCond()) {
if (o.getEvt() != null) {
return o.getDelay();
}
}
} else {
CTTimeNodeList seqNodeLists = seqs.getCTn().getChildTnLst();
for (Object seqObjs : seqNodeLists.getParOrSeqOrExcl()) {
if (seqObjs instanceof CTTLTimeNodeSequence) {
CTTLTimeNodeSequence seqss = (CTTLTimeNodeSequence) seqObjs;
if (seqss.getCTn().getStCondLst() != null) {
CTTLTimeConditionList stCondLst = seqss.getCTn().getStCondLst();
for (CTTLTimeCondition o : stCondLst.getCond()) {
if (o.getEvt() != null) {
return o.getDelay();
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
return "";
}
/// 形状动作,鼠标单机-动作
@@ -1002,7 +1413,6 @@ public class ShapePage {
}
}
}
return "";
}
/// 文本轮廓 宽度
@@ -1052,5 +1462,86 @@ public class ShapePage {
return "待开发";
}
// 文字效果 阴影→绘制
public static String getTextBoxParagraphShadowDraw(org.pptx4j.pml.Shape sp, CTSlideTiming timing) {
if (sp.getTxBody() != null) {
for (CTTextParagraph paragraph : sp.getTxBody().getP()) {
for (Object obj : paragraph.getEGTextRun()) {
if (obj instanceof CTRegularTextRun ctRegularTextRun) {
CTTextCharacterProperties rPr = ctRegularTextRun.getRPr();
CTEffectList ctEffectList = rPr.getEffectLst();
if (ctEffectList.getInnerShdw() != null || ctEffectList.getOuterShdw() != null || ctEffectList.getPrstShdw() != null) {
return "";
} else {
return "";
}
}
}
}
}
return "";
}
// 文字效果 阴影→预设
// 文字效果 阴影→效果
public static String getTextBoxParagraphShadowEffect(org.pptx4j.pml.Shape sp, CTSlideTiming timing) {
return "待开发";
}
// 文字效果 倒影→绘制
public static String getTextBoxParagraphReflectionDraw(org.pptx4j.pml.Shape sp, CTSlideTiming timing) {
if (sp.getTxBody() != null) {
for (CTTextParagraph paragraph : sp.getTxBody().getP()) {
for (Object obj : paragraph.getEGTextRun()) {
if (obj instanceof CTRegularTextRun ctRegularTextRun) {
CTTextCharacterProperties rPr = ctRegularTextRun.getRPr();
CTEffectList ctEffectList = rPr.getEffectLst();
if (ctEffectList != null && ctEffectList.getReflection() != null) {
return "";
} else {
return "";
}
}
}
}
}
return "";
}
// 文字效果 倒影→预设
// 文字效果 倒影→效果
public static String getTextBoxParagraphReflectionEffect(org.pptx4j.pml.Shape sp, CTSlideTiming timing) {
if (sp.getTxBody() != null) {
for (CTTextParagraph paragraph : sp.getTxBody().getP()) {
for (Object obj : paragraph.getEGTextRun()) {
if (obj instanceof CTRegularTextRun ctRegularTextRun) {
CTTextCharacterProperties rPr = ctRegularTextRun.getRPr();
CTEffectList ctEffectList = rPr.getEffectLst();
CTReflectionEffect ctReflectionEffect = ctEffectList.getReflection();
return SlideUtils.getShadowLikeDescription(ctReflectionEffect);
}
}
}
}
return "";
}
// 文字效果 发光→绘制
public static String getTextBoxParagraphGlowDraw(org.pptx4j.pml.Shape sp, CTSlideTiming timing) {
return "待开发";
}
// 文字效果 发光→效果
public static String getTextBoxParagraphGlowEffect(org.pptx4j.pml.Shape sp, CTSlideTiming timing) {
return "待开发";
}
// 文字效果 转换→弯曲
public static String getTextBoxParagraphConvertCurve(org.pptx4j.pml.Shape sp, CTSlideTiming timing) {
return "待开发";
}
// 文字效果 单机鼠标
public static String getTextBoxParagraphMouseClick(org.pptx4j.pml.Shape sp, CTSlideTiming timing) {
System.out.println(timing);
return "待开发";
}
}

View File

@@ -0,0 +1,859 @@
package pc.exam.pp.module.judgement.utils.wps_pptx.pptx4j;
import jakarta.xml.bind.JAXBElement;
import org.docx4j.dml.*;
import org.pptx4j.pml.*;
import java.math.BigInteger;
public class ShapePic {
// 大小 - 高度
public static String getShapeSizeHeight(Pic sp, CTSlideTiming timing) {
CTTransform2D xfrm = sp.getSpPr().getXfrm();
// 获取位置和尺寸(单位 EMU1英寸=914400 EMU1cm≈360000 EMU
CTPositiveSize2D ext = xfrm.getExt(); // 尺寸
double heightPt = emuToPt(ext.getCy());
return String.valueOf(heightPt);
}
// 大小 - 宽度
public static String getShapeSizeWidthPt(Pic sp, CTSlideTiming timing) {
CTTransform2D xfrm = sp.getSpPr().getXfrm();
// 获取位置和尺寸(单位 EMU1英寸=914400 EMU1cm≈360000 EMU
CTPositiveSize2D ext = xfrm.getExt(); // 尺寸
double widthPt = emuToPt(ext.getCx());
return String.valueOf(widthPt);
}
// 大小 - 锁定纵横比
public static String getShapeSizeLockAspectRatio(Pic sp, CTSlideTiming timing) {
CTTransform2D xfrm = sp.getSpPr().getXfrm();
// 获取位置和尺寸(单位 EMU1英寸=914400 EMU1cm≈360000 EMU
CTPositiveSize2D ext = xfrm.getExt(); // 尺寸
Boolean lockAspectRatio = null;
if (sp.getSpPr().getPrstGeom() != null &&
sp.getSpPr().getPrstGeom().getAvLst() != null) {
// 这个部分一般不会直接提供锁定横纵比,要看 spPr.getExtLst()
if (sp.getSpPr().getExtLst() != null) {
// pptx4j 没有直接的 getter要自己解析 XML
String xml = sp.getSpPr().getExtLst().toString();
if (xml.contains("lockAspectRatio=\"1\"") || xml.contains("lockAspectRatio=\"true\"")) {
lockAspectRatio = true;
} else if (xml.contains("lockAspectRatio=\"0\"") || xml.contains("lockAspectRatio=\"false\"")) {
lockAspectRatio = false;
}
}
}
return String.valueOf(lockAspectRatio);
}
// EMU 转 pt
private static double emuToPt(long emu) {
return emu / 12700.0;
}
/// 大小 旋转
public static String getShapeSizeRotate(Pic sp, CTSlideTiming timing) {
return "待开发";
}
// 位置 水平位置
public static String getShapePositionLeft(Pic sp, CTSlideTiming timing) {
CTTransform2D xfrm = sp.getSpPr().getXfrm();
if (xfrm != null) {
long x = xfrm.getOff().getX(); // 水平位置EMU
return String.valueOf(x / 9525.0);
}
return "";
}
// 位置 垂直位置
public static String getShapePositionTop(Pic sp, CTSlideTiming timing) {
CTTransform2D xfrm = sp.getSpPr().getXfrm();
if (xfrm != null) {
long y = xfrm.getOff().getY(); // 垂直位置EMU
return String.valueOf(y / 9525.0);
}
return "";
}
// 形状填充 填充方式
public static String getShapeFillType(Pic sp, CTSlideTiming timing) {
CTShapeProperties spPr = sp.getSpPr();
return SlideUtils.getFillType(spPr);
}
// 形状填充 纯色填充-颜色
public static String getShapeFillSolidColor(Pic sp, CTSlideTiming timing) {
CTShapeProperties spPr = sp.getSpPr();
if (spPr != null && spPr.getSolidFill() != null) {
return SlideUtils.getSolidFillColor(spPr.getSolidFill());
}
return "";
}
// 形状填充 渐变填充-效果
public static String getShapeFillGradientType(Pic sp, CTSlideTiming timing) {
CTShapeProperties spPr = sp.getSpPr();
if (spPr != null && spPr.getGradFill() != null) {
System.out.println("形状: " + sp.getNvPicPr().getCNvPr().getName());
return SlideUtils.printGradientFill(spPr.getGradFill());
}
return "";
}
// 形状填充 图片填充-效果
public static String getShapeFillPictureType(Pic sp, CTSlideTiming timing) {
CTShapeProperties spPr = sp.getSpPr();
if (spPr != null && spPr.getBlipFill() != null) {
System.out.println("形状: " + sp.getNvPicPr().getCNvPr().getName());
return SlideUtils.printImageFill(spPr.getBlipFill());
}
return "";
}
// 形状填充 纹理填充-效果
public static String getShapeFillTextureType(Pic sp, CTSlideTiming timing) {
CTShapeProperties spPr = sp.getSpPr();
if (spPr != null && spPr.getPattFill() != null) {
return SlideUtils.printPatternFill(spPr.getPattFill());
}
return "";
}
// 形状填充 图案填充-效果
public static String getShapeFillPatternType(Pic sp, CTSlideTiming timing) {
CTShapeProperties spPr = sp.getSpPr();
if (spPr != null && spPr.getPattFill() != null) {
return spPr.getPattFill().getPrst().value();
}
return "";
}
// 形状填充 幻灯片背景填充-效果
public static String getShapeFillSlideBackgroundType(Pic sp, CTSlideTiming timing) {
return "待开发";
}
// 形状填充 填充透明度
public static String getShapeFillOpacity(Pic sp, CTSlideTiming timing) {
return "待开发";
}
// 形状线条 绘制
public static String getShapeLineDraw(Pic sp, CTSlideTiming timing) {
CTShapeProperties spPr = sp.getSpPr();
if (spPr != null && spPr.getLn() != null) {
CTLineProperties ln = spPr.getLn();
// 宽度EMU -> pt
double widthPt = ln.getW() / 12700.0;
System.out.println("形状: " + sp.getNvPicPr().getCNvPr().getName());
System.out.println("线宽: " + widthPt + " pt");
// 颜色
if (ln.getSolidFill() != null && ln.getSolidFill().getSrgbClr() != null) {
CTSRgbColor rgb = ln.getSolidFill().getSrgbClr();
System.out.println("线条颜色: #" + rgb.getVal());
}
// 虚线样式
if (ln.getPrstDash() != null) {
System.out.println("线型: " + ln.getPrstDash().getVal().value());
}
// 端点样式
if (ln.getCap() != null) {
System.out.println("端点: " + ln.getCap().value());
}
return "";
}
return "";
}
// 形状线条 线条颜色
public static String getShapeLineColor(Pic sp, CTSlideTiming timing) {
CTShapeProperties spPr = sp.getSpPr();
if (spPr != null && spPr.getLn() != null) {
CTLineProperties ln = spPr.getLn();
// 颜色
if (ln.getSolidFill() != null && ln.getSolidFill().getSrgbClr() != null) {
CTSRgbColor rgb = ln.getSolidFill().getSrgbClr();
return rgb.getVal();
}
}
return "";
}
// 形状线条 线条宽度
public static String getShapeLineWidth(Pic sp, CTSlideTiming timing) {
CTShapeProperties spPr = sp.getSpPr();
if (spPr != null && spPr.getLn() != null) {
CTLineProperties ln = spPr.getLn();
// 宽度EMU -> pt
double widthPt = ln.getW() / 12700.0;
return String.valueOf(widthPt);
}
return "";
}
// 形状线条 透明度
public static String getShapeLineOpacity(Pic sp, CTSlideTiming timing) {
return "";
}
// 形状线条 复合类型
public static String getStrokeCompound(Pic sp, CTSlideTiming timing) {
if (sp == null || sp.getSpPr() == null) return "未定义";
CTShapeProperties spPr = sp.getSpPr();
CTLineProperties ln = spPr.getLn();
if (ln == null) return "未定义";
STCompoundLine cmpd = ln.getCmpd(); // 可能为 null
String v = (cmpd != null) ? cmpd.value() : "sng"; // 默认单线
switch (v) {
case "dbl":
return "双线 (dbl)";
case "thickThin":
return "粗-细双线 (thickThin)";
case "thinThick":
return "细-粗双线 (thinThick)";
case "tri":
return "三重线 (tri)";
case "sng":
default:
return "单线 (sng)";
}
}
// 形状线条 短划线类型
public static String getStrokeDash(Pic sp, CTSlideTiming timing) {
if (sp == null || sp.getSpPr() == null) return "solid";
CTShapeProperties spPr = sp.getSpPr();
CTLineProperties ln = spPr.getLn();
if (ln == null) return "solid";
// 1) 预设短划线
if (ln.getPrstDash() != null && ln.getPrstDash().getVal() != null) {
STPresetLineDashVal val = ln.getPrstDash().getVal();
return SlideUtils.mapPreset(val);
}
// 2) 自定义短划线
if (ln.getCustDash() != null && ln.getCustDash().getDs() != null && !ln.getCustDash().getDs().isEmpty()) {
StringBuilder sb = new StringBuilder("custom ");
for (CTDashStop ds : ln.getCustDash().getDs()) {
int d = ds.getD(); // dash length相对线宽的比例单位
int sps = ds.getSp(); // space length相对线宽的比例单位
sb.append("[d=").append(d).append(", sps=").append(sps).append("] ");
}
return sb.toString().trim();
}
// 3) 未设置 → 视为实线
return "solid";
}
// 形状线条 开始箭头类型
public static String getShapeLineStartArrow(Pic sp, CTSlideTiming timing) {
CTShapeProperties spPr = sp.getSpPr();
if (spPr != null && spPr.getLn() != null) {
CTLineProperties ln = spPr.getLn();
if (ln.getHeadEnd() != null) {
return ln.getHeadEnd().getType().value();
}
}
return "无箭头";
}
// 形状线条 开始箭头粗细
public static String getShapeLineStartArrowWidth(Pic sp, CTSlideTiming timing) {
return "待开发";
}
// 形状线条 结尾箭头类型
public static String getShapeLineEndArrow(Pic sp, CTSlideTiming timing) {
return "待开发";
}
// 形状线条 结尾箭头粗细
public static String getShapeLineEndArrowWidth(Pic sp, CTSlideTiming timing) {
return "待开发";
}
// 形状效果 阴影-绘制
public static String getShapeShadowDraw(Pic sp, CTSlideTiming timing) {
CTShapeProperties spPr = sp.getSpPr();
CTEffectList effList = spPr.getEffectLst();
if (effList == null) {
return "";
}
// 判断三种阴影效果
return effList.getOuterShdw() != null
|| effList.getInnerShdw() != null
|| effList.getPrstShdw() != null ? "" : "";
}
// 形状效果 阴影-效果
public static String getShapeShadowEffect(Pic sp, CTSlideTiming timing) {
if (sp == null || sp.getSpPr() == null) {
return "无阴影";
}
CTShapeProperties spPr = sp.getSpPr();
CTEffectList effList = spPr.getEffectLst();
if (effList == null) {
return "无阴影";
}
if (effList.getOuterShdw() != null) {
return "外阴影";
} else if (effList.getInnerShdw() != null) {
return "内阴影";
} else if (effList.getPrstShdw() != null) {
return "预设阴影";
}
return "无阴影";
}
// 形状效果 倒影-绘制
public static String getShapeReflectionDraw(Pic sp, CTSlideTiming timing) {
CTShapeProperties spPr = sp.getSpPr();
CTEffectList effList = spPr.getEffectLst();
if (effList == null) {
return "无倒影";
}
CTReflectionEffect reflection = effList.getReflection();
if (reflection != null) {
// 如果需要详细参数,这里可以读取
return "有倒影";
}
return "无倒影";
}
// 形状效果 倒影-效果
public static String getShapeReflectionEffect(Pic sp, CTSlideTiming timing) {
CTReflectionEffect r = SlideUtils.getReflectionPic(sp);
if (r == null) return "无倒影";
// —— 1) 倒影覆盖程度:用 stPos/endPos0..100000)估算 —— //
double st = SlideUtils.to100k(BigInteger.valueOf(r.getStPos()), 0);
double ed = SlideUtils.to100k(BigInteger.valueOf(r.getEndPos()), 100000); // 默认 100%
double coverage = Math.max(0, ed - st) / 100000.0; // 0.0 ~ 1.0
String coverageLabel;
if (coverage >= 0.85) {
coverageLabel = "全倒影";
} else if (coverage >= 0.45) {
coverageLabel = "半倒影";
} else {
coverageLabel = "短倒影";
}
// —— 2) 偏移描述dist EMU -> pt<1pt 视作“紧贴”,否则 "Xpt 偏移" —— //
double distPt = emuToPt(r.getDist()); // 可能为 0
String offsetLabel = distPt < 1.0 ? "紧贴" : (SlideUtils.fmt1(distPt) + "pt 偏移");
return coverageLabel + " " + offsetLabel;
}
// 形状效果 发光
public static String getShapeGlow(Pic sp, CTSlideTiming timing) {
if (sp == null || sp.getSpPr() == null) return null;
CTShapeProperties spPr = sp.getSpPr();
CTEffectList eff = spPr.getEffectLst();
return (eff != null) ? eff.getGlow().toString() : null;
}
// 形状效果 发光-效果
public static String getShapeGlowEffect(Pic sp, CTSlideTiming timing) {
return "待开发";
}
// 形状效果 柔化边缘-绘制
public static String getShapeSoftEdgesDraw(Pic sp, CTSlideTiming timing) {
CTSoftEdgesEffect se = getSoftEdge(sp);
return (se != null) ? "" : "";
}
// 形状效果 柔化边缘→大小
public static String getShapeSoftEdgesSize(Pic sp, CTSlideTiming timing) {
CTSoftEdgesEffect se = getSoftEdge(sp);
return (se != null) ? String.valueOf(se.getRad()) : null;
}
// 形状效果 三维效果→绘制
public static String getShape3DEffectDraw(Pic sp, CTSlideTiming timing) {
return "待开发";
}
// 形状效果 三维格式→效果
public static String getShape3DEffect(Pic sp, CTSlideTiming timing) {
return "待开发";
}
// 形状效果 三维旋转→效果
public static String getShape3DRotation(Pic sp, CTSlideTiming timing) {
return "待开发";
}
/* —— 内部spPr/effectLst/softEdge —— */
private static CTSoftEdgesEffect getSoftEdge(Pic shape) {
if (shape == null || shape.getSpPr() == null) return null;
CTShapeProperties spPr = shape.getSpPr();
CTEffectList eff = spPr.getEffectLst();
return (eff != null) ? eff.getSoftEdge() : null;
// 说明:极少数文件把效果写在 effectDag若拿不到再补 effectDag 解析。
}
// 动画 效果
// public static String getAnimation(org.pptx4j.pml.Shape sp, CTSlideTiming timing) throws JAXBException, XPathBinderAssociationIsPartialException {
// // 获取形状中的ID
// if (sp == null) return "无动画";
// long spId = sp.getNvSpPr().getCNvPr().getId();
// // 获取动画效果
// CTTimeNodeList timeNodeList = timing.getTnLst();
// for (Object obj : timeNodeList.getParOrSeqOrExcl()) {
// if (obj instanceof CTTLTimeNodeParallel) {
// CTTLTimeNodeParallel par = (CTTLTimeNodeParallel) obj;
// CTTLCommonTimeNodeData node = par.getCTn();
// if (node.getChildTnLst().getParOrSeqOrExcl() != null) {
// CTTimeNodeList childTimeNodeList = node.getChildTnLst();
// for (Object object : childTimeNodeList.getParOrSeqOrExcl()) {
// if (object instanceof CTTLSetBehavior) {
// if (((CTTLSetBehavior) object).getCBhvr() != null) {
// if (((CTTLSetBehavior) object).getCBhvr().getTgtEl().getSpTgt() != null) {
// // 检查目标形状ID是否匹配
// if (((CTTLSetBehavior) object).getCBhvr().getTgtEl().getSpTgt().getSpid().equals(String.valueOf(spId))) {
// // 返回动画效果
//
// }
// }
// }
// }
// if (object instanceof CTTLTimeNodeSequence) {
// CTTLTimeNodeSequence seq = (CTTLTimeNodeSequence) object;
// CTTimeNodeList seqNodeList = seq.getCTn().getChildTnLst();
// for (Object seqObjs : seqNodeList.getParOrSeqOrExcl()) {
// if (seqObjs instanceof CTTLSetBehavior) {
// if (((CTTLSetBehavior) seqObjs).getCBhvr() != null) {
// if (((CTTLSetBehavior) seqObjs).getCBhvr().getTgtEl().getSpTgt() != null) {
// // 检查目标形状ID是否匹配
// if (((CTTLSetBehavior) seqObjs).getCBhvr().getTgtEl().getSpTgt().getSpid().equals(String.valueOf(spId))) {
// // 返回动画效果
//
// }
// }
// }
// }
// if (seqObjs instanceof CTTLTimeNodeSequence) {
// CTTLTimeNodeSequence seqObj = (CTTLTimeNodeSequence) seqObjs;
// CTTimeNodeList seqNodeLists = seqObj.getCTn().getChildTnLst();
// for (Object seqObjss : seqNodeLists.getParOrSeqOrExcl()) {
// if (seqObjss instanceof CTTLSetBehavior) {
// if (((CTTLSetBehavior) seqObjss).getCBhvr() != null) {
// if (((CTTLSetBehavior) seqObjss).getCBhvr().getTgtEl().getSpTgt() != null) {
// // 检查目标形状ID是否匹配
// if (((CTTLSetBehavior) seqObjss).getCBhvr().getTgtEl().getSpTgt().getSpid().equals(String.valueOf(spId))) {
// // 返回动画效果
//
// }
// }
// }
// }
// }
// }
// }
// }
// }
// }
//
//
// if (node.getDur() != null && !"indefinite".equals(node.getDur())) {
// return node.getDur();
// }
// System.out.println(par.getCTn());
// }
// }
// return "待开发";
// }
public static String getAnimation(org.pptx4j.pml.Pic sp, CTSlideTiming timing) {
if (sp == null || timing == null || timing.getTnLst() == null) return "无动画";
final String spId = String.valueOf(sp.getNvPicPr().getCNvPr().getId());
CTTimeNodeList root = timing.getTnLst();
// 先找进入类effect
String entrance = findFirstBehavior(root, spId, /*preferEntrance=*/true);
if (entrance != null) return entrance;
// 再找其它类型(包括 CTTLAnimateBehavior 的 ppt_x/ppt_y
String any = findFirstBehavior(root, spId, /*preferEntrance=*/false);
return any != null ? any : "无动画";
}
/* 递归遍历所有 time nodes返回首个命中的行为字符串 */
private static String findFirstBehavior(CTTimeNodeList list, String spId, boolean preferEntrance) {
if (list == null || list.getParOrSeqOrExcl() == null) return null;
for (Object raw : list.getParOrSeqOrExcl()) {
Object node = unwrap(raw);
// 1) 直接是某种行为Behavior
String desc = tryDescribeIfBehavior(node, spId, preferEntrance);
if (desc != null) return desc;
// 2) par / seq / excl进入子列表递归
CTTimeNodeList child = getChildList(node);
if (child != null) {
String got = findFirstBehavior(child, spId, preferEntrance);
if (got != null) return got;
}
}
return null;
}
/* 如果对象是某种 Behavior且目标命中当前 spId则返回描述否则返回 null */
private static String tryDescribeIfBehavior(Object obj, String spId, boolean preferEntrance) {
// 统一 unwrap
obj = unwrap(obj);
// --- 进入类效果Effect---
if (obj instanceof CTTLAnimateEffectBehavior) {
CTTLAnimateEffectBehavior b = (CTTLAnimateEffectBehavior) obj;
if (isTarget(b.getCBhvr(), spId)) {
String filter = safe(b.getFilter()); // 如 "fade"、"strips(downRight)" 等
return filter.isEmpty() ? "进入效果" : ("进入效果:" + filter);
}
}
// 非优先阶段:其它类型
if (!preferEntrance) {
// 通用 Animate (B 动画关键ppt_x / ppt_y)
if (obj instanceof CTTLAnimateBehavior) {
CTTLAnimateBehavior b = (CTTLAnimateBehavior) obj;
if (isTarget(b.getCBhvr(), spId)) {
String attr = firstAttrName(b.getCBhvr());
if ("ppt_x".equalsIgnoreCase(attr)) return "位置动画Xppt_x";
if ("ppt_y".equalsIgnoreCase(attr)) return "位置动画Yppt_y";
return attr.isEmpty() ? "数值动画Animate" : ("数值动画(" + attr + "");
}
}
if (obj instanceof CTTLAnimateMotionBehavior) {
CTTLAnimateMotionBehavior b = (CTTLAnimateMotionBehavior) obj;
if (isTarget(b.getCBhvr(), spId)) return "路径动画Motion";
}
if (obj instanceof CTTLAnimateRotationBehavior) {
CTTLAnimateRotationBehavior b = (CTTLAnimateRotationBehavior) obj;
if (isTarget(b.getCBhvr(), spId)) return "旋转动画";
}
if (obj instanceof CTTLAnimateScaleBehavior) {
CTTLAnimateScaleBehavior b = (CTTLAnimateScaleBehavior) obj;
if (isTarget(b.getCBhvr(), spId)) return "缩放动画";
}
if (obj instanceof CTTLSetBehavior) {
CTTLSetBehavior b = (CTTLSetBehavior) obj;
if (isTarget(b.getCBhvr(), spId)) {
String to = (b.getTo()!=null && b.getTo().getStrVal()!=null) ? safe(b.getTo().getStrVal().getVal()) : "";
String attr = firstAttrName(b.getCBhvr());
if (!attr.isEmpty() || !to.isEmpty()) {
return "属性设置Set" + (attr.isEmpty() ? "" : attr) + (to.isEmpty() ? "" : (" -> " + to));
}
return "属性设置Set";
}
}
if (obj instanceof CTTLAnimateColorBehavior) {
CTTLAnimateColorBehavior b = (CTTLAnimateColorBehavior) obj;
if (isTarget(b.getCBhvr(), spId)) return "颜色动画";
}
if (obj instanceof CTTLCommandBehavior) {
CTTLCommandBehavior b = (CTTLCommandBehavior) obj;
if (isTarget(b.getCBhvr(), spId)) return "命令动画Command";
}
}
return null;
}
/* 提取并返回子节点列表par/seq/excl 三种) */
private static CTTimeNodeList getChildList(Object node) {
node = unwrap(node);
if (node instanceof CTTLTimeNodeParallel) {
CTTLTimeNodeParallel n = (CTTLTimeNodeParallel) node;
return n.getCTn() != null ? n.getCTn().getChildTnLst() : null;
}
if (node instanceof CTTLTimeNodeSequence) {
CTTLTimeNodeSequence n = (CTTLTimeNodeSequence) node;
return n.getCTn() != null ? n.getCTn().getChildTnLst() : null;
}
if (node instanceof CTTLTimeNodeExclusive) {
CTTLTimeNodeExclusive n = (CTTLTimeNodeExclusive) node;
return n.getCTn() != null ? n.getCTn().getChildTnLst() : null;
}
return null;
}
/* 判断行为的目标是否命中当前形状 spId */
private static boolean isTarget(CTTLCommonBehaviorData cb, String spId) {
if (cb == null || cb.getTgtEl() == null || cb.getTgtEl().getSpTgt() == null) return false;
String tgt = cb.getTgtEl().getSpTgt().getSpid();
return String.valueOf(spId).equals(tgt);
}
/* 读第一个 attrName如 ppt_x / ppt_y / style.visibility ...*/
private static String firstAttrName(CTTLCommonBehaviorData cb) {
if (cb == null || cb.getAttrNameLst() == null) return "";
java.util.List<String> names = cb.getAttrNameLst().getAttrName();
return (names != null && !names.isEmpty()) ? safe(names.get(0)) : "";
}
/* 统一解包 JAXBElement */
private static Object unwrap(Object o) {
return (o instanceof JAXBElement) ? ((JAXBElement<?>) o).getValue() : o;
}
/* 安全字符串 */
private static String safe(String s) {
return s == null ? "" : s.trim();
}
// 动画-方向
public static String getAnimateDirection(Pic sp, CTSlideTiming timing) {
String dir = getAnimation(sp, timing);
if (dir.equals("downRight")) {
return "右下";
}
if (dir.equals("downLeft")) {
return "左下";
}
if (dir.equals("upRight")) {
return "右上";
}
if (dir.equals("upLeft")) {
return "左上";
}
if (dir.equals("right")) {
return "向右";
}
if (dir.equals("left")) {
return "向左";
}
if (dir.equals("down")) {
return "向下";
}
if (dir.equals("up")) {
return "向上";
}
if (dir.equals("fromTop")) {
return "从顶部";
}
if (dir.equals("fromBottom")) {
return "从底部";
}
if (dir.equals("fromLeft")) {
return "从左侧";
}
if (dir.equals("fromRight")) {
return "从右侧";
}
return "";
}
// 动画 触发方式
public static String getAnimateTrigger(Pic sp, CTSlideTiming timing) {
// 获取形状中的ID
if (sp == null) return "无动画";
long spId = sp.getNvPicPr().getCNvPr().getId();
// 获取动画效果
CTTimeNodeList timeNodeList = timing.getTnLst();
for (Object obj : timeNodeList.getParOrSeqOrExcl()) {
if (obj instanceof CTTLTimeNodeParallel) {
CTTLTimeNodeParallel par = (CTTLTimeNodeParallel) obj;
CTTLCommonTimeNodeData node = par.getCTn();
if (node.getChildTnLst().getParOrSeqOrExcl() != null) {
CTTimeNodeList childTimeNodeList = node.getChildTnLst();
for (Object object : childTimeNodeList.getParOrSeqOrExcl()) {
if (object instanceof CTTLTimeNodeSequence) {
CTTLTimeNodeSequence seq = (CTTLTimeNodeSequence) object;
if (seq.getCTn().getStCondLst() != null) {
CTTLTimeConditionList stCondLst = seq.getCTn().getStCondLst();
for (CTTLTimeCondition o : stCondLst.getCond()) {
if (o.getEvt() != null) {
return o.getEvt().value();
}
}
} else {
CTTimeNodeList seqNodeList = seq.getCTn().getChildTnLst();
for (Object seqObj : seqNodeList.getParOrSeqOrExcl()) {
if (seqObj instanceof CTTLTimeNodeSequence) {
CTTLTimeNodeSequence seqs = (CTTLTimeNodeSequence) seqObj;
if (seqs.getCTn().getStCondLst() != null) {
CTTLTimeConditionList stCondLst = seqs.getCTn().getStCondLst();
for (CTTLTimeCondition o : stCondLst.getCond()) {
if (o.getEvt() != null) {
return o.getEvt().value();
}
}
} else {
CTTimeNodeList seqNodeLists = seqs.getCTn().getChildTnLst();
for (Object seqObjs : seqNodeLists.getParOrSeqOrExcl()) {
if (seqObjs instanceof CTTLTimeNodeSequence) {
CTTLTimeNodeSequence seqss = (CTTLTimeNodeSequence) seqObjs;
if (seqss.getCTn().getStCondLst() != null) {
CTTLTimeConditionList stCondLst = seqss.getCTn().getStCondLst();
for (CTTLTimeCondition o : stCondLst.getCond()) {
if (o.getEvt() != null) {
return o.getEvt().value();
}
}
}
}
}
}
} else {
if (seqObj instanceof CTTLTimeNodeParallel) {
CTTLTimeNodeParallel seqs = (CTTLTimeNodeParallel) seqObj;
if (seqs.getCTn().getStCondLst() != null) {
CTTLTimeConditionList stCondLst = seqs.getCTn().getStCondLst();
for (CTTLTimeCondition o : stCondLst.getCond()) {
if (o.getEvt() != null) {
return o.getEvt().value();
}
}
} else {
CTTimeNodeList seqNodeLists = seqs.getCTn().getChildTnLst();
for (Object seqObjs : seqNodeLists.getParOrSeqOrExcl()) {
if (seqObjs instanceof CTTLTimeNodeSequence) {
CTTLTimeNodeSequence seqss = (CTTLTimeNodeSequence) seqObjs;
if (seqss.getCTn().getStCondLst() != null) {
CTTLTimeConditionList stCondLst = seqss.getCTn().getStCondLst();
for (CTTLTimeCondition o : stCondLst.getCond()) {
if (o.getEvt() != null) {
return o.getEvt().value();
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
return "";
}
// 动画 持续时间
public static String getAnimationDuration(Pic sp, CTSlideTiming timing) {
if (sp == null || timing == null || timing.getTnLst() == null) return "无动画";
final String spId = String.valueOf(sp.getNvPicPr().getCNvPr().getId());
CTTimeNodeList root = timing.getTnLst();
// 先找“进入类效果effect
String entrance = findFirstBehavior(root, spId, /*preferEntrance=*/true);
if (entrance != null) return entrance;
// 找不到进入类再找其它类型运动、旋转、缩放、Set 等)
String any = findFirstBehavior(root, spId, /*preferEntrance=*/false);
return any != null ? any : "无动画";
}
// 动画 延迟
public static String getAnimationDelay(Pic sp, CTSlideTiming timing) {
// 获取形状中的ID
if (sp == null) return "无动画";
long spId = sp.getNvPicPr().getCNvPr().getId();
// 获取动画效果
CTTimeNodeList timeNodeList = timing.getTnLst();
for (Object obj : timeNodeList.getParOrSeqOrExcl()) {
if (obj instanceof CTTLTimeNodeParallel) {
CTTLTimeNodeParallel par = (CTTLTimeNodeParallel) obj;
CTTLCommonTimeNodeData node = par.getCTn();
if (node.getChildTnLst().getParOrSeqOrExcl() != null) {
CTTimeNodeList childTimeNodeList = node.getChildTnLst();
for (Object object : childTimeNodeList.getParOrSeqOrExcl()) {
if (object instanceof CTTLTimeNodeSequence) {
CTTLTimeNodeSequence seq = (CTTLTimeNodeSequence) object;
if (seq.getCTn().getStCondLst() != null) {
CTTLTimeConditionList stCondLst = seq.getCTn().getStCondLst();
for (CTTLTimeCondition o : stCondLst.getCond()) {
if (o.getEvt() != null) {
return o.getDelay();
}
}
} else {
CTTimeNodeList seqNodeList = seq.getCTn().getChildTnLst();
for (Object seqObj : seqNodeList.getParOrSeqOrExcl()) {
if (seqObj instanceof CTTLTimeNodeSequence) {
CTTLTimeNodeSequence seqs = (CTTLTimeNodeSequence) seqObj;
if (seqs.getCTn().getStCondLst() != null) {
CTTLTimeConditionList stCondLst = seqs.getCTn().getStCondLst();
for (CTTLTimeCondition o : stCondLst.getCond()) {
if (o.getEvt() != null) {
return o.getDelay();
}
}
} else {
CTTimeNodeList seqNodeLists = seqs.getCTn().getChildTnLst();
for (Object seqObjs : seqNodeLists.getParOrSeqOrExcl()) {
if (seqObjs instanceof CTTLTimeNodeSequence) {
CTTLTimeNodeSequence seqss = (CTTLTimeNodeSequence) seqObjs;
if (seqss.getCTn().getStCondLst() != null) {
CTTLTimeConditionList stCondLst = seqss.getCTn().getStCondLst();
for (CTTLTimeCondition o : stCondLst.getCond()) {
if (o.getEvt() != null) {
return o.getDelay();
}
}
}
}
}
}
} else {
if (seqObj instanceof CTTLTimeNodeParallel) {
CTTLTimeNodeParallel seqs = (CTTLTimeNodeParallel) seqObj;
if (seqs.getCTn().getStCondLst() != null) {
CTTLTimeConditionList stCondLst = seqs.getCTn().getStCondLst();
for (CTTLTimeCondition o : stCondLst.getCond()) {
if (o.getEvt() != null) {
return o.getDelay();
}
}
} else {
CTTimeNodeList seqNodeLists = seqs.getCTn().getChildTnLst();
for (Object seqObjs : seqNodeLists.getParOrSeqOrExcl()) {
if (seqObjs instanceof CTTLTimeNodeSequence) {
CTTLTimeNodeSequence seqss = (CTTLTimeNodeSequence) seqObjs;
if (seqss.getCTn().getStCondLst() != null) {
CTTLTimeConditionList stCondLst = seqss.getCTn().getStCondLst();
for (CTTLTimeCondition o : stCondLst.getCond()) {
if (o.getEvt() != null) {
return o.getDelay();
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
return "";
}
/// 形状动作,鼠标单机-动作
}

View File

@@ -0,0 +1,18 @@
package pc.exam.pp.module.judgement.utils.wps_pptx.pptx4j;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.PresentationMLPackage;
import org.docx4j.openpackaging.parts.PresentationML.SlidePart;
import org.pptx4j.pml.CTSlideTiming;
public class SlideAllSetting {
// 设计 主题模板
public static String getAllSlideTheme( SlidePart slidePart, PresentationMLPackage presentation) throws Docx4JException {
// 获取第一个幻灯片母版(通常主主题在这里)
return "WPS";
}
// 幻灯片切换 切换声音
}

View File

@@ -22,7 +22,7 @@ public class SlideConversion {
XMLSlideShow pptxXml = new XMLSlideShow(inputStream)) {
int index = 0;
String firstId = getStringRandom();
setSlideDataInfo(firstId, "", "幻灯片", "w:p", "", false, dataInfoVOS);
setSlideDataInfo(firstId, "", "幻灯片", "slide", "", false, dataInfoVOS);
for (XSLFSlide slides : pptxXml.getSlides()){
index += 1;
String secondId = getStringRandom();
@@ -30,7 +30,7 @@ public class SlideConversion {
// 第三层
String thirdId = getStringRandom();
int indexCnvPr = 1;
setSlideDataInfo(thirdId, secondId, "幻灯片设置", "slide", String.valueOf(index), true, dataInfoVOS);
setSlideDataInfo(thirdId, secondId, "幻灯片设置", "slideSetting", String.valueOf(index) + "_0", true, dataInfoVOS);
XmlCursor spCursor = slides.getXmlObject().newCursor();
spCursor.selectPath("declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//p:sp");
while (spCursor.toNextSelection()) {
@@ -39,7 +39,7 @@ public class SlideConversion {
if (cNvPrXml.toNextSelection()) {
String name = cNvPrXml.getTextValue();
String fourId = getStringRandom();
setSlideDataInfo(fourId, secondId, "形状"+indexCnvPr+"->"+name, "shape", String.valueOf(indexCnvPr), true, dataInfoVOS);
setSlideDataInfo(fourId, secondId, "形状"+indexCnvPr+"->"+name, "shape", String.valueOf(index) + "_" + String.valueOf(indexCnvPr), true, dataInfoVOS);
indexCnvPr += 1;
}
}

View File

@@ -3,20 +3,15 @@ package pc.exam.pp.module.judgement.utils.wps_pptx.pptx4j;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.OpcPackage;
import org.docx4j.openpackaging.packages.PresentationMLPackage;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.PresentationML.SlidePart;
import org.docx4j.openpackaging.parts.WordprocessingML.NumberingDefinitionsPart;
import org.docx4j.openpackaging.parts.WordprocessingML.StyleDefinitionsPart;
import org.docx4j.wml.P;
import org.pptx4j.pml.CTSlideTiming;
import org.pptx4j.pml.GroupShape;
import org.pptx4j.pml.Pic;
import org.pptx4j.pml.Shape;
import org.springframework.web.multipart.MultipartFile;
import pc.exam.pp.module.judgement.controller.admin.AutoWps.vo.WpsSlideInfoVo;
import pc.exam.pp.module.judgement.utils.wps_pptx.pptx4j.vo.JudgementSlidesVO;
import pc.exam.pp.module.judgement.utils.wps_word.docx4j.paragraph.Paragraphs;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
@@ -26,21 +21,19 @@ import java.util.List;
public class SlideMaster {
public static List<JudgementSlidesVO> slideMaster(List<WpsSlideInfoVo> wpsSlideInfoVos, MultipartFile file) throws IOException, Docx4JException {
File files = new File("E:\\Project\\Exam\\Software\\Temp\\1.pptx");
// File files = new File("E:\\Project\\Exam\\Software\\Temp\\1.pptx");
List<JudgementSlidesVO> judgementSlidesVOS = new ArrayList<>();
// 1、获取想要判断的文件地址文件流
// try (InputStream inputStream = file.getInputStream()) {
try {
try (InputStream inputStream = file.getInputStream()) {
// try {
// 加载 .pptx 文件
PresentationMLPackage ppt =
(PresentationMLPackage) OpcPackage.load(files);
(PresentationMLPackage) OpcPackage.load(inputStream);
// 你可以在这里处理 ppt比如读取文字、页数等
for (WpsSlideInfoVo wpsSlideInfoVo : wpsSlideInfoVos) {
// 幻灯片位置(第几张幻灯片)
String slideIndex = wpsSlideInfoVo.getSlideIndex();
String shapeIndex = wpsSlideInfoVo.getShapeIndex();
// 形状类型 slide 幻灯片设置 shape 形状(不包含图片) shapePic 形状图片 presentation 总幻灯片设置
String type = wpsSlideInfoVo.getType();
String slideIndex = wpsSlideInfoVo.getSlideIndex().split("_")[0];
String shapeIndex = wpsSlideInfoVo.getSlideIndex().split("_")[1];
// 大类名称
String firstName = wpsSlideInfoVo.getFirstName();
// 方法名称
@@ -51,11 +44,13 @@ public class SlideMaster {
String examCode = wpsSlideInfoVo.getExamCode();
// 方式方法
String method = wpsSlideInfoVo.getMethod();
if (type.equals("shape")) {
// 查询幻灯片图片
List<SlidePart> slideParts = ppt.getMainPresentationPart().getSlideParts();
int slideIndexFoFile = 0;
for (SlidePart slidePart : slideParts) {
String content = wpsSlideInfoVo.getSlideIndex() + "@" + firstName + "@" + function + "@" + examName + "@" + examCode + "@" + method;
// 查询幻灯片图片
List<SlidePart> slideParts = ppt.getMainPresentationPart().getSlideParts();
int slideIndexFoFile = 0;
for (SlidePart slidePart : slideParts) {
if (method.equals("shape")) {
// 获取幻灯片内容
slideIndexFoFile++;
if (slideIndex.equals(String.valueOf(slideIndexFoFile))) {
@@ -63,14 +58,12 @@ public class SlideMaster {
// 遍历 shape tree 中的 spshape元素
GroupShape spTree = slidePart.getJaxbElement().getCSld().getSpTree();
CTSlideTiming timing = slidePart.getJaxbElement().getTiming();
List<Object> shapes = spTree.getSpOrGrpSpOrGraphicFrame();
List<Object> shapes = spTree.getSpOrGrpSpOrGraphicFrame();
int shapeIndexFoFile = 0;
for (Object shapeObj : shapes) {
for (Object shapeObj : shapes) {
shapeIndexFoFile++;
if (shapeObj instanceof Shape) {
Shape shape = (Shape) shapeObj;
if (shapeObj instanceof Shape shape) {
if (shapeIndex.equals(String.valueOf(shapeIndexFoFile))) {
// 查询出具体想要查询哪个段落的数据
// 目标对象
ShapePage shapeFunction = new ShapePage();
// 获取参数中类型的定义
@@ -80,13 +73,48 @@ public class SlideMaster {
// 实际参数值
Object[] arguments = {shape, timing};
String value = (String) methodWithArgs.invoke(shapeFunction, arguments);
System.out.println(value);
JudgementSlidesVO judgementSlidesVO = new JudgementSlidesVO();
judgementSlidesVO.setContent(content + "@" + value);
judgementSlidesVO.setContentIn(firstName + examName + value);
judgementSlidesVO.setScoreRate(1);
judgementSlidesVOS.add(judgementSlidesVO);
}
} else if (shapeObj instanceof Pic pic) {
if (shapeIndex.equals(String.valueOf(shapeIndexFoFile))) {
// 目标对象
ShapePic shapePicFunction = new ShapePic();
// 获取参数中类型的定义
Class<?>[] paramTypes = {Pic.class, CTSlideTiming.class};
// 带参数的方法调用示例
Method methodWithArgs = shapePicFunction.getClass().getMethod(function, paramTypes);
// 实际参数值
Object[] arguments = {pic, timing};
String value = (String) methodWithArgs.invoke(shapePicFunction, arguments);
JudgementSlidesVO judgementSlidesVO = new JudgementSlidesVO();
judgementSlidesVO.setContent(content + "@" + value);
judgementSlidesVO.setContentIn(firstName + examName + value);
judgementSlidesVO.setScoreRate(1);
judgementSlidesVOS.add(judgementSlidesVO);
}
}
}
}
}
if (method.equals("slideSetting")) {
SlideSetting slideSettingFunction = new SlideSetting();
Class<?>[] paramTypes = {SlidePart.class, PresentationMLPackage.class};
Method methodWithArgs = slideSettingFunction.getClass().getMethod(function, paramTypes);
Object[] arguments = {slidePart, ppt};
String value = (String) methodWithArgs.invoke(slideSettingFunction, arguments);
JudgementSlidesVO judgementSlidesVO = new JudgementSlidesVO();
judgementSlidesVO.setContent(content + "@" + value);
judgementSlidesVO.setContentIn(firstName + examName + value);
judgementSlidesVO.setScoreRate(1);
judgementSlidesVOS.add(judgementSlidesVO);
}
}
}
} catch (Exception e) {
e.printStackTrace();

View File

@@ -0,0 +1,162 @@
package pc.exam.pp.module.judgement.utils.wps_pptx.pptx4j;
import org.docx4j.dml.CTPositiveSize2D;
import org.docx4j.dml.CTTransform2D;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.PresentationMLPackage;
import org.docx4j.openpackaging.parts.PresentationML.SlideLayoutPart;
import org.docx4j.openpackaging.parts.PresentationML.SlideMasterPart;
import org.docx4j.openpackaging.parts.PresentationML.SlidePart;
import org.pptx4j.pml.CTBackground;
import org.pptx4j.pml.CTBackgroundProperties;
import org.pptx4j.pml.CTSlideTiming;
import org.pptx4j.pml.*;
import org.docx4j.dml.*;
import java.lang.reflect.Method;
import java.util.List;
// 单个幻灯片设置
public class SlideSetting {
// 幻灯片 版式
public static String getSlideLayout(SlidePart slidePart, PresentationMLPackage presentation) throws Docx4JException {
SlideLayoutPart layoutPart = slidePart.getSlideLayoutPart();
if (layoutPart.getContents().getCSld() != null) {
return layoutPart.getContents().getCSld().getName();
}
return "";
}
// 设计 主题模板
public static String getSlideTheme(SlidePart slidePart, PresentationMLPackage presentation) throws Docx4JException {
// 获取第一个幻灯片母版(通常主主题在这里)
return "WPS";
}
// 背景填充 填充方式
public static String getSlideBackground(SlidePart slidePart, PresentationMLPackage presentation) throws Docx4JException {
CTBackground ctBackground = slidePart.getContents().getCSld().getBg();
if (ctBackground != null) {
CTBackgroundProperties ctBackgroundProperties = ctBackground.getBgPr();
return getBackgroundFillType(ctBackgroundProperties);
}
return "";
}
private static String getBackgroundFillType(CTBackgroundProperties bgPr) {
if (bgPr.getSolidFill() != null) return "纯色填充";
if (bgPr.getGradFill() != null) return "渐变填充";
if (bgPr.getBlipFill() != null) return "图片填充";
if (bgPr.getPattFill() != null) return "图案填充";
if (bgPr.getGrpFill() != null) return "组合填充";
if (bgPr.getNoFill() != null) return "无填充";
return "未知填充类型";
}
// 背景填充 纯色填充-颜色
public static String getSlideBackgroundSolidColor(SlidePart slidePart, PresentationMLPackage presentation) throws Docx4JException {
CTBackground ctBackground = slidePart.getContents().getCSld().getBg();
if (ctBackground != null) {
CTBackgroundProperties ctBackgroundProperties = ctBackground.getBgPr();
return getColorValue(ctBackgroundProperties);
}
return "";
}
private static String getColorValue(CTBackgroundProperties solidFill) {
if (solidFill.getSolidFill().getSrgbClr() != null) {
return "RGB颜色: " + solidFill.getSolidFill().getSrgbClr().getVal();
} else if (solidFill.getSolidFill().getSchemeClr() != null) {
return "主题颜色: " + solidFill.getSolidFill().getSchemeClr().getVal();
} else if (solidFill.getSolidFill().getHslClr() != null) {
return "HSL颜色";
} else if (solidFill.getSolidFill().getSysClr() != null) {
return "系统颜色";
} else if (solidFill.getSolidFill().getPrstClr() != null) {
return "预设颜色: " + solidFill.getSolidFill().getPrstClr().getVal();
}
return "未知颜色类型";
}
// 背景填充 隐藏背景图形
public static String getSlideBackgroundHideShape(SlidePart slidePart, PresentationMLPackage presentation) throws Docx4JException {
return "待开发";
}
// 幻灯片切换 切换效果
public static String getSlideTransition(SlidePart slidePart, PresentationMLPackage presentation) throws Docx4JException {
Sld slides = (Sld) slidePart.getJaxbElement();
Sld slide = (Sld) slidePart.getContents();
CTSlideTransition ctSlideTransition = slide.getTransition();
return "";
}
// 幻灯片切换 切换声音
public static String getSlideTransitionSound(SlidePart slidePart, PresentationMLPackage presentation) throws Docx4JException {
Sld slide = (Sld) slidePart.getContents();
CTSlideTransition ctSlideTransition = slide.getTransition();
CTTransitionSoundAction ctTransitionSoundAction = ctSlideTransition.getSndAc();
if (ctTransitionSoundAction != null) {
return ctTransitionSoundAction.getStSnd().getSnd().getName();
}
return "";
}
// 幻灯片切换 切换速度
public static String getSlideTransitionSpeed(SlidePart slidePart, PresentationMLPackage presentation) throws Docx4JException {
Sld slide = (Sld) slidePart.getContents();
CTSlideTransition ctSlideTransition = slide.getTransition();
Long speed = ctSlideTransition.getAdvTm();
if (speed != null) {
return String.valueOf(speed) + "毫秒";
}
return "";
}
// 隐藏幻灯片
public static String getSlideHide(SlidePart slidePart, PresentationMLPackage presentation) throws Docx4JException {
Sld sld = slidePart.getJaxbElement();
if (sld != null) {
return sld.isShow() ? "显示幻灯片" : "隐藏幻灯片";
}
return "";
}
// 页眉页脚 包含→日期和时间
public static String getSlideHeaderFooterDateTime(SlidePart slidePart, PresentationMLPackage presentation) throws Docx4JException {
GroupShape spTree = slidePart.getJaxbElement().getCSld().getSpTree();
List<Object> shapes = spTree.getSpOrGrpSpOrGraphicFrame();
for (Object shapeObj : shapes) {
if (shapeObj instanceof Shape) {
Shape shape = (Shape) shapeObj;
if (shape.getNvSpPr().getCNvPr().getName().equals("日期")) {
return "包含";
}
}
}
return "";
}
// 页眉页脚 包含→幻灯片编号
public static String getSlideHeaderFooterSlideNumber(SlidePart slidePart, PresentationMLPackage presentation) throws Docx4JException {
GroupShape spTree = slidePart.getJaxbElement().getCSld().getSpTree();
List<Object> shapes = spTree.getSpOrGrpSpOrGraphicFrame();
for (Object shapeObj : shapes) {
if (shapeObj instanceof Shape) {
Shape shape = (Shape) shapeObj;
if (shape.getNvSpPr().getCNvPr().getName().equals("编号")) {
return "包含";
}
}
}
return "";
}
// 页眉页脚 包含→页脚
public static String getSlideHeaderFooterFooter(SlidePart slidePart, PresentationMLPackage presentation) throws Docx4JException {
GroupShape spTree = slidePart.getJaxbElement().getCSld().getSpTree();
List<Object> shapes = spTree.getSpOrGrpSpOrGraphicFrame();
for (Object shapeObj : shapes) {
if (shapeObj instanceof Shape) {
Shape shape = (Shape) shapeObj;
if (shape.getNvSpPr().getCNvPr().getName().equals("页脚")) {
return "包含";
}
}
}
return "";
}
}

View File

@@ -98,23 +98,34 @@ public class SlideUtils {
// 常见值solid, dash, dot, dashDot, lgDash, lgDashDot, lgDashDotDot,
// sysDash, sysDot, sysDashDot, sysDashDotDot
switch (v) {
case SOLID: return "solid";
case DASH: return "dash";
case DOT: return "dot";
case DASH_DOT: return "dashDot";
case LG_DASH: return "lgDash";
case LG_DASH_DOT: return "lgDashDot";
case LG_DASH_DOT_DOT:return "lgDashDotDot";
case SYS_DASH: return "sysDash";
case SYS_DOT: return "sysDot";
case SYS_DASH_DOT: return "sysDashDot";
case SYS_DASH_DOT_DOT:return "sysDashDotDot";
default: return v.value(); // 兜底:返回原枚举字符串
case SOLID:
return "solid";
case DASH:
return "dash";
case DOT:
return "dot";
case DASH_DOT:
return "dashDot";
case LG_DASH:
return "lgDash";
case LG_DASH_DOT:
return "lgDashDot";
case LG_DASH_DOT_DOT:
return "lgDashDotDot";
case SYS_DASH:
return "sysDash";
case SYS_DOT:
return "sysDot";
case SYS_DASH_DOT:
return "sysDashDot";
case SYS_DASH_DOT_DOT:
return "sysDashDotDot";
default:
return v.value(); // 兜底:返回原枚举字符串
}
}
/* ——— 内部:拿到 spPr/effectLst/reflection ——— */
public static CTReflectionEffect getReflection(org.pptx4j.pml.Shape shape) {
if (shape == null || shape.getSpPr() == null) return null;
@@ -124,14 +135,24 @@ public class SlideUtils {
// 如遇到效果写在 effectDag可再补充从 spPr.getEffectDag() 解析。
}
public static CTReflectionEffect getReflectionPic(org.pptx4j.pml.Pic shape) {
if (shape == null || shape.getSpPr() == null) return null;
CTShapeProperties spPr = shape.getSpPr();
CTEffectList eff = spPr.getEffectLst();
return (eff != null) ? eff.getReflection() : null;
// 如遇到效果写在 effectDag可再补充从 spPr.getEffectDag() 解析。
}
/* ——— 工具 ——— */
public static double emuToPt(BigInteger emu) {
if (emu == null) return 0.0;
return emu.doubleValue() / 12700.0; // 1 pt = 12700 EMU
}
public static double to100k(BigInteger v, int def) {
return v == null ? def : v.doubleValue();
}
public static String fmt1(double d) {
return new DecimalFormat("#.##").format(d); // 保留 1~2 位,去掉多余 0
}
@@ -141,6 +162,7 @@ public class SlideUtils {
if (val == null || val.length != 3) return "000000";
return String.format("%02X%02X%02X", val[0] & 0xFF, val[1] & 0xFF, val[2] & 0xFF);
}
public static String extractAlpha(java.util.List<CTPositiveFixedPercentage> alphas) {
if (alphas != null && !alphas.isEmpty()) {
double pct = alphas.get(0).getVal() / 1000.0;
@@ -148,10 +170,47 @@ public class SlideUtils {
}
return null;
}
public static int iOr0(BigInteger bi) {
return bi == null ? 0 : bi.intValue();
}
public static String fmt(double d) {
return (Math.round(d * 100.0) / 100.0) + ""; // 保留 2 位小数
}
public static String getShadowLikeDescription(CTReflectionEffect reflection) {
if (reflection == null) return "无阴影效果";
// 1. 判断是否为底部反射(类似阴影)
boolean isBottomReflection =
(reflection.getAlgn().value().equals("b")) ||
(reflection.getSy() < 0);
if (!isBottomReflection) {
return "特殊反射效果";
}
// 2. 生成类似阴影的描述
StringBuilder desc = new StringBuilder("阴影效果-");
// 模糊程度
double blurPt = reflection.getBlurRad() / 12700.0;
if (blurPt > 5) desc.append("强模糊");
else if (blurPt > 2) desc.append("模糊");
else desc.append("清晰");
// 距离/强度
double distance = reflection.getEndPos() / 1000.0;
if (distance > 40) desc.append("-大距离");
else if (distance > 20) desc.append("-中距离");
else desc.append("-小距离");
// 透明度
int alpha = reflection.getStA();
if (alpha < 30000) desc.append("-高透明");
else if (alpha < 60000) desc.append("-半透明");
return desc.toString();
}
}

View File

@@ -14,4 +14,6 @@ public class JudgementSlidesVO {
// 考点名称
private String contentIn;
private int scoreRate;
}