You've already forked FrameTour-BE
refactor(puzzle): 重构元素DTO及新增元素基类
- 将ElementCreateRequest和PuzzleElementDTO中的elementType从Integer改为String - 删除所有类型特定字段,新增config和configMap支持JSON配置 - 新增BaseElement抽象基类定义元素通用行为 - 添加ElementConfig接口和具体实现类ImageConfig、TextConfig - 创建ElementFactory工厂类和ElementRegistrar注册器 - 新增ElementType枚举和ElementValidationException异常类 - 实现ImageElement和TextElement具体元素类 - 添加Position位置信息封装类
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
package com.ycwl.basic.puzzle.element;
|
||||
|
||||
import com.ycwl.basic.puzzle.element.base.BaseElement;
|
||||
import com.ycwl.basic.puzzle.element.base.ElementFactory;
|
||||
import com.ycwl.basic.puzzle.element.enums.ElementType;
|
||||
import com.ycwl.basic.puzzle.element.impl.ImageElement;
|
||||
import com.ycwl.basic.puzzle.element.impl.TextElement;
|
||||
import com.ycwl.basic.puzzle.entity.PuzzleElementEntity;
|
||||
import com.ycwl.basic.puzzle.test.PuzzleTestDataBuilder;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* ElementFactory 单元测试
|
||||
*
|
||||
* @author Claude
|
||||
* @since 2025-01-18
|
||||
*/
|
||||
@SpringBootTest
|
||||
class ElementFactoryTest {
|
||||
|
||||
@BeforeAll
|
||||
static void setUp() {
|
||||
// 确保Element已注册(Spring会自动调用ElementRegistrar)
|
||||
ElementFactory.register(ElementType.TEXT, TextElement.class);
|
||||
ElementFactory.register(ElementType.IMAGE, ImageElement.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateTextElement_Success() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = PuzzleTestDataBuilder.createTextElement(
|
||||
1L, "userName", 100, 200, 300, 50, 10,
|
||||
"测试文字", 24, "#333333"
|
||||
);
|
||||
|
||||
// When
|
||||
BaseElement element = ElementFactory.create(entity);
|
||||
|
||||
// Then
|
||||
assertNotNull(element);
|
||||
assertInstanceOf(TextElement.class, element);
|
||||
assertEquals(ElementType.TEXT, element.getElementType());
|
||||
assertEquals("userName", element.getElementKey());
|
||||
assertEquals(100, element.getPosition().getX());
|
||||
assertEquals(200, element.getPosition().getY());
|
||||
assertEquals(300, element.getPosition().getWidth());
|
||||
assertEquals(50, element.getPosition().getHeight());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateImageElement_Success() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = PuzzleTestDataBuilder.createImageElement(
|
||||
1L, "userAvatar", 50, 100, 100, 100, 5,
|
||||
"https://example.com/avatar.jpg"
|
||||
);
|
||||
|
||||
// When
|
||||
BaseElement element = ElementFactory.create(entity);
|
||||
|
||||
// Then
|
||||
assertNotNull(element);
|
||||
assertInstanceOf(ImageElement.class, element);
|
||||
assertEquals(ElementType.IMAGE, element.getElementType());
|
||||
assertEquals("userAvatar", element.getElementKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateElement_InvalidType() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = new PuzzleElementEntity();
|
||||
entity.setElementType("INVALID_TYPE");
|
||||
entity.setElementKey("test");
|
||||
entity.setConfig("{}");
|
||||
|
||||
// When & Then
|
||||
assertThrows(IllegalArgumentException.class, () -> ElementFactory.create(entity));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateElement_NullConfig() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = new PuzzleElementEntity();
|
||||
entity.setElementType("TEXT");
|
||||
entity.setElementKey("test");
|
||||
entity.setConfig(null);
|
||||
entity.setXPosition(0);
|
||||
entity.setYPosition(0);
|
||||
entity.setWidth(100);
|
||||
entity.setHeight(50);
|
||||
|
||||
// When & Then
|
||||
assertThrows(IllegalArgumentException.class, () -> ElementFactory.create(entity));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package com.ycwl.basic.puzzle.element;
|
||||
|
||||
import com.ycwl.basic.puzzle.element.base.BaseElement;
|
||||
import com.ycwl.basic.puzzle.element.base.ElementFactory;
|
||||
import com.ycwl.basic.puzzle.element.exception.ElementValidationException;
|
||||
import com.ycwl.basic.puzzle.element.renderer.RenderContext;
|
||||
import com.ycwl.basic.puzzle.entity.PuzzleElementEntity;
|
||||
import com.ycwl.basic.puzzle.test.PuzzleTestDataBuilder;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* ImageElement 单元测试
|
||||
*
|
||||
* @author Claude
|
||||
* @since 2025-01-18
|
||||
*/
|
||||
class ImageElementTest {
|
||||
|
||||
private Graphics2D graphics;
|
||||
private RenderContext context;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
BufferedImage canvas = new BufferedImage(800, 600, BufferedImage.TYPE_INT_ARGB);
|
||||
graphics = canvas.createGraphics();
|
||||
|
||||
Map<String, String> dynamicData = new HashMap<>();
|
||||
context = new RenderContext(graphics, dynamicData, 800, 600);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testImageElement_Creation_Success() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = PuzzleTestDataBuilder.createImageElement(
|
||||
1L, "userAvatar", 50, 100, 100, 100, 5,
|
||||
"https://example.com/avatar.jpg"
|
||||
);
|
||||
|
||||
// When
|
||||
BaseElement element = ElementFactory.create(entity);
|
||||
|
||||
// Then
|
||||
assertNotNull(element);
|
||||
assertEquals("userAvatar", element.getElementKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testImageElement_RoundedImage_Success() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = PuzzleTestDataBuilder.createRoundedImageElement(
|
||||
1L, "userAvatar", 50, 100, 100, 100, 5,
|
||||
"https://example.com/avatar.jpg", 50
|
||||
);
|
||||
|
||||
// When
|
||||
BaseElement element = ElementFactory.create(entity);
|
||||
|
||||
// Then
|
||||
assertNotNull(element);
|
||||
// 验证配置包含圆角信息
|
||||
String schema = element.getConfigSchema();
|
||||
assertTrue(schema.contains("borderRadius"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testImageElement_InvalidConfig_MissingDefaultImageUrl() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = new PuzzleElementEntity();
|
||||
entity.setElementType("IMAGE");
|
||||
entity.setElementKey("testKey");
|
||||
entity.setConfig("{\"imageFitMode\":\"FILL\"}"); // 缺少 defaultImageUrl
|
||||
entity.setXPosition(0);
|
||||
entity.setYPosition(0);
|
||||
entity.setWidth(100);
|
||||
entity.setHeight(100);
|
||||
|
||||
// When & Then
|
||||
assertThrows(ElementValidationException.class, () -> ElementFactory.create(entity));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testImageElement_InvalidConfig_InvalidBorderRadius() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = new PuzzleElementEntity();
|
||||
entity.setElementType("IMAGE");
|
||||
entity.setElementKey("testKey");
|
||||
entity.setConfig("{\"defaultImageUrl\":\"test.jpg\",\"borderRadius\":-1}"); // 非法圆角
|
||||
entity.setXPosition(0);
|
||||
entity.setYPosition(0);
|
||||
entity.setWidth(100);
|
||||
entity.setHeight(100);
|
||||
|
||||
// When & Then
|
||||
assertThrows(ElementValidationException.class, () -> ElementFactory.create(entity));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testImageElement_GetConfigSchema() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = PuzzleTestDataBuilder.createImageElement(
|
||||
1L, "userAvatar", 50, 100, 100, 100, 5,
|
||||
"https://example.com/avatar.jpg"
|
||||
);
|
||||
|
||||
BaseElement element = ElementFactory.create(entity);
|
||||
|
||||
// When
|
||||
String schema = element.getConfigSchema();
|
||||
|
||||
// Then
|
||||
assertNotNull(schema);
|
||||
assertTrue(schema.contains("defaultImageUrl"));
|
||||
assertTrue(schema.contains("imageFitMode"));
|
||||
assertTrue(schema.contains("borderRadius"));
|
||||
}
|
||||
}
|
||||
107
src/test/java/com/ycwl/basic/puzzle/element/TextElementTest.java
Normal file
107
src/test/java/com/ycwl/basic/puzzle/element/TextElementTest.java
Normal file
@@ -0,0 +1,107 @@
|
||||
package com.ycwl.basic.puzzle.element;
|
||||
|
||||
import com.ycwl.basic.puzzle.element.base.BaseElement;
|
||||
import com.ycwl.basic.puzzle.element.base.ElementFactory;
|
||||
import com.ycwl.basic.puzzle.element.exception.ElementValidationException;
|
||||
import com.ycwl.basic.puzzle.element.renderer.RenderContext;
|
||||
import com.ycwl.basic.puzzle.entity.PuzzleElementEntity;
|
||||
import com.ycwl.basic.puzzle.test.PuzzleTestDataBuilder;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* TextElement 单元测试
|
||||
*
|
||||
* @author Claude
|
||||
* @since 2025-01-18
|
||||
*/
|
||||
class TextElementTest {
|
||||
|
||||
private Graphics2D graphics;
|
||||
private RenderContext context;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
BufferedImage canvas = new BufferedImage(800, 600, BufferedImage.TYPE_INT_ARGB);
|
||||
graphics = canvas.createGraphics();
|
||||
|
||||
Map<String, String> dynamicData = new HashMap<>();
|
||||
context = new RenderContext(graphics, dynamicData, 800, 600);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTextElement_Render_Success() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = PuzzleTestDataBuilder.createTextElement(
|
||||
1L, "userName", 100, 200, 300, 50, 10,
|
||||
"默认文字", 24, "#333333"
|
||||
);
|
||||
|
||||
BaseElement element = ElementFactory.create(entity);
|
||||
|
||||
// 添加动态数据
|
||||
context.getDynamicData().put("userName", "张三");
|
||||
|
||||
// When & Then (不抛出异常即为成功)
|
||||
assertDoesNotThrow(() -> element.render(context));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTextElement_InvalidConfig_MissingDefaultText() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = new PuzzleElementEntity();
|
||||
entity.setElementType("TEXT");
|
||||
entity.setElementKey("testKey");
|
||||
entity.setConfig("{\"fontSize\":14,\"fontColor\":\"#000000\"}"); // 缺少 defaultText
|
||||
entity.setXPosition(0);
|
||||
entity.setYPosition(0);
|
||||
entity.setWidth(100);
|
||||
entity.setHeight(50);
|
||||
|
||||
// When & Then
|
||||
assertThrows(ElementValidationException.class, () -> ElementFactory.create(entity));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTextElement_InvalidConfig_InvalidFontSize() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = new PuzzleElementEntity();
|
||||
entity.setElementType("TEXT");
|
||||
entity.setElementKey("testKey");
|
||||
entity.setConfig("{\"defaultText\":\"test\",\"fontSize\":0,\"fontColor\":\"#000000\"}"); // 非法字号
|
||||
entity.setXPosition(0);
|
||||
entity.setYPosition(0);
|
||||
entity.setWidth(100);
|
||||
entity.setHeight(50);
|
||||
|
||||
// When & Then
|
||||
assertThrows(ElementValidationException.class, () -> ElementFactory.create(entity));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTextElement_GetConfigSchema() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = PuzzleTestDataBuilder.createTextElement(
|
||||
1L, "userName", 100, 200, 300, 50, 10,
|
||||
"测试文字", 24, "#333333"
|
||||
);
|
||||
|
||||
BaseElement element = ElementFactory.create(entity);
|
||||
|
||||
// When
|
||||
String schema = element.getConfigSchema();
|
||||
|
||||
// Then
|
||||
assertNotNull(schema);
|
||||
assertTrue(schema.contains("defaultText"));
|
||||
assertTrue(schema.contains("fontSize"));
|
||||
assertTrue(schema.contains("fontColor"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package com.ycwl.basic.puzzle.integration;
|
||||
|
||||
import com.ycwl.basic.puzzle.element.base.BaseElement;
|
||||
import com.ycwl.basic.puzzle.element.base.ElementFactory;
|
||||
import com.ycwl.basic.puzzle.element.enums.ElementType;
|
||||
import com.ycwl.basic.puzzle.element.impl.ImageElement;
|
||||
import com.ycwl.basic.puzzle.element.impl.TextElement;
|
||||
import com.ycwl.basic.puzzle.entity.PuzzleElementEntity;
|
||||
import com.ycwl.basic.puzzle.test.PuzzleTestDataBuilder;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* Element 调试测试
|
||||
* 用于验证 Element 创建和配置是否正确
|
||||
*/
|
||||
class ElementDebugTest {
|
||||
|
||||
@BeforeAll
|
||||
static void registerElements() {
|
||||
ElementFactory.register(ElementType.TEXT, TextElement.class);
|
||||
ElementFactory.register(ElementType.IMAGE, ImageElement.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateTextElement() {
|
||||
System.out.println("=== 测试创建 TEXT 元素 ===");
|
||||
|
||||
PuzzleElementEntity entity = PuzzleTestDataBuilder.createTextElement(
|
||||
1L, "testText", 100, 200, 300, 50, 10,
|
||||
"测试文字", 24, "#333333"
|
||||
);
|
||||
|
||||
System.out.println("Entity elementType: " + entity.getElementType());
|
||||
System.out.println("Entity config: " + entity.getConfig());
|
||||
|
||||
try {
|
||||
BaseElement element = ElementFactory.create(entity);
|
||||
System.out.println("✅ Element 创建成功");
|
||||
System.out.println("Element type: " + element.getElementType());
|
||||
System.out.println("Element key: " + element.getElementKey());
|
||||
assertNotNull(element);
|
||||
} catch (Exception e) {
|
||||
System.err.println("❌ Element 创建失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
fail("Element 创建失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateImageElement() {
|
||||
System.out.println("\n=== 测试创建 IMAGE 元素 ===");
|
||||
|
||||
PuzzleElementEntity entity = PuzzleTestDataBuilder.createImageElement(
|
||||
1L, "testImage", 50, 100, 100, 100, 5,
|
||||
"https://example.com/test.jpg"
|
||||
);
|
||||
|
||||
System.out.println("Entity elementType: " + entity.getElementType());
|
||||
System.out.println("Entity config: " + entity.getConfig());
|
||||
|
||||
try {
|
||||
BaseElement element = ElementFactory.create(entity);
|
||||
System.out.println("✅ Element 创建成功");
|
||||
System.out.println("Element type: " + element.getElementType());
|
||||
System.out.println("Element key: " + element.getElementKey());
|
||||
assertNotNull(element);
|
||||
} catch (Exception e) {
|
||||
System.err.println("❌ Element 创建失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
fail("Element 创建失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRealScenarioElements() {
|
||||
System.out.println("\n=== 测试现实场景元素创建 ===");
|
||||
|
||||
var elements = PuzzleTestDataBuilder.createRealScenarioElements(1L);
|
||||
System.out.println("元素数量: " + elements.size());
|
||||
|
||||
int successCount = 0;
|
||||
for (PuzzleElementEntity entity : elements) {
|
||||
System.out.println("\n--- 测试元素: " + entity.getElementKey() + " ---");
|
||||
System.out.println("Type: " + entity.getElementType());
|
||||
System.out.println("Config: " + entity.getConfig());
|
||||
|
||||
try {
|
||||
BaseElement element = ElementFactory.create(entity);
|
||||
System.out.println("✅ 创建成功");
|
||||
successCount++;
|
||||
} catch (Exception e) {
|
||||
System.err.println("❌ 创建失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("\n总结: " + successCount + "/" + elements.size() + " 个元素创建成功");
|
||||
assertEquals(elements.size(), successCount, "所有元素都应该创建成功");
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,15 @@
|
||||
package com.ycwl.basic.puzzle.integration;
|
||||
|
||||
import com.ycwl.basic.puzzle.element.enums.ElementType;
|
||||
import com.ycwl.basic.puzzle.entity.PuzzleElementEntity;
|
||||
import com.ycwl.basic.puzzle.entity.PuzzleTemplateEntity;
|
||||
import com.ycwl.basic.puzzle.test.MockImageUtil;
|
||||
import com.ycwl.basic.puzzle.test.PuzzleTestDataBuilder;
|
||||
import com.ycwl.basic.puzzle.util.PuzzleImageRenderer;
|
||||
import org.apache.commons.lang3.Strings;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
@@ -18,6 +22,7 @@ import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
@@ -102,6 +107,18 @@ class PuzzleRealScenarioIntegrationTest {
|
||||
dynamicData.put("qrCode", mockImageFiles.get("qrCode").getAbsolutePath());
|
||||
dynamicData.put("bottomText", "奇遇时光乐园\n2025.11.11");
|
||||
|
||||
// 打印调试信息
|
||||
System.out.println("\n=== 调试信息 ===");
|
||||
System.out.println("元素数量: " + elements.size());
|
||||
for (PuzzleElementEntity element : elements) {
|
||||
System.out.println("元素: " + element.getElementKey() +
|
||||
" | 类型: " + element.getElementType() +
|
||||
" | 配置: " + element.getConfig());
|
||||
}
|
||||
System.out.println("\n动态数据:");
|
||||
dynamicData.forEach((k, v) -> System.out.println(" " + k + " = " + v));
|
||||
System.out.println("=================\n");
|
||||
|
||||
// When: 渲染拼图
|
||||
BufferedImage result = renderer.render(template, elements, dynamicData);
|
||||
|
||||
@@ -192,17 +209,6 @@ class PuzzleRealScenarioIntegrationTest {
|
||||
|
||||
List<PuzzleElementEntity> elements = PuzzleTestDataBuilder.createRealScenarioElements(template.getId());
|
||||
|
||||
// 设置默认图片路径
|
||||
for (PuzzleElementEntity element : elements) {
|
||||
if (element.getElementType() == 1) {
|
||||
// 图片元素使用本地文件
|
||||
String key = element.getElementKey();
|
||||
if (mockImageFiles.containsKey(key)) {
|
||||
element.setDefaultImageUrl(mockImageFiles.get(key).getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// When: 不传动态数据,使用默认值
|
||||
Map<String, String> dynamicData = new HashMap<>();
|
||||
BufferedImage result = renderer.render(template, elements, dynamicData);
|
||||
@@ -297,4 +303,17 @@ class PuzzleRealScenarioIntegrationTest {
|
||||
data.put("bottomText", "测试文字内容");
|
||||
return data;
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
static void registerElements() {
|
||||
// 注册 Element 类型(确保工厂可用)
|
||||
com.ycwl.basic.puzzle.element.base.ElementFactory.register(
|
||||
com.ycwl.basic.puzzle.element.enums.ElementType.TEXT,
|
||||
com.ycwl.basic.puzzle.element.impl.TextElement.class
|
||||
);
|
||||
com.ycwl.basic.puzzle.element.base.ElementFactory.register(
|
||||
com.ycwl.basic.puzzle.element.enums.ElementType.IMAGE,
|
||||
com.ycwl.basic.puzzle.element.impl.ImageElement.class
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ public class PuzzleTestDataBuilder {
|
||||
PuzzleElementEntity element = new PuzzleElementEntity();
|
||||
element.setId(System.currentTimeMillis());
|
||||
element.setTemplateId(templateId);
|
||||
element.setElementType(1); // 图片
|
||||
element.setElementType("IMAGE"); // 修改为字符串类型
|
||||
element.setElementKey(elementKey);
|
||||
element.setElementName(elementKey);
|
||||
element.setXPosition(x);
|
||||
@@ -70,9 +70,11 @@ public class PuzzleTestDataBuilder {
|
||||
element.setZIndex(zIndex);
|
||||
element.setRotation(0);
|
||||
element.setOpacity(100);
|
||||
element.setDefaultImageUrl(imageUrl);
|
||||
element.setImageFitMode("FILL"); // 使用FILL模式确保图片完全填充区域
|
||||
element.setBorderRadius(0);
|
||||
|
||||
// 使用JSON配置
|
||||
String config = String.format("{\"defaultImageUrl\":\"%s\",\"imageFitMode\":\"FILL\",\"borderRadius\":0}", imageUrl);
|
||||
element.setConfig(config);
|
||||
|
||||
element.setCreateTime(new Date());
|
||||
element.setUpdateTime(new Date());
|
||||
element.setDeleted(0);
|
||||
@@ -85,8 +87,28 @@ public class PuzzleTestDataBuilder {
|
||||
public static PuzzleElementEntity createRoundedImageElement(Long templateId, String elementKey,
|
||||
int x, int y, int width, int height,
|
||||
int zIndex, String imageUrl, int borderRadius) {
|
||||
PuzzleElementEntity element = createImageElement(templateId, elementKey, x, y, width, height, zIndex, imageUrl);
|
||||
element.setBorderRadius(borderRadius);
|
||||
PuzzleElementEntity element = new PuzzleElementEntity();
|
||||
element.setId(System.currentTimeMillis());
|
||||
element.setTemplateId(templateId);
|
||||
element.setElementType("IMAGE");
|
||||
element.setElementKey(elementKey);
|
||||
element.setElementName(elementKey);
|
||||
element.setXPosition(x);
|
||||
element.setYPosition(y);
|
||||
element.setWidth(width);
|
||||
element.setHeight(height);
|
||||
element.setZIndex(zIndex);
|
||||
element.setRotation(0);
|
||||
element.setOpacity(100);
|
||||
|
||||
// 使用JSON配置(包含圆角)
|
||||
String config = String.format("{\"defaultImageUrl\":\"%s\",\"imageFitMode\":\"COVER\",\"borderRadius\":%d}",
|
||||
imageUrl, borderRadius);
|
||||
element.setConfig(config);
|
||||
|
||||
element.setCreateTime(new Date());
|
||||
element.setUpdateTime(new Date());
|
||||
element.setDeleted(0);
|
||||
return element;
|
||||
}
|
||||
|
||||
@@ -100,7 +122,7 @@ public class PuzzleTestDataBuilder {
|
||||
PuzzleElementEntity element = new PuzzleElementEntity();
|
||||
element.setId(System.currentTimeMillis());
|
||||
element.setTemplateId(templateId);
|
||||
element.setElementType(2); // 文字
|
||||
element.setElementType("TEXT"); // 修改为字符串类型
|
||||
element.setElementKey(elementKey);
|
||||
element.setElementName(elementKey);
|
||||
element.setXPosition(x);
|
||||
@@ -110,16 +132,15 @@ public class PuzzleTestDataBuilder {
|
||||
element.setZIndex(zIndex);
|
||||
element.setRotation(0);
|
||||
element.setOpacity(100);
|
||||
element.setDefaultText(defaultText);
|
||||
element.setFontFamily("微软雅黑");
|
||||
element.setFontSize(fontSize);
|
||||
element.setFontColor(fontColor);
|
||||
element.setFontWeight("NORMAL");
|
||||
element.setFontStyle("NORMAL");
|
||||
element.setTextAlign("LEFT");
|
||||
element.setLineHeight(BigDecimal.valueOf(1.5));
|
||||
element.setMaxLines(null);
|
||||
element.setTextDecoration("NONE");
|
||||
|
||||
// 使用JSON配置
|
||||
String config = String.format(
|
||||
"{\"defaultText\":\"%s\",\"fontFamily\":\"微软雅黑\",\"fontSize\":%d,\"fontColor\":\"%s\"," +
|
||||
"\"fontWeight\":\"NORMAL\",\"fontStyle\":\"NORMAL\",\"textAlign\":\"LEFT\"," +
|
||||
"\"lineHeight\":1.5,\"textDecoration\":\"NONE\"}",
|
||||
defaultText, fontSize, fontColor);
|
||||
element.setConfig(config);
|
||||
|
||||
element.setCreateTime(new Date());
|
||||
element.setUpdateTime(new Date());
|
||||
element.setDeleted(0);
|
||||
@@ -133,9 +154,31 @@ public class PuzzleTestDataBuilder {
|
||||
int x, int y, int width, int height,
|
||||
int zIndex, String defaultText,
|
||||
int fontSize, String fontColor, String textAlign) {
|
||||
PuzzleElementEntity element = createTextElement(templateId, elementKey, x, y, width, height, zIndex, defaultText, fontSize, fontColor);
|
||||
element.setFontWeight("BOLD");
|
||||
element.setTextAlign(textAlign);
|
||||
PuzzleElementEntity element = new PuzzleElementEntity();
|
||||
element.setId(System.currentTimeMillis());
|
||||
element.setTemplateId(templateId);
|
||||
element.setElementType("TEXT");
|
||||
element.setElementKey(elementKey);
|
||||
element.setElementName(elementKey);
|
||||
element.setXPosition(x);
|
||||
element.setYPosition(y);
|
||||
element.setWidth(width);
|
||||
element.setHeight(height);
|
||||
element.setZIndex(zIndex);
|
||||
element.setRotation(0);
|
||||
element.setOpacity(100);
|
||||
|
||||
// 使用JSON配置(粗体)
|
||||
String config = String.format(
|
||||
"{\"defaultText\":\"%s\",\"fontFamily\":\"微软雅黑\",\"fontSize\":%d,\"fontColor\":\"%s\"," +
|
||||
"\"fontWeight\":\"BOLD\",\"fontStyle\":\"NORMAL\",\"textAlign\":\"%s\"," +
|
||||
"\"lineHeight\":1.5,\"textDecoration\":\"NONE\"}",
|
||||
defaultText, fontSize, fontColor, textAlign);
|
||||
element.setConfig(config);
|
||||
|
||||
element.setCreateTime(new Date());
|
||||
element.setUpdateTime(new Date());
|
||||
element.setDeleted(0);
|
||||
return element;
|
||||
}
|
||||
|
||||
@@ -175,9 +218,9 @@ public class PuzzleTestDataBuilder {
|
||||
public static List<PuzzleElementEntity> createRealScenarioElements(Long templateId) {
|
||||
List<PuzzleElementEntity> elements = new ArrayList<>();
|
||||
|
||||
// 画布总高度1520,每张图片460高度
|
||||
int imageHeight = 460;
|
||||
int bottomHeight = 140; // 剩余高度:1520 - 460*3 = 140
|
||||
// 画布总高度1520,每张图片470高度
|
||||
int imageHeight = 470;
|
||||
int bottomHeight = 110; // 剩余高度:1520 - 470*3 = 110
|
||||
|
||||
// 上方3张图片,每张470高度
|
||||
elements.add(createImageElement(templateId, "image1", 0, 0, 1020, imageHeight, 1,
|
||||
@@ -190,17 +233,50 @@ public class PuzzleTestDataBuilder {
|
||||
"https://example.com/image3.jpg"));
|
||||
|
||||
// 底部区域起始Y坐标
|
||||
int bottomY = imageHeight * 3; // 1380
|
||||
int bottomY = imageHeight * 3; // 1410
|
||||
|
||||
// 底部二维码(左侧,占满底部高度)
|
||||
elements.add(createImageElement(templateId, "qrCode", 20, bottomY + 10, 120, 120, 2,
|
||||
"https://example.com/qrcode.png"));
|
||||
PuzzleElementEntity qrElement = new PuzzleElementEntity();
|
||||
qrElement.setId(System.currentTimeMillis());
|
||||
qrElement.setTemplateId(templateId);
|
||||
qrElement.setElementType("IMAGE");
|
||||
qrElement.setElementKey("qrCode");
|
||||
qrElement.setElementName("qrCode");
|
||||
qrElement.setXPosition(20);
|
||||
qrElement.setYPosition(bottomY + 5);
|
||||
qrElement.setWidth(100);
|
||||
qrElement.setHeight(100);
|
||||
qrElement.setZIndex(2);
|
||||
qrElement.setRotation(0);
|
||||
qrElement.setOpacity(100);
|
||||
qrElement.setConfig("{\"defaultImageUrl\":\"https://example.com/qrcode.png\",\"imageFitMode\":\"CONTAIN\",\"borderRadius\":0}");
|
||||
qrElement.setCreateTime(new Date());
|
||||
qrElement.setUpdateTime(new Date());
|
||||
qrElement.setDeleted(0);
|
||||
elements.add(qrElement);
|
||||
|
||||
// 底部文字(右侧,占满剩余宽度和高度)
|
||||
int textX = 140; // 二维码右侧留20像素间距
|
||||
int textWidth = 1020 - textX - 20; // 右侧留20像素边距
|
||||
elements.add(createBoldTextElement(templateId, "bottomText", textX, bottomY + 20, textWidth, bottomHeight - 20, 2,
|
||||
"扫码查看详情", 18, "#333333", "RIGHT"));
|
||||
|
||||
PuzzleElementEntity textElement = new PuzzleElementEntity();
|
||||
textElement.setId(System.currentTimeMillis() + 1);
|
||||
textElement.setTemplateId(templateId);
|
||||
textElement.setElementType("TEXT");
|
||||
textElement.setElementKey("bottomText");
|
||||
textElement.setElementName("bottomText");
|
||||
textElement.setXPosition(textX);
|
||||
textElement.setYPosition(bottomY + 10);
|
||||
textElement.setWidth(textWidth);
|
||||
textElement.setHeight(bottomHeight - 10);
|
||||
textElement.setZIndex(2);
|
||||
textElement.setRotation(0);
|
||||
textElement.setOpacity(100);
|
||||
textElement.setConfig("{\"defaultText\":\"扫码查看详情\",\"fontFamily\":\"微软雅黑\",\"fontSize\":18,\"fontColor\":\"#333333\",\"fontWeight\":\"BOLD\",\"textAlign\":\"RIGHT\",\"lineHeight\":1.5,\"textDecoration\":\"NONE\"}");
|
||||
textElement.setCreateTime(new Date());
|
||||
textElement.setUpdateTime(new Date());
|
||||
textElement.setDeleted(0);
|
||||
elements.add(textElement);
|
||||
|
||||
return elements;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package com.ycwl.basic.puzzle.test;
|
||||
|
||||
import com.ycwl.basic.puzzle.element.base.ElementFactory;
|
||||
import com.ycwl.basic.puzzle.element.enums.ElementType;
|
||||
import com.ycwl.basic.puzzle.element.impl.ImageElement;
|
||||
import com.ycwl.basic.puzzle.element.impl.TextElement;
|
||||
import com.ycwl.basic.puzzle.entity.PuzzleElementEntity;
|
||||
import com.ycwl.basic.puzzle.entity.PuzzleTemplateEntity;
|
||||
import com.ycwl.basic.puzzle.util.PuzzleImageRenderer;
|
||||
@@ -56,7 +60,7 @@ public class RealScenarioTestHelper {
|
||||
* 创建场景图片(1020x470)
|
||||
*/
|
||||
private void createSceneImage(String key, String text, Color bgColor) throws IOException {
|
||||
BufferedImage image = MockImageUtil.createImageWithText(1020, 460, text, bgColor, Color.BLACK);
|
||||
BufferedImage image = MockImageUtil.createImageWithText(1020, 470, text, bgColor, Color.BLACK);
|
||||
File file = saveImage(image, key + ".jpg");
|
||||
resourceFiles.put(key, file);
|
||||
}
|
||||
@@ -224,6 +228,10 @@ public class RealScenarioTestHelper {
|
||||
* 快速测试方法(主方法,可直接运行)
|
||||
*/
|
||||
public static void main(String[] args) throws IOException {
|
||||
// 【重要】注册 Element 类型(主方法运行必须先注册)
|
||||
ElementFactory.register(ElementType.TEXT, TextElement.class);
|
||||
ElementFactory.register(ElementType.IMAGE, ImageElement.class);
|
||||
|
||||
// 创建临时目录
|
||||
Path tempDir = Files.createTempDirectory("puzzle_test_");
|
||||
System.out.println("📂 测试目录: " + tempDir.toAbsolutePath());
|
||||
|
||||
Reference in New Issue
Block a user