From 1c0ba2b8a08373efc13ccfb233b3658bd5f418dd Mon Sep 17 00:00:00 2001 From: dlaren Date: Sun, 17 Aug 2025 19:32:50 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91=20PPTX=20?= =?UTF-8?q?=E5=8A=A8=E7=94=BB=E8=80=83=E7=82=B9=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../utils/wps_pptx/pptx4j/ShapePage.java | 561 ++++-------------- .../utils/wps_pptx/pptx4j/ShapePic.java | 527 +++------------- .../wps_pptx/pptx4j/SlideConversion.java | 71 ++- 3 files changed, 259 insertions(+), 900 deletions(-) diff --git a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/ShapePage.java b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/ShapePage.java index e78aaeec..f192372a 100644 --- a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/ShapePage.java +++ b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/ShapePage.java @@ -7,6 +7,7 @@ import org.docx4j.jaxb.XPathBinderAssociationIsPartialException; import org.pptx4j.pml.*; import java.math.BigInteger; +import java.util.List; public class ShapePage { @@ -79,6 +80,7 @@ public class ShapePage { } return ""; } + /// 替换文字 说明 public static String getShapeText(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { return "待开发"; @@ -266,6 +268,7 @@ public class ShapePage { // 3) 未设置 → 视为实线 return "solid"; } + // 形状线条 开始箭头类型 public static String getShapeLineStartArrow(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { CTShapeProperties spPr = sp.getSpPr(); @@ -277,14 +280,17 @@ public class ShapePage { } return "无箭头"; } + // 形状线条 开始箭头粗细 public static String getShapeLineStartArrowWidth(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { return "待开发"; } + // 形状线条 结尾箭头类型 public static String getShapeLineEndArrow(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { return "待开发"; } + // 形状线条 结尾箭头粗细 public static String getShapeLineEndArrowWidth(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { return "待开发"; @@ -391,14 +397,17 @@ public class ShapePage { CTSoftEdgesEffect se = getSoftEdge(sp); return (se != null) ? String.valueOf(se.getRad()) : null; } + // 形状效果 三维效果→绘制 public static String getShape3DEffectDraw(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { return "待开发"; } + // 形状效果 三维格式→效果 public static String getShape3DEffect(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { return "待开发"; } + // 形状效果 三维旋转→效果 public static String getShape3DRotation(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { return "待开发"; @@ -415,440 +424,46 @@ public class ShapePage { // 动画 效果 -// 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; - } + long spId = sp.getNvSpPr().getCNvPr().getId(); + CTTimeNodeList ctTimeNodeList = timing.getTnLst(); + if (ctTimeNodeList == null) return "无动画"; + // 第一层 + List parOrSeqOrExcl = ctTimeNodeList.getParOrSeqOrExcl(); + String value = getAniationInfo(parOrSeqOrExcl, null, String.valueOf(spId), "type"); + if (!value.isEmpty()) { + return value; } - return null; + return ""; } - - /* 如果对象是某种 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 "位置动画:X(ppt_x)"; - if ("ppt_y".equalsIgnoreCase(attr)) return "位置动画:Y(ppt_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)); + public static String getAniationInfo(List objects, List upObjects, String spId, String parameter) { + for (Object object : objects) { + if (object instanceof CTTLSetBehavior) { + String spIds = ((CTTLSetBehavior) object).getCBhvr().getTgtEl().getSpTgt().getSpid(); + // 判断ID是否一致 + if (spIds.equals(spId)) { + // 持续时间 + if (parameter.equals("dur")) { + return ((CTTLSetBehavior) object).getCBhvr().getCTn().getDur(); } - 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 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(); - // 获取动画效果 - 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(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(); - } - } - } - } - } - } - } + // 向上获取延迟 + for (Object upObject : upObjects) { + if (upObject instanceof CTTLTimeNodeParallel) { + // 获取动画效果 + if (parameter.equals("type")) { + Integer type = ((CTTLTimeNodeParallel) upObject).getCTn().getPresetSubtype(); + return String.valueOf(type); + } + // 触发方式 + if (parameter.equals("function")) { + return ((CTTLTimeNodeParallel) upObject).getCTn().getNodeType().value(); + } + // 获取延迟方法 + for (Object condObject : ((CTTLTimeNodeParallel) upObject).getCTn().getStCondLst().getCond()) { + if (condObject instanceof CTTLTimeCondition) { + // 获取延迟 + if (parameter.equals("delay")) { + return ((CTTLTimeCondition) condObject).getDelay(); } } } @@ -856,10 +471,69 @@ public class ShapePage { } } } + if (object instanceof CTTLTimeNodeParallel obj) { + String result = getAniationInfo(obj.getCTn().getChildTnLst().getParOrSeqOrExcl(), objects, spId, parameter); + if (!result.isEmpty()) { + return result; + } + } + if (object instanceof CTTLTimeNodeSequence obj) { + String result = getAniationInfo(obj.getCTn().getChildTnLst().getParOrSeqOrExcl(), objects, spId, parameter); + if (!result.isEmpty()) { + return result; + } + } + } + + return ""; + } + + // 动画-方向 + public static String getAnimateDirection(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { + return "待开发"; + } + + // 动画 触发方式 + public static String getAnimateTrigger(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { + long spId = sp.getNvSpPr().getCNvPr().getId(); + CTTimeNodeList ctTimeNodeList = timing.getTnLst(); + if (ctTimeNodeList == null) return "无动画"; + // 第一层 + List parOrSeqOrExcl = ctTimeNodeList.getParOrSeqOrExcl(); + String value = getAniationInfo(parOrSeqOrExcl, null, String.valueOf(spId), "function"); + if (!value.isEmpty()) { + return value; } return ""; } + // 动画 持续时间 + public static String getAnimationDuration(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { + long spId = sp.getNvSpPr().getCNvPr().getId(); + CTTimeNodeList ctTimeNodeList = timing.getTnLst(); + if (ctTimeNodeList == null) return "无动画"; + // 第一层 + List parOrSeqOrExcl = ctTimeNodeList.getParOrSeqOrExcl(); + String value = getAniationInfo(parOrSeqOrExcl, null, String.valueOf(spId), "dur"); + if (!value.isEmpty()) { + return value; + } + return ""; + } + + // 动画 延迟 + public static String getAnimationDelay(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { + long spId = sp.getNvSpPr().getCNvPr().getId(); + CTTimeNodeList ctTimeNodeList = timing.getTnLst(); + if (ctTimeNodeList == null) return "无动画"; + // 第一层 + List parOrSeqOrExcl = ctTimeNodeList.getParOrSeqOrExcl(); + String value = getAniationInfo(parOrSeqOrExcl, null, String.valueOf(spId), "delay"); + if (!value.isEmpty()) { + return value; + } + return ""; + } /// 形状动作,鼠标单机-动作 @@ -1223,6 +897,7 @@ public class ShapePage { } return "0"; } + /// 段落 缩进→度量值 public static String getTextBoxParagraphIndentMeasure(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { if (sp.getTxBody() != null) { @@ -1236,6 +911,7 @@ public class ShapePage { } return "0"; } + /// 段落 间距→段前 public static String getTextBoxParagraphSpaceBefore(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { if (sp.getTxBody() != null) { @@ -1249,6 +925,7 @@ public class ShapePage { } return ""; } + /// 段落 间距→段后 public static String getTextBoxParagraphSpaceAfter(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { if (sp.getTxBody() != null) { @@ -1262,6 +939,7 @@ public class ShapePage { } return ""; } + /// 段落 间距→行距→类型 public static String getTextBoxParagraphSpaceLine(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { if (sp.getTxBody() != null) { @@ -1278,6 +956,7 @@ public class ShapePage { } return ""; } + /// 段落 间距→行距→设置值 public static String getTextBoxParagraphSpaceLineValue(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { if (sp.getTxBody() != null) { @@ -1285,7 +964,7 @@ public class ShapePage { // 遍历所有段落 for (CTTextParagraph paragraph : textBody.getP()) { if (paragraph.getPPr().getLnSpc().getSpcPct() != null) { - return paragraph.getPPr().getLnSpc().getSpcPct().getVal() / 100000 + "倍行距"; // EMU 转 pt + return paragraph.getPPr().getLnSpc().getSpcPct().getVal() / 100000 + "倍行距"; // EMU 转 pt } else if (paragraph.getPPr().getLnSpc().getSpcPts() != null) { return paragraph.getPPr().getLnSpc().getSpcPts().getVal() / 10 + "磅固定行距"; // EMU 转 pt } @@ -1294,6 +973,7 @@ public class ShapePage { } return ""; } + /// 段落 项目符号和编号→类型 public static String getTextBoxParagraphSymbol(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { return "待开发"; @@ -1331,6 +1011,7 @@ public class ShapePage { } return ""; } + /// 文本填充 纯色填充→颜色 public static String getTextBoxParagraphFillColor(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { if (sp.getTxBody() != null) { @@ -1355,26 +1036,32 @@ public class ShapePage { } return ""; } + /// 文本填充 渐变填充→效果 public static String getTextBoxParagraphFillGradient(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { return "待开发"; } + /// 文本填充 图片填充→效果 public static String getTextBoxParagraphFillImage(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { return "待开发"; } + /// 文本填充 纹理填充→效果 public static String getTextBoxParagraphFillTexture(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { return "待开发"; } + /// 文本填充 图案填充→效果 public static String getTextBoxParagraphFillPattern(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { return "待开发"; } + /// 文本填充 填充透明度 public static String getTextBoxParagraphFillOpacity(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { return "待开发"; } + /// 文本轮廓 颜色 public static String getTextBoxParagraphOutlineColor(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { if (sp.getTxBody() != null) { @@ -1391,6 +1078,7 @@ public class ShapePage { return ""; } + /// 文本轮廓 透明度 public static String getTextBoxParagraphOutlineOpacity(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { if (sp.getTxBody() != null) { @@ -1404,8 +1092,7 @@ public class ShapePage { int alpha = 0; if (fill.getSrgbClr() != null) { alpha = Integer.parseInt(fill.getSrgbClr().getVal()); - } - else if (fill.getSchemeClr() != null) { + } else if (fill.getSchemeClr() != null) { alpha = fill.getSchemeClr().getVal().ordinal(); } return String.valueOf((100000 - alpha) / 1000.0); @@ -1415,6 +1102,7 @@ public class ShapePage { } return ""; } + /// 文本轮廓 宽度 public static String getTextBoxParagraphOutlineWidth(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { if (sp.getTxBody() != null) { @@ -1434,6 +1122,7 @@ public class ShapePage { } return ""; } + /// 文本轮廓 高度 public static String getTextBoxParagraphOutlineHeight(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { if (sp.getTxBody() != null) { @@ -1453,10 +1142,12 @@ public class ShapePage { } return ""; } + /// 文本轮廓 复合类型 public static String getTextBoxParagraphOutlineType(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { return "待开发"; } + /// 文本轮廓 短划线类型 public static String getTextBoxParagraphOutlineDashType(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { return "待开发"; @@ -1481,6 +1172,7 @@ public class ShapePage { } return ""; } + // 文字效果 阴影→预设 // 文字效果 阴影→效果 public static String getTextBoxParagraphShadowEffect(org.pptx4j.pml.Shape sp, CTSlideTiming timing) { @@ -1525,14 +1217,17 @@ public class ShapePage { } 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 "待开发"; diff --git a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/ShapePic.java b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/ShapePic.java index 199386b5..2b1621f1 100644 --- a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/ShapePic.java +++ b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/ShapePic.java @@ -5,6 +5,7 @@ import org.docx4j.dml.*; import org.pptx4j.pml.*; import java.math.BigInteger; +import java.util.List; public class ShapePic { @@ -409,440 +410,46 @@ public class ShapePic { // 动画 效果 -// 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; - } + long spId = sp.getNvPicPr().getCNvPr().getId(); + CTTimeNodeList ctTimeNodeList = timing.getTnLst(); + if (ctTimeNodeList == null) return "无动画"; + // 第一层 + List parOrSeqOrExcl = ctTimeNodeList.getParOrSeqOrExcl(); + String value = getAniationInfo(parOrSeqOrExcl, null, String.valueOf(spId), "type"); + if (!value.isEmpty()) { + return value; } - return null; + return ""; } - - /* 如果对象是某种 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 "位置动画:X(ppt_x)"; - if ("ppt_y".equalsIgnoreCase(attr)) return "位置动画:Y(ppt_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)); + public static String getAniationInfo(List objects, List upObjects, String spId, String parameter) { + for (Object object : objects) { + if (object instanceof CTTLSetBehavior) { + String spIds = ((CTTLSetBehavior) object).getCBhvr().getTgtEl().getSpTgt().getSpid(); + // 判断ID是否一致 + if (spIds.equals(spId)) { + // 持续时间 + if (parameter.equals("dur")) { + return ((CTTLSetBehavior) object).getCBhvr().getCTn().getDur(); } - 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 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(); - } - } - } - } - } - } - } + // 向上获取延迟 + for (Object upObject : upObjects) { + if (upObject instanceof CTTLTimeNodeParallel) { + // 获取动画效果 + if (parameter.equals("type")) { + Integer type = ((CTTLTimeNodeParallel) upObject).getCTn().getPresetSubtype(); + return String.valueOf(type); + } + // 触发方式 + if (parameter.equals("function")) { + return ((CTTLTimeNodeParallel) upObject).getCTn().getNodeType().value(); + } + // 获取延迟方法 + for (Object condObject : ((CTTLTimeNodeParallel) upObject).getCTn().getStCondLst().getCond()) { + if (condObject instanceof CTTLTimeCondition) { + // 获取延迟 + if (parameter.equals("delay")) { + return ((CTTLTimeCondition) condObject).getDelay(); } } } @@ -850,6 +457,66 @@ public class ShapePic { } } } + if (object instanceof CTTLTimeNodeParallel obj) { + String result = getAniationInfo(obj.getCTn().getChildTnLst().getParOrSeqOrExcl(), objects, spId, parameter); + if (!result.isEmpty()) { + return result; + } + } + if (object instanceof CTTLTimeNodeSequence obj) { + String result = getAniationInfo(obj.getCTn().getChildTnLst().getParOrSeqOrExcl(), objects, spId, parameter); + if (!result.isEmpty()) { + return result; + } + } + } + + return ""; + } + + // 动画-方向 + public static String getAnimateDirection(org.pptx4j.pml.Pic sp, CTSlideTiming timing) { + return "待开发"; + } + + // 动画 触发方式 + public static String getAnimateTrigger(org.pptx4j.pml.Pic sp, CTSlideTiming timing) { + long spId = sp.getNvPicPr().getCNvPr().getId(); + CTTimeNodeList ctTimeNodeList = timing.getTnLst(); + if (ctTimeNodeList == null) return "无动画"; + // 第一层 + List parOrSeqOrExcl = ctTimeNodeList.getParOrSeqOrExcl(); + String value = getAniationInfo(parOrSeqOrExcl, null, String.valueOf(spId), "function"); + if (!value.isEmpty()) { + return value; + } + return ""; + } + + // 动画 持续时间 + public static String getAnimationDuration(org.pptx4j.pml.Pic sp, CTSlideTiming timing) { + long spId = sp.getNvPicPr().getCNvPr().getId(); + CTTimeNodeList ctTimeNodeList = timing.getTnLst(); + if (ctTimeNodeList == null) return "无动画"; + // 第一层 + List parOrSeqOrExcl = ctTimeNodeList.getParOrSeqOrExcl(); + String value = getAniationInfo(parOrSeqOrExcl, null, String.valueOf(spId), "dur"); + if (!value.isEmpty()) { + return value; + } + return ""; + } + + // 动画 延迟 + public static String getAnimationDelay(org.pptx4j.pml.Pic sp, CTSlideTiming timing) { + long spId = sp.getNvPicPr().getCNvPr().getId(); + CTTimeNodeList ctTimeNodeList = timing.getTnLst(); + if (ctTimeNodeList == null) return "无动画"; + // 第一层 + List parOrSeqOrExcl = ctTimeNodeList.getParOrSeqOrExcl(); + String value = getAniationInfo(parOrSeqOrExcl, null, String.valueOf(spId), "delay"); + if (!value.isEmpty()) { + return value; } return ""; } diff --git a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/SlideConversion.java b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/SlideConversion.java index b383638c..8eb2bcda 100644 --- a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/SlideConversion.java +++ b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/SlideConversion.java @@ -3,6 +3,13 @@ package pc.exam.pp.module.judgement.utils.wps_pptx.pptx4j; import org.apache.poi.xslf.usermodel.XMLSlideShow; import org.apache.poi.xslf.usermodel.XSLFSlide; import org.apache.xmlbeans.XmlCursor; +import org.docx4j.openpackaging.packages.OpcPackage; +import org.docx4j.openpackaging.packages.PresentationMLPackage; +import org.docx4j.openpackaging.parts.PresentationML.SlidePart; +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.utils.wps_pptx.pptx4j.vo.SlideDataInfoVO; @@ -18,52 +25,42 @@ public class SlideConversion { // 3、获取第三层目录 幻灯片设置/形状 - 幻灯片母版 - 幻灯片设置 - 文件操作 public static List SlideDataInfos(MultipartFile file) throws Exception { List dataInfoVOS = new ArrayList<>(); - try (InputStream inputStream = file.getInputStream(); - XMLSlideShow pptxXml = new XMLSlideShow(inputStream)) { - int index = 0; + + try (InputStream inputStream = file.getInputStream()) { + PresentationMLPackage ppt = + (PresentationMLPackage) OpcPackage.load(inputStream); + // 获取页数 + List slideParts = ppt.getMainPresentationPart().getSlideParts(); + int slideIndexFoFile = 0; String firstId = getStringRandom(); setSlideDataInfo(firstId, "", "幻灯片", "slide", "", false, dataInfoVOS); - for (XSLFSlide slides : pptxXml.getSlides()){ - index += 1; + for (SlidePart slidePart : slideParts) { + slideIndexFoFile ++; String secondId = getStringRandom(); - setSlideDataInfo(secondId, firstId, "第"+index+"页", "sld", String.valueOf(index), true, dataInfoVOS); + setSlideDataInfo(secondId, firstId, "第"+slideIndexFoFile+"页", "sld", String.valueOf(slideIndexFoFile), true, dataInfoVOS); + // 获取形状 + GroupShape spTree = slidePart.getJaxbElement().getCSld().getSpTree(); + List shapes = spTree.getSpOrGrpSpOrGraphicFrame(); + int slideIndexFoShape = 0; // 第三层 String thirdId = getStringRandom(); - int indexCnvPr = 1; - 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()) { - XmlCursor cNvPrXml = spCursor.newCursor(); - cNvPrXml.selectPath("declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//p:cNvPr/@name"); - if (cNvPrXml.toNextSelection()) { - String name = cNvPrXml.getTextValue(); - String fourId = getStringRandom(); - setSlideDataInfo(fourId, secondId, "形状"+indexCnvPr+"->"+name, "shape", String.valueOf(index) + "_" + String.valueOf(indexCnvPr), true, dataInfoVOS); - indexCnvPr += 1; - } - } - XmlCursor picCursor = slides.getXmlObject().newCursor(); - System.out.println(picCursor.xmlText()); - picCursor.selectPath("declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//p:pic"); - int indexCnvPrPic = 1; - while (picCursor.toNextSelection()) { + setSlideDataInfo(thirdId, secondId, "幻灯片设置", "slideSetting", String.valueOf(slideIndexFoFile) + "_0", true, dataInfoVOS); + for (Object shapeObj : shapes) { + slideIndexFoShape ++; + // 形状 String fourId = getStringRandom(); - setSlideDataInfo(fourId, secondId, "图像"+indexCnvPrPic+"->图像", "shapePic", String.valueOf(indexCnvPrPic), true, dataInfoVOS); - indexCnvPrPic += 1; + if (shapeObj instanceof Shape) { + setSlideDataInfo(fourId, secondId, "形状"+slideIndexFoShape+"->"+((Shape) shapeObj).getNvSpPr().getCNvPr().getName(), "shape", String.valueOf(slideIndexFoFile) + "_" + String.valueOf(slideIndexFoShape), true, dataInfoVOS); + } + if (shapeObj instanceof Pic) { + setSlideDataInfo(fourId, secondId, "形状"+slideIndexFoShape+"->"+((Pic) shapeObj).getNvPicPr().getCNvPr().getName(), "shape", String.valueOf(slideIndexFoFile) + "_" + String.valueOf(slideIndexFoShape), true, dataInfoVOS); + } + + } } - // 设置 - String firstIds = getStringRandom(); - setSlideDataInfo(firstIds, "", "设置", "presentation", String.valueOf(0), false, dataInfoVOS); - String secondIds = getStringRandom(); - setSlideDataInfo(secondIds, firstIds, "幻灯片设置", "presentation", String.valueOf(0), true, dataInfoVOS); - - // 母版 -// String dFirstId = getStringRandom(); -// setPptxInfo("母版", "p:sld", "p:sld", filePath, dFirstId, "0", pptxInfoReqVos); } catch (Exception e) { - throw new RuntimeException(e); + e.printStackTrace(); } return dataInfoVOS; }