【新增】 ppt考点信息等

This commit is contained in:
dlaren
2025-09-09 23:09:40 +08:00
parent 02eb70d15e
commit 660494cd1c
7 changed files with 405 additions and 38 deletions

View File

@@ -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<Object> objects, List<Object> 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<CTTLTimeAnimateValue> 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());
}
}
}

View File

@@ -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<Object> objects, List<Object> 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<CTTLTimeAnimateValue> 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) {

View File

@@ -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<Object> 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<Object> 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<Object> 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<SlideDataInfoVO> dataInfoVOS) throws Exception {
String type, String index, boolean isTrue, String belongToName, List<SlideDataInfoVO> dataInfoVOS) throws Exception {
SlideDataInfoVO dataInfo = new SlideDataInfoVO();
dataInfo.setId(id);
dataInfo.setParentId(parentId);

View File

@@ -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";

View File

@@ -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<String, String> 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);
}
}

View File

@@ -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)");
}
}

View File

@@ -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; // 未收录则原样
}
}
}