Files
FrameTour-BE/src/main/java/com/ycwl/basic/puzzle/util/ElementConfigHelper.java
Jerry Yan cfb3625ac0 feat(puzzle): 实现智能自动填充引擎和安全增强
- 新增拼图元素自动填充引擎 PuzzleElementFillEngine
- 支持基于规则的条件匹配和数据源解析
- 实现机位数量、机位ID等多维度条件策略
- 添加 DEVICE_IMAGE、USER_AVATAR 等数据源类型支持
- 增加景区隔离校验确保模板使用安全性
- 强化图片下载安全校验,防范 SSRF 攻击
- 支持本地文件路径解析和公网 URL 安全检查
- 完善静态值数据源策略支持 localPath 配置
- 优化生成流程中 faceId 和 scenicId 的校验逻辑
- 补充相关单元测试覆盖核心功能点
2025-11-19 17:28:41 +08:00

163 lines
5.2 KiB
Java

package com.ycwl.basic.puzzle.util;
import cn.hutool.core.util.StrUtil;
import com.ycwl.basic.puzzle.dto.ElementCreateRequest;
import com.ycwl.basic.puzzle.element.enums.ElementType;
import com.ycwl.basic.puzzle.entity.PuzzleElementEntity;
import com.ycwl.basic.utils.JacksonUtil;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
/**
* Element配置辅助类
* 处理ElementCreateRequest到PuzzleElementEntity的转换
* 负责config和configMap之间的序列化/反序列化
*
* @author Claude
* @since 2025-01-18
*/
@Slf4j
public class ElementConfigHelper {
/**
* 将ElementCreateRequest转换为PuzzleElementEntity
*
* @param request 创建请求
* @return Entity对象
*/
public static PuzzleElementEntity toEntity(ElementCreateRequest request) {
PuzzleElementEntity entity = new PuzzleElementEntity();
// 基本属性
entity.setTemplateId(request.getTemplateId());
entity.setElementType(request.getElementType());
entity.setElementKey(request.getElementKey());
entity.setElementName(request.getElementName());
// 位置和布局属性
entity.setXPosition(request.getXPosition());
entity.setYPosition(request.getYPosition());
entity.setWidth(request.getWidth());
entity.setHeight(request.getHeight());
entity.setZIndex(request.getZIndex());
entity.setRotation(request.getRotation());
entity.setOpacity(request.getOpacity());
// 处理配置:优先使用config字符串,否则将configMap序列化为JSON
String configJson = getConfigJson(request);
entity.setConfig(configJson);
return entity;
}
/**
* 从Request获取JSON配置字符串
* 优先级:config字符串 > configMap序列化
*
* @param request 创建请求
* @return JSON配置字符串
*/
public static String getConfigJson(ElementCreateRequest request) {
// 优先使用config字段
if (StrUtil.isNotBlank(request.getConfig())) {
return request.getConfig();
}
// 否则将configMap序列化为JSON
if (request.getConfigMap() != null && !request.getConfigMap().isEmpty()) {
try {
return JacksonUtil.toJson(request.getConfigMap());
} catch (Exception e) {
log.error("configMap序列化为JSON失败", e);
throw new IllegalArgumentException("配置序列化失败: " + e.getMessage());
}
}
// 都为空则返回空JSON对象
return "{}";
}
/**
* 将JSON配置字符串解析为Map
*
* @param configJson JSON配置字符串
* @return Map对象
*/
@SuppressWarnings("unchecked")
public static Map<String, Object> parseConfigToMap(String configJson) {
if (StrUtil.isBlank(configJson)) {
return Map.of();
}
try {
return JacksonUtil.fromJson(configJson, Map.class);
} catch (Exception e) {
log.error("JSON解析为Map失败: {}", configJson, e);
return Map.of();
}
}
/**
* 验证元素类型是否有效
*
* @param elementType 元素类型
* @return true-有效,false-无效
*/
public static boolean isValidElementType(String elementType) {
if (StrUtil.isBlank(elementType)) {
return false;
}
try {
ElementType type = ElementType.fromCode(elementType);
return type.isImplemented();
} catch (IllegalArgumentException ex) {
return false;
}
}
/**
* 验证元素配置是否完整
*
* @param request 创建请求
* @throws IllegalArgumentException 配置不完整时抛出
*/
public static void validateRequest(ElementCreateRequest request) {
if (request.getTemplateId() == null) {
throw new IllegalArgumentException("模板ID不能为空");
}
if (StrUtil.isBlank(request.getElementType())) {
throw new IllegalArgumentException("元素类型不能为空");
}
if (!isValidElementType(request.getElementType())) {
throw new IllegalArgumentException("不支持的元素类型: " + request.getElementType());
}
if (StrUtil.isBlank(request.getElementKey())) {
throw new IllegalArgumentException("元素标识不能为空");
}
// 验证位置属性
if (request.getXPosition() == null || request.getYPosition() == null) {
throw new IllegalArgumentException("位置坐标不能为空");
}
if (request.getWidth() == null || request.getHeight() == null) {
throw new IllegalArgumentException("宽高不能为空");
}
if (request.getWidth() <= 0 || request.getHeight() <= 0) {
throw new IllegalArgumentException("宽高必须大于0");
}
// 验证配置
if (StrUtil.isBlank(request.getConfig()) &&
(request.getConfigMap() == null || request.getConfigMap().isEmpty())) {
throw new IllegalArgumentException("元素配置不能为空(config或configMap至少提供一个)");
}
}
}