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 9953b005..c3ac175b 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 @@ -5,12 +5,14 @@ import jakarta.xml.bind.JAXBException; import org.docx4j.dml.*; import org.docx4j.jaxb.XPathBinderAssociationIsPartialException; import org.pptx4j.pml.*; +import pc.exam.pp.module.judgement.utils.wps_pptx.pptx4j.utils.HexColorUtils; import pc.exam.pp.module.judgement.utils.wps_pptx.pptx4j.utils.PtToCmConverter; import pc.exam.pp.module.judgement.utils.wps_pptx.pptx4j.utils.PtToEmuConverter; import pc.exam.pp.module.judgement.utils.wps_pptx.pptx4j.utils.Transition; import java.math.BigInteger; import java.util.List; +import java.util.regex.Pattern; public class ShapePage { @@ -453,6 +455,7 @@ public class ShapePage { } return ""; } + public static String getAniationInfo(List objects, List upObjects, String spId, String parameter) { boolean isDur = false; boolean isDirection = false; @@ -466,7 +469,34 @@ public class ShapePage { // 判断方向 if (isDirection) { if (object instanceof CTTLAnimateEffectBehavior) { - return ((CTTLAnimateEffectBehavior) object).getFilter(); + return Transition.effectWithDirToChinese(((CTTLAnimateEffectBehavior) object).getFilter()); + } else { + // 获取行动轨迹 + for (Object ob : objects) { + if (ob instanceof CTTLAnimateBehavior) { + List cttlTimeAnimateValues = ((CTTLAnimateBehavior) ob).getTavLst().getTav(); + for (CTTLTimeAnimateValue cttlTimeAnimateValue : cttlTimeAnimateValues) { + String value = cttlTimeAnimateValue.getVal().getStrVal().getVal(); + if (cttlTimeAnimateValue.getVal().getStrVal().getVal().contains("0-#ppt_h/") || + cttlTimeAnimateValue.getVal().getStrVal().getVal().contains("-#ppt_h")) { + return "自顶部"; + } + if (cttlTimeAnimateValue.getVal().getStrVal().getVal().contains("#ppt_h+") || + cttlTimeAnimateValue.getVal().getStrVal().getVal().contains("+#ppt_h")) { + return "自底部"; + } + if (cttlTimeAnimateValue.getVal().getStrVal().getVal().contains("+#ppt_w") || + cttlTimeAnimateValue.getVal().getStrVal().getVal().contains("#ppt_w+")) { + return "自右侧"; + } + if (cttlTimeAnimateValue.getVal().getStrVal().getVal().contains("0-#ppt_w/") || + cttlTimeAnimateValue.getVal().getStrVal().getVal().contains("-#ppt_w") || + cttlTimeAnimateValue.getVal().getStrVal().getVal().contains("-N")) { + return "自左侧"; + } + } + } + } } } if (object instanceof CTTLSetBehavior) { @@ -828,7 +858,7 @@ public class ShapePage { // 遍历段落中的所有文本运行 Object obj = paragraph.getEGTextRun().get(0); if (obj instanceof CTRegularTextRun ctRegularTextRun) { - return ctRegularTextRun.getRPr().getSolidFill().getSrgbClr().getVal(); + return HexColorUtils.hexToColorString(ctRegularTextRun.getRPr().getSolidFill().getSrgbClr().getVal()); } } } 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 cd9534f7..59595a4b 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 @@ -11,6 +11,37 @@ import java.util.List; public class ShapePic { + // 图片 插入 + public static String getAddPic(Pic sp, CTSlideTiming timing) { + return "是"; + } + + // 自选图形 - 类型 + public static String getShapeType(Pic sp, CTSlideTiming timing) { + CTShapeProperties ctShapeProperties = sp.getSpPr(); + CTPresetGeometry2D prst = ctShapeProperties.getPrstGeom(); + if (prst != null && prst.getPrst() != null) { + STShapeType t = prst.getPrst(); + switch (t) { + case HEXAGON: return "六边形"; + case RECT: return "矩形"; + case ROUND_RECT: return "圆角矩形"; + case ELLIPSE: return "椭圆"; + case TRIANGLE: return "三角形"; + case DIAMOND: return "菱形"; + case PARALLELOGRAM: return "平行四边形"; + case TRAPEZOID: return "梯形"; + case OCTAGON: return "八边形"; + case PENTAGON: return "五边形"; + default: return "预设形状:" + t.value(); + } + } + if (ctShapeProperties.getCustGeom() != null) { + return "自定义几何(custGeom)"; + } + return "未指定几何"; + } + // 大小 - 高度 public static String getShapeSizeHeight(Pic sp, CTSlideTiming timing) { CTTransform2D xfrm = sp.getSpPr().getXfrm(); @@ -258,6 +289,7 @@ public class ShapePic { // 3) 未设置 → 视为实线 return "solid"; } + // 形状线条 开始箭头类型 public static String getShapeLineStartArrow(Pic sp, CTSlideTiming timing) { CTShapeProperties spPr = sp.getSpPr(); @@ -269,14 +301,17 @@ public class ShapePic { } 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 "待开发"; @@ -349,12 +384,12 @@ public class ShapePic { } else if (coverage >= 0.45) { coverageLabel = "半倒影"; } else { - coverageLabel = "短倒影"; + coverageLabel = "紧密倒影"; } - // —— 2) 偏移描述:dist EMU -> pt;<1pt 视作“紧贴”,否则 "Xpt 偏移" —— // + // —— 2) 偏移描述:dist EMU -> pt;<1pt 视作“接触”,否则 "Xpt 偏移" —— // double distPt = emuToPt(r.getDist()); // 可能为 0 - String offsetLabel = distPt < 1.0 ? "紧贴" : (SlideUtils.fmt1(distPt) + "pt 偏移"); + String offsetLabel = distPt < 1.0 ? "接触" : (SlideUtils.fmt1(distPt) + "pt 偏移"); return coverageLabel + " " + offsetLabel; } @@ -383,14 +418,17 @@ public class ShapePic { 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 "待开发"; @@ -425,6 +463,7 @@ public class ShapePic { } return ""; } + public static String getAniationInfo(List objects, List upObjects, String spId, String parameter) { boolean isDur = false; boolean isDirection = false; @@ -438,7 +477,33 @@ public class ShapePic { // 判断方向 if (isDirection) { if (object instanceof CTTLAnimateEffectBehavior) { - return ((CTTLAnimateEffectBehavior) object).getFilter(); + return Transition.effectWithDirToChinese(((CTTLAnimateEffectBehavior) object).getFilter()); + } else { + // 获取行动轨迹 + for (Object ob : objects) { + if (ob instanceof CTTLAnimateBehavior) { + List cttlTimeAnimateValues = ((CTTLAnimateBehavior) ob).getTavLst().getTav(); + for (CTTLTimeAnimateValue cttlTimeAnimateValue : cttlTimeAnimateValues) { + if (cttlTimeAnimateValue.getVal().getStrVal().getVal().contains("0-#ppt_h/") || + cttlTimeAnimateValue.getVal().getStrVal().getVal().contains("-#ppt_h")) { + return "自顶部"; + } + if (cttlTimeAnimateValue.getVal().getStrVal().getVal().contains("#ppt_h+") || + cttlTimeAnimateValue.getVal().getStrVal().getVal().contains("+#ppt_h")) { + return "自底部"; + } + if (cttlTimeAnimateValue.getVal().getStrVal().getVal().contains("+#ppt_w") || + cttlTimeAnimateValue.getVal().getStrVal().getVal().contains("#ppt_w+")) { + return "自右侧"; + } + if (cttlTimeAnimateValue.getVal().getStrVal().getVal().contains("0-#ppt_w/") || + cttlTimeAnimateValue.getVal().getStrVal().getVal().contains("-#ppt_w") || + cttlTimeAnimateValue.getVal().getStrVal().getVal().contains("-N")) { + return "自左侧"; + } + } + } + } } } if (object instanceof CTTLSetBehavior) { 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 e25ab7b1..278c6fdd 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 @@ -1,12 +1,10 @@ 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.NotesMasterPart; +import org.docx4j.openpackaging.parts.PresentationML.SlideMasterPart; 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; @@ -35,25 +33,27 @@ public class SlideConversion { String firstId = getStringRandom(); setSlideDataInfo(firstId, "", "幻灯片", "slide", "", false, "", dataInfoVOS); for (SlidePart slidePart : slideParts) { - slideIndexFoFile ++; + // 第三层 String secondId = getStringRandom(); - setSlideDataInfo(secondId, firstId, "第"+slideIndexFoFile+"页", "sld", String.valueOf(slideIndexFoFile), false, "", dataInfoVOS); + String thirdSettingId = getStringRandom(); + String thirdId = getStringRandom(); + slideIndexFoFile++; + setSlideDataInfo(secondId, firstId, "第" + slideIndexFoFile + "页", "sld", String.valueOf(slideIndexFoFile), false, "", dataInfoVOS); + setSlideDataInfo(thirdSettingId, secondId, "幻灯片设置", "slideSetting", String.valueOf(slideIndexFoFile) + "_0", true, "第" + slideIndexFoFile + "页", dataInfoVOS); + setSlideDataInfo(thirdId, secondId, "形状", "shapeMaster", "", false, "", dataInfoVOS); // 获取形状 GroupShape spTree = slidePart.getJaxbElement().getCSld().getSpTree(); List shapes = spTree.getSpOrGrpSpOrGraphicFrame(); int slideIndexFoShape = 0; - // 第三层 - String thirdId = getStringRandom(); - setSlideDataInfo(thirdId, secondId, "幻灯片设置", "slideSetting", String.valueOf(slideIndexFoFile) + "_0", true, "第"+slideIndexFoFile+"页", dataInfoVOS); for (Object shapeObj : shapes) { - slideIndexFoShape ++; + slideIndexFoShape++; // 形状 String fourId = getStringRandom(); if (shapeObj instanceof Shape) { - setSlideDataInfo(fourId, secondId, "形状"+slideIndexFoShape+"->"+((Shape) shapeObj).getNvSpPr().getCNvPr().getName(), "shape", String.valueOf(slideIndexFoFile) + "_" + String.valueOf(slideIndexFoShape), true, "第"+slideIndexFoFile+"页", dataInfoVOS); + setSlideDataInfo(fourId, thirdId, "形状" + slideIndexFoShape + "->" + ((Shape) shapeObj).getNvSpPr().getCNvPr().getName(), "shape", String.valueOf(slideIndexFoFile) + "_" + String.valueOf(slideIndexFoShape), true, "第" + slideIndexFoFile + "页", dataInfoVOS); } if (shapeObj instanceof Pic) { - setSlideDataInfo(fourId, secondId, "形状"+slideIndexFoShape+"->"+((Pic) shapeObj).getNvPicPr().getCNvPr().getName(), "shape", String.valueOf(slideIndexFoFile) + "_" + String.valueOf(slideIndexFoShape), true, "第"+slideIndexFoFile+"页", dataInfoVOS); + setSlideDataInfo(fourId, thirdId, "形状" + slideIndexFoShape + "->" + ((Pic) shapeObj).getNvPicPr().getCNvPr().getName(), "shape", String.valueOf(slideIndexFoFile) + "_" + String.valueOf(slideIndexFoShape), true, "第" + slideIndexFoFile + "页", dataInfoVOS); } } } @@ -62,7 +62,61 @@ public class SlideConversion { String secondSetId = getStringRandom(); setSlideDataInfo(firstSetId, "", "设置", "slideAllSetting", "", false, "", dataInfoVOS); setSlideDataInfo(secondSetId, firstSetId, "幻灯片设置", "slideAllSetting", "0_0", true, "设置", dataInfoVOS); - + // 幻灯片母版 + String firstModelId = getStringRandom(); + String secondModelId = getStringRandom(); + SlideMasterPart slideMasterPart = SlideMasterUtils.getSlideMaster(ppt); + setSlideDataInfo(firstModelId, "", "母版", "slideModel", "", false, "", dataInfoVOS); + // 获取母版的形状 + if (slideMasterPart != null) { + setSlideDataInfo(secondModelId, firstModelId, "幻灯片母版", "shapeMaster", "", false, "", dataInfoVOS); + List masterShapeList = slideMasterPart.getJaxbElement().getCSld().getSpTree().getSpOrGrpSpOrGraphicFrame(); + int slideIndexForModel = 0; + String thirdModelId = getStringRandom(); + String thirdModelSettingId = getStringRandom(); + for (Object shapeObj : masterShapeList) { + String fourModelId = getStringRandom(); + if (slideIndexForModel == 0) { + setSlideDataInfo(thirdModelSettingId, secondModelId, "幻灯片设置", "shapeMaster", "", true, "", dataInfoVOS); + setSlideDataInfo(thirdModelId, secondModelId, "形状", "shapeMaster", "", false, "", dataInfoVOS); + } + slideIndexForModel++; + if (shapeObj instanceof Shape) { + String valueName = ((Shape) shapeObj).getNvSpPr().getCNvPr().getName(); + setSlideDataInfo(fourModelId, thirdModelId, "形状" + slideIndexForModel + "->" + valueName, "slideModel", "0_" + String.valueOf(slideIndexForModel), true, "第" + slideIndexForModel + "页", dataInfoVOS); + } + if (shapeObj instanceof Pic) { + String valueName = ((Pic) shapeObj).getNvPicPr().getCNvPr().getName(); + setSlideDataInfo(fourModelId, thirdModelId, "形状" + slideIndexForModel + "->" + valueName, "slideModel", "0_" + String.valueOf(slideIndexForModel), true, "第" + slideIndexForModel + "页", dataInfoVOS); + } + } + } + String secondModelNodeId = getStringRandom(); + // 备注母版 + NotesMasterPart notesMasterPart = SlideMasterUtils.getNotesMaster(ppt); + if (notesMasterPart != null) { + setSlideDataInfo(secondModelNodeId, firstModelId, "备注母版", "shapeNotesMaster", "", false, "", dataInfoVOS); + List masterShapeList = notesMasterPart.getJaxbElement().getCSld().getSpTree().getSpOrGrpSpOrGraphicFrame(); + int slideIndexForModel = 0; + String thirdModelId = getStringRandom(); + String thirdModelSettingId = getStringRandom(); + for (Object shapeObj : masterShapeList) { + String fourModelId = getStringRandom(); + if (slideIndexForModel == 0) { + setSlideDataInfo(thirdModelSettingId, secondModelNodeId, "幻灯片设置", "shapeNotesMaster", "", true, "", dataInfoVOS); + setSlideDataInfo(thirdModelId, secondModelNodeId, "形状", "shapeNotesMaster", "", false, "", dataInfoVOS); + } + slideIndexForModel++; + if (shapeObj instanceof Shape) { + String valueName = ((Shape) shapeObj).getNvSpPr().getCNvPr().getName(); + setSlideDataInfo(fourModelId, thirdModelId, "形状" + slideIndexForModel + "->" + valueName, "shapeNotesMaster", "0_" + String.valueOf(slideIndexForModel), true, "第" + slideIndexForModel + "页", dataInfoVOS); + } + if (shapeObj instanceof Pic) { + String valueName = ((Pic) shapeObj).getNvPicPr().getCNvPr().getName(); + setSlideDataInfo(fourModelId, thirdModelId, "形状" + slideIndexForModel + "->" + valueName, "shapeNotesMaster", "0_" + String.valueOf(slideIndexForModel), true, "第" + slideIndexForModel + "页", dataInfoVOS); + } + } + } } catch (Exception e) { e.printStackTrace(); } @@ -85,7 +139,7 @@ public class SlideConversion { // 想数组中添加数据 public static void setSlideDataInfo(String id, String parentId, String text, - String type, String index, boolean isTrue, String belongToName, List dataInfoVOS) throws Exception { + String type, String index, boolean isTrue, String belongToName, List dataInfoVOS) throws Exception { SlideDataInfoVO dataInfo = new SlideDataInfoVO(); dataInfo.setId(id); dataInfo.setParentId(parentId); diff --git a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/SlideMasterUtils.java b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/SlideMasterUtils.java index 742a7fb1..58880ac1 100644 --- a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/SlideMasterUtils.java +++ b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/SlideMasterUtils.java @@ -6,13 +6,12 @@ import org.docx4j.openpackaging.packages.PresentationMLPackage; import org.docx4j.openpackaging.parts.JaxbXmlPart; import org.docx4j.openpackaging.parts.Part; import org.docx4j.openpackaging.parts.PresentationML.MainPresentationPart; +import org.docx4j.openpackaging.parts.PresentationML.NotesMasterPart; import org.docx4j.openpackaging.parts.PresentationML.SlideMasterPart; import org.docx4j.openpackaging.parts.relationships.RelationshipsPart; import org.docx4j.relationships.Relationship; import org.pptx4j.jaxb.Context; -import org.pptx4j.pml.CTBackground; -import org.pptx4j.pml.Presentation; -import org.pptx4j.pml.PresentationPr; +import org.pptx4j.pml.*; import java.util.Map; @@ -58,6 +57,42 @@ public class SlideMasterUtils { return null; } + + + /** + * 获取备注母版 NotesMasterPart(若文件未显式定义备注母版则返回 null) + */ + public static NotesMasterPart getNotesMaster(PresentationMLPackage ppt) { + // 2. 获取 Presentation 对象 + MainPresentationPart mpp = ppt.getMainPresentationPart(); + Presentation pres = (Presentation) mpp.getJaxbElement(); + RelationshipsPart rels = ppt.getMainPresentationPart().getRelationshipsPart(); + // 获取母版ID + CTNotesMasterIdList idList = pres.getNotesMasterIdLst(); + CTNotesMasterIdListEntry smId = idList.getNotesMasterId(); + String rId = null; + try { + rId = smId.getId(); // 新一点的模型常见 + } catch (Throwable ignore) { + } + if (rId == null) { + try { + // 某些版本字段名为 id2(即 r:id) + rId = (String) CTNotesMasterIdList.class.getMethod("getId2").invoke(smId); + } catch (Throwable ignore) { + } + } + Relationship rel = rels.getRelationshipByID(rId); + // 再通过关系拿到具体的 Part + Part part = rels.getPart(rel); + if (part instanceof NotesMasterPart) { + NotesMasterPart notes = (NotesMasterPart) part; + return notes; + } + return null; + } + + // /ppt/presProps.xml 的关系类型 private static final String REL_TYPE_PRES_PROPS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/presProps"; diff --git a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/utils/HexColorUtils.java b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/utils/HexColorUtils.java new file mode 100644 index 00000000..1abbd99e --- /dev/null +++ b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/utils/HexColorUtils.java @@ -0,0 +1,116 @@ +package pc.exam.pp.module.judgement.utils.wps_pptx.pptx4j.utils; + +import java.awt.Color; +import java.util.HashMap; +import java.util.Map; + +public class HexColorUtils { + + // 常见颜色映射表(可按需扩展) + private static final Map COLOR_NAME_MAP = new HashMap<>(); + + static { + // -------------------- 基础色 -------------------- + COLOR_NAME_MAP.put("#000000", "黑色"); + COLOR_NAME_MAP.put("#FFFFFF", "白色"); + COLOR_NAME_MAP.put("#FF0000", "红色"); + COLOR_NAME_MAP.put("#00FF00", "亮绿色"); + COLOR_NAME_MAP.put("#0000FF", "蓝色"); + COLOR_NAME_MAP.put("#FFFF00", "黄色"); + COLOR_NAME_MAP.put("#00FFFF", "青色"); + COLOR_NAME_MAP.put("#FF00FF", "洋红色"); + + // -------------------- Office 常见标准色 -------------------- + COLOR_NAME_MAP.put("#0070C0", "蓝色"); + COLOR_NAME_MAP.put("#00B050", "绿色"); + COLOR_NAME_MAP.put("#7030A0", "紫罗兰色"); + COLOR_NAME_MAP.put("#C00000", "深红色"); + COLOR_NAME_MAP.put("#FFC000", "橙黄色"); + + // -------------------- 灰阶 -------------------- + COLOR_NAME_MAP.put("#808080", "灰色"); + COLOR_NAME_MAP.put("#C0C0C0", "银色"); + COLOR_NAME_MAP.put("#A9A9A9", "深灰色"); + COLOR_NAME_MAP.put("#D3D3D3", "浅灰色"); + COLOR_NAME_MAP.put("#F5F5F5", "白烟色"); + + // -------------------- 常见网页颜色 -------------------- + COLOR_NAME_MAP.put("#800000", "栗色"); + COLOR_NAME_MAP.put("#808000", "橄榄色"); + COLOR_NAME_MAP.put("#800080", "紫色"); + COLOR_NAME_MAP.put("#008080", "水鸭色"); + COLOR_NAME_MAP.put("#FFA500", "橙色"); + COLOR_NAME_MAP.put("#A52A2A", "棕色"); + COLOR_NAME_MAP.put("#F5F5DC", "米色"); + COLOR_NAME_MAP.put("#FFC0CB", "粉红色"); + COLOR_NAME_MAP.put("#ADD8E6", "浅蓝色"); + COLOR_NAME_MAP.put("#90EE90", "浅绿色"); + COLOR_NAME_MAP.put("#FFD700", "金色"); + COLOR_NAME_MAP.put("#FA8072", "鲑鱼色"); + COLOR_NAME_MAP.put("#FF4500", "橙红色"); + COLOR_NAME_MAP.put("#4682B4", "钢蓝色"); + COLOR_NAME_MAP.put("#2E8B57", "海绿色"); + COLOR_NAME_MAP.put("#B22222", "耐火砖红"); + COLOR_NAME_MAP.put("#6B8E23", "橄榄褐色"); + COLOR_NAME_MAP.put("#DAA520", "秋麒麟色"); + COLOR_NAME_MAP.put("#5F9EA0", "军服蓝"); + COLOR_NAME_MAP.put("#D2691E", "巧克力色"); + + // -------------------- WPS/Excel 扩展色 -------------------- + COLOR_NAME_MAP.put("#1F497D", "深蓝色"); + COLOR_NAME_MAP.put("#4F81BD", "中蓝色"); + COLOR_NAME_MAP.put("#9BBB59", "草绿色"); + COLOR_NAME_MAP.put("#8064A2", "紫罗兰色"); + COLOR_NAME_MAP.put("#F79646", "杏橙色"); + COLOR_NAME_MAP.put("#C0504D", "砖红色"); + + COLOR_NAME_MAP.put("#31869B", "蓝绿色"); + COLOR_NAME_MAP.put("#E46C0A", "深橙色"); + COLOR_NAME_MAP.put("#77933C", "苔藓绿"); + COLOR_NAME_MAP.put("#963634", "褐红色"); + COLOR_NAME_MAP.put("#4BACC6", "湖蓝色"); + COLOR_NAME_MAP.put("#604A7B", "深紫色"); + + // -------------------- 柔和色调 -------------------- + COLOR_NAME_MAP.put("#B6DDE8", "浅湖蓝色"); + COLOR_NAME_MAP.put("#E6B8B7", "浅褐红色"); + COLOR_NAME_MAP.put("#D8E4BC", "浅草绿色"); + COLOR_NAME_MAP.put("#CCC0DA", "浅紫色"); + COLOR_NAME_MAP.put("#F2DCDB", "浅玫瑰色"); + COLOR_NAME_MAP.put("#B8CCE4", "浅蓝灰色"); + } + + /** + * 把十六进制颜色转成 "颜色名 RGB(r,g,b)" 格式的字符串 + * @param hex 十六进制颜色,例如 "00B050" 或 "#00B050" + * @return 格式化后的字符串 + */ + public static String hexToColorString(String hex) { + if (hex == null || hex.isEmpty()) { + return "无效颜色"; + } + + // 去掉 # 前缀 + if (hex.startsWith("#")) { + hex = hex.substring(1); + } + + // 转换为 Color + Color color = new Color(Integer.parseInt(hex, 16)); + int r = color.getRed(); + int g = color.getGreen(); + int b = color.getBlue(); + + // 转回统一的十六进制形式(大写,带 #) + String hexKey = String.format("#%02X%02X%02X", r, g, b); + + // 查找颜色名 + String name = COLOR_NAME_MAP.getOrDefault(hexKey, "未知颜色"); + + return String.format("%s RGB(%d,%d,%d)", name, r, g, b); + } + + + +} + diff --git a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/utils/PtToCmConverter.java b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/utils/PtToCmConverter.java index 0198872b..c8a0a323 100644 --- a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/utils/PtToCmConverter.java +++ b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/utils/PtToCmConverter.java @@ -24,19 +24,4 @@ public class PtToCmConverter { public static double cmToPoints(double cm) { return cm / PT_TO_CM; } - - public static void main(String[] args) { - // 示例转换 - double points = 10.0; - double cm = pointsToCm(points); - - System.out.println(points + " pt = " + cm + " cm"); - System.out.println("反向转换: " + cm + " cm = " + cmToPoints(cm) + " pt"); - - // 常见值的转换示例 - System.out.println("\n常见值转换:"); - System.out.println("8 pt = " + pointsToCm(8) + " cm"); - System.out.println("12 pt = " + pointsToCm(12) + " cm"); - System.out.println("72 pt = " + pointsToCm(72) + " cm (1 inch)"); - } } \ No newline at end of file diff --git a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/utils/Transition.java b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/utils/Transition.java index 4de906e2..943eaea2 100644 --- a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/utils/Transition.java +++ b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_pptx/pptx4j/utils/Transition.java @@ -1,6 +1,13 @@ package pc.exam.pp.module.judgement.utils.wps_pptx.pptx4j.utils; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.regex.*; + public class Transition { + + private static final Pattern P = Pattern.compile("\\(([^)]+)\\)"); public static String getCnName(String fileName) { if (fileName == null) return "未知"; @@ -121,4 +128,79 @@ public class Transition { default: return ""; } } + + public static String getDirection(String spec) { + if (spec == null) return null; + Matcher m = P.matcher(spec); + return m.find() ? m.group(1).trim() : null; + } + + /** + * 将方向英文/短码汉化;可直接传入诸如 "downRight"、"rd"、"rightDown"、"vert"、"in" 等。 + * @param raw 方向原始字符串(不区分大小写,允许下划线/中横线/驼峰) + * @return 对应的中文(若无法识别,原样返回) + */ + public static String toChinese(String raw) { + if (raw == null || raw.isEmpty()) return raw; + String s = normalize(raw); + + switch (s) { + // 单向 + case "l": case "left": return "向左"; + case "r": case "right": return "向右"; + case "u": case "up": return "向上"; + case "d": case "down": return "向下"; + + // 斜向 + case "lu": case "upleft": case "leftup": return "左上"; + case "ru": case "upright": case "rightup": return "右上"; + case "ld": case "downleft": case "leftdown": return "左下"; + case "rd": case "downright": case "rightdown": return "右下"; + + // 其他常见关键字 + case "vert": case "vertical": return "垂直"; + case "horz": case "horizontal": return "水平"; + case "in": return "向内"; + case "out": return "向外"; + + default: + return raw; // 不识别则原样返回,避免误判 + } + } + + /** 归一化:去空格/分隔符、转小写、转驼峰组合为连续词 */ + private static String normalize(String s) { + s = s.trim().toLowerCase(Locale.ROOT); + s = s.replaceAll("[_\\-\\s]", ""); // 去掉下划线/中横线/空格 + return s; + } + + /** 示例:把效果+方向组合成人类可读中文,比如 "strips(downRight)" → "条纹(右下)" */ + public static String effectWithDirToChinese(String dir) { + return toChinese(getDirection(dir)); + } + + /** 常见效果英文→中文(可按需扩展) */ + public static String effectToChinese(String effect) { + if (effect == null) return "效果"; + String e = effect.trim().toLowerCase(Locale.ROOT); + switch (e) { + case "strips": return "条纹"; + case "blinds": return "百叶窗"; + case "wipe": return "擦除"; + case "push": return "推出"; + case "split": return "分割"; + case "checkerboard":return "棋盘格"; + case "cover": return "覆盖"; + case "uncover": return "揭开"; + case "randombars": return "随机条"; + case "shape": return "形状"; + case "circle": return "圆形"; + case "diamond": return "菱形"; + case "plus": return "十字形"; + case "fade": return "淡入"; + case "appear": return "出现"; + default: return effect; // 未收录则原样 + } + } }