Преглед изворни кода

页面装修数据结构定义

jason пре 1 година
родитељ
комит
6b1d996b66
18 измењених фајлова са 607 додато и 0 уклоњено
  1. 19 0
      sql/mysql/optional/mall.sql
  2. 13 0
      yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/json/JsonUtils.java
  3. 7 0
      yudao-module-mall/yudao-module-promotion-api/pom.xml
  4. 12 0
      yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/decorate/dto/CommonStyle.java
  5. 52 0
      yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/decorate/dto/NavMenuComponent.java
  6. 39 0
      yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/decorate/dto/PageComponentDTO.java
  7. 25 0
      yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/decorate/dto/ProductCategoryComponent.java
  8. 43 0
      yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/decorate/dto/RollingBannerComponent.java
  9. 21 0
      yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/decorate/DecoratePageTypeEnum.java
  10. 54 0
      yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/decorate/PageComponentEnum.java
  11. 38 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/decorate/vo/DecoratePageReqVO.java
  12. 34 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/decorate/vo/DecoratePageRespVO.java
  13. 45 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/decorate/DecoratePageConvert.java
  14. 48 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/decorate/PageDecorateDO.java
  15. 18 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/decorate/PageDecorateMapper.java
  16. 26 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/decorate/DecoratePageService.java
  17. 30 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/decorate/DecoratePageServiceImpl.java
  18. 83 0
      yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/decorate/DecoratePageServiceImplTest.java

+ 19 - 0
sql/mysql/optional/mall.sql

@@ -447,6 +447,25 @@ CREATE TABLE `trade_delivery_express` (
   PRIMARY KEY (`id`) USING BTREE
 ) ENGINE=InnoDB COMMENT='快递公司';
 
+-- ----------------------------
+-- 页面装修表结构
+-- ----------------------------
+DROP TABLE IF EXISTS `promotion_page_decorate`;
+CREATE TABLE `promotion_page_decorate` (
+   `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
+   `type` int  NOT NULL COMMENT '页面类型',
+   `component_code` varchar(64)  NOT NULL COMMENT '组件编码',
+   `component_value` json NOT NULL  COMMENT '组件值:json 格式。包含配置和数据',
+   `status` tinyint NOT NULL DEFAULT 0 COMMENT '状态',
+   `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
+   `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+   `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
+   `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+   `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
+   `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
+   PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB COMMENT='页面装修';
+
 SET FOREIGN_KEY_CHECKS = 1;
 
 BEGIN;

+ 13 - 0
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/json/JsonUtils.java

@@ -14,6 +14,7 @@ import lombok.experimental.UtilityClass;
 import lombok.extern.slf4j.Slf4j;
 
 import java.io.IOException;
+import java.lang.reflect.Type;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -72,6 +73,18 @@ public class JsonUtils {
         }
     }
 
+    public static <T> T parseObject(String text, Type type) {
+        if (StrUtil.isEmpty(text)) {
+            return null;
+        }
+        try {
+            return objectMapper.readValue(text, objectMapper.getTypeFactory().constructType(type));
+        } catch (IOException e) {
+            log.error("json parse err,json:{}", text, e);
+            throw new RuntimeException(e);
+        }
+    }
+
     /**
      * 将字符串解析成指定类型的对象
      * 使用 {@link #parseObject(String, Class)} 时,在@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) 的场景下,

+ 7 - 0
yudao-module-mall/yudao-module-promotion-api/pom.xml

@@ -28,6 +28,13 @@
             <artifactId>spring-boot-starter-validation</artifactId>
             <optional>true</optional>
         </dependency>
+
+        <!-- 工具类中使用了 -->
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <optional>true</optional>
+        </dependency>
     </dependencies>
 
 </project>

+ 12 - 0
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/decorate/dto/CommonStyle.java

@@ -0,0 +1,12 @@
+package cn.iocoder.yudao.module.promotion.api.decorate.dto;
+
+import lombok.Data;
+
+/**
+ * 通用的样式 DTO. 由于每个组件的样式配置可能会不一样。 样式配置暂时没想好如何做。 暂时使用一个通用的DTO, 没有任何属性
+ *
+ * @author jason
+ */
+@Data
+public class CommonStyle {
+}

+ 52 - 0
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/decorate/dto/NavMenuComponent.java

@@ -0,0 +1,52 @@
+package cn.iocoder.yudao.module.promotion.api.decorate.dto;
+
+import lombok.Data;
+
+/**
+ * 导航菜单组件的内容配置,数据结构 定义
+ * 不知道放哪里比较好 // TODO @芋艿 貌似放 api 这里不太合适。有什么建议没有?
+ *
+ * @author jason
+ */
+@Data
+public class NavMenuComponent {
+
+    /**
+     * 导航菜单组件对内容的配置项
+     */
+    @Data
+    public static class Config {
+
+        /**
+         * 是否启用
+         */
+        private Boolean enabled;
+    }
+
+    /**
+     * 导航菜单组件的数据结构
+     */
+    @Data
+    public static class DataStructure {
+        /**
+         * 显示名称
+         */
+        private String name;
+
+        /**
+         * 显示图片
+         */
+        private String img;
+
+        /**
+         * 连接路径
+         */
+        private String path;
+
+        /**
+         * 状态, 是否显示
+         */
+        private Integer status;
+
+    }
+}

+ 39 - 0
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/decorate/dto/PageComponentDTO.java

@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.module.promotion.api.decorate.dto;
+
+import lombok.Data;
+
+/**
+ * 页面组件通用模板结构 DTO
+ * 每个组件都有自己对应的内容配置, 样式配置, 具体数据,和其他组件不同的。但这个三个配置是必须的, 所以定义通用的模板结构
+ * 内容配置, 样式配置, 具体数据的结构 需要每个组件单独定义。
+ * 1. 内容配置 (不包括具体的内容) 例如是否启用,是否显示, 商品分类页的排版方式等
+ * 2. 样式设置,对应 crmeb php 版组件的样式配置。 暂时可能用不。 所以使用通用 CommonStyleDTO,后续可能用上
+ * 3. 具体数据, 有些组件(导航菜单组件)数据是通过装修配置, 需要定制数据。有些组件(如商品分类),数据从接口获取,不需要该项
+ *
+ * @author jason
+ */
+@Data
+public class PageComponentDTO<Config, Style, Content> {
+
+    /**
+     * 组件标题, 每个组件都有的
+     */
+    private String title;
+
+    /**
+     * 组件的内容配置项
+     */
+    private Config config;
+
+    /**
+     * 组件的样式配置
+     */
+    private Style style;
+
+    /**
+     * 组件的具体数据
+     *
+     */
+    private Content data;
+
+}

+ 25 - 0
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/decorate/dto/ProductCategoryComponent.java

@@ -0,0 +1,25 @@
+package cn.iocoder.yudao.module.promotion.api.decorate.dto;
+
+import lombok.Data;
+
+/**
+ * 商品分类组件的内容配置, 无数据结构定义。数据从接口获取
+ *
+ * @author jason
+ */
+public class ProductCategoryComponent {
+
+    /**
+     * 商品分类组件组件的内容配置项
+     */
+    @Data
+    public static class Config {
+
+        /**
+         * 页面风格类型
+         */
+        private Integer layoutStyle;
+
+        // TODO 其它
+    }
+}

+ 43 - 0
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/decorate/dto/RollingBannerComponent.java

@@ -0,0 +1,43 @@
+package cn.iocoder.yudao.module.promotion.api.decorate.dto;
+
+import lombok.Data;
+
+/**
+ * 滚动横幅广告组件的内容配置,数据结构定义
+ *
+ * @author jason
+ */
+public class RollingBannerComponent {
+    /**
+     * 滚动横幅广告组件的内容配置项
+     */
+    @Data
+    public static class Config {
+
+        /**
+         * 是否启用
+         */
+        private Boolean enabled;
+    }
+
+    /**
+     * 导航菜单组件的数据结构
+     */
+    @Data
+    public static class DataStructure {
+        /**
+         * 显示图片
+         */
+        private String img;
+
+        /**
+         * 连接路径
+         */
+        private String path;
+
+        /**
+         * 状态, 是否显示
+         */
+        private Integer status;
+    }
+}

+ 21 - 0
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/decorate/DecoratePageTypeEnum.java

@@ -0,0 +1,21 @@
+package cn.iocoder.yudao.module.promotion.enums.decorate;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 装修页面枚举
+ *
+ * @author jason
+ */
+@AllArgsConstructor
+@Getter
+public enum DecoratePageTypeEnum {
+    INDEX(1, "首页");
+
+    private final Integer type;
+    /**
+     * 名字
+     */
+    private final String name;
+}

+ 54 - 0
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/decorate/PageComponentEnum.java

@@ -0,0 +1,54 @@
+package cn.iocoder.yudao.module.promotion.enums.decorate;
+
+import cn.hutool.core.lang.TypeReference;
+import cn.hutool.core.util.ArrayUtil;
+import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
+import cn.iocoder.yudao.module.promotion.api.decorate.dto.*;
+import lombok.Getter;
+
+import java.lang.reflect.Type;
+import java.util.List;
+
+/**
+ * 页面组件枚举
+ *
+ * @author jason
+ */
+@Getter
+public enum PageComponentEnum {
+    NAV_MENU("nav-menu", "导航菜单",
+            new TypeReference<PageComponentDTO<NavMenuComponent.Config, CommonStyle, List<NavMenuComponent.DataStructure>>>() {}.getType()),
+    ROLLING_BANNER("rolling-banner", "滚动横幅广告",
+            new TypeReference<PageComponentDTO<RollingBannerComponent.Config, CommonStyle, List<RollingBannerComponent.DataStructure>>>() {}.getType()),
+    PRODUCT_CATEGORY("product-category", "商品分类",
+            new TypeReference<PageComponentDTO<ProductCategoryComponent.Config, CommonStyle, Object>>() {}.getType()); // data 会为null 用 object 代替
+
+    /**
+     * 页面组件代码
+     */
+    private final String code;
+
+    /**
+     * 页面组件说明
+     */
+    private final String desc;
+
+    /**
+     * 具体组件的类型
+     */
+    private final Type  componentType;
+
+    PageComponentEnum(String code, String desc, Type componentType) {
+        this.code = code;
+        this.desc = desc;
+        this.componentType = componentType;
+    }
+
+    public static PageComponentEnum getOfCode(String code) {
+        return ArrayUtil.firstMatch(component -> component.getCode().equals(code), PageComponentEnum.values());
+    }
+
+    public <C, S, D> PageComponentDTO<C, S, D> parsePageComponent(String text) {
+        return JsonUtils.parseObject(text, componentType);
+    }
+}

+ 38 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/decorate/vo/DecoratePageReqVO.java

@@ -0,0 +1,38 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.decorate.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+/**
+ * @author jason
+ */
+@Schema(description = "管理后台 - 页面装,整个页面 Request VO ")
+@Data
+public class DecoratePageReqVO {
+    @Schema(description = "页面类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @NotNull(message = "页面类型不能为空")
+    private Integer type;
+    @Schema(description = "页面组件列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "TODO")
+    @NotEmpty(message = "页面组件列表不能为空")
+    @Valid
+    private List<ComponentReqVO> components;
+
+    @Schema(description = "管理后台 - 页面组件 Request VO, 后面是不是可以做分组件保存?? ")
+    @Data
+    public static class ComponentReqVO {
+
+        @Schema(description = "组件编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "nav-menu")
+        @NotEmpty(message = "组件编码不能为空")
+        private String componentCode;
+
+        @Schema(description = "组件对应值, json 字符串, 含内容配置,具体数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "TODO")
+        @NotEmpty(message = "组件值为空")
+        private String value;
+    }
+
+}

+ 34 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/decorate/vo/DecoratePageRespVO.java

@@ -0,0 +1,34 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.decorate.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author jason
+ */
+@Schema(description = "管理后台 - 页面装修 Resp VO")
+@Data
+public class DecoratePageRespVO {
+    @Schema(description = "页面类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    private Integer type;
+    @Schema(description = "页面组件", requiredMode = Schema.RequiredMode.REQUIRED, example = "TODO")
+    private List<ComponentRespVO> components;
+
+    @Schema(description = "管理后台 - 页面组件 Resp VO")
+    @Data
+    public static class ComponentRespVO {
+        @Schema(description = "组件标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "首页广告")
+        private String title;
+        @Schema(description = "组件编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "nav-menu")
+        private String componentCode;
+        @Schema(description = "组件的内容配置项", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "TODO")
+        private Object config;
+        @Schema(description = "组件的样式配置", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "TODO")
+        private Object style;
+        @Schema(description = "组件的具体数据", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "TODO")
+        private Object data;
+    }
+
+}

+ 45 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/decorate/DecoratePageConvert.java

@@ -0,0 +1,45 @@
+package cn.iocoder.yudao.module.promotion.convert.decorate;
+
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.module.promotion.api.decorate.dto.PageComponentDTO;
+import cn.iocoder.yudao.module.promotion.controller.admin.decorate.vo.DecoratePageReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.decorate.vo.DecoratePageRespVO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.decorate.PageDecorateDO;
+import cn.iocoder.yudao.module.promotion.enums.decorate.PageComponentEnum;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+
+@Mapper
+public interface DecoratePageConvert {
+
+    DecoratePageConvert INSTANCE = Mappers.getMapper(DecoratePageConvert.class);
+
+    default List<PageDecorateDO> convert(Integer type, List<DecoratePageReqVO.ComponentReqVO> components) {
+        return CollectionUtils.convertList(components, c -> {
+            PageComponentEnum component = PageComponentEnum.getOfCode(c.getComponentCode());
+            if (component == null) {
+                return null;
+            }
+            return new PageDecorateDO().setComponentCode(c.getComponentCode())
+                    .setType(type).setComponentValue(c.getValue());
+        });
+    }
+
+    default DecoratePageRespVO convert2(Integer type, List<PageDecorateDO> doList) {
+        List<DecoratePageRespVO.ComponentRespVO> components = CollectionUtils.convertList(doList,
+                item -> {
+                    PageComponentEnum component = PageComponentEnum.getOfCode(item.getComponentCode());
+                    if (component == null) {
+                        return null;
+                    }
+                    @SuppressWarnings("rawtypes")
+                    PageComponentDTO dto = component.parsePageComponent(item.getComponentValue());
+                    return new DecoratePageRespVO.ComponentRespVO()
+                            .setTitle(dto.getTitle()).setStyle(dto.getStyle()).setComponentCode(item.getComponentCode())
+                            .setConfig(dto.getConfig()).setData(dto.getData());
+                });
+        return new DecoratePageRespVO().setType(type).setComponents(components);
+    }
+}

+ 48 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/decorate/PageDecorateDO.java

@@ -0,0 +1,48 @@
+package cn.iocoder.yudao.module.promotion.dal.dataobject.decorate;
+
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.module.promotion.enums.decorate.DecoratePageTypeEnum;
+import cn.iocoder.yudao.module.promotion.enums.decorate.PageComponentEnum;
+import com.baomidou.mybatisplus.annotation.*;
+
+import lombok.Data;
+
+/**
+ * 页面装修 DO
+ *
+ * @author jason
+ */
+@TableName(value ="promotion_page_decorate")
+@KeySequence("promotion_page_decorate_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+public class PageDecorateDO extends BaseDO {
+    /**
+     * 编号
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 页面类型
+     * 枚举 {@link DecoratePageTypeEnum#getType()}
+     */
+    private Integer type;
+
+    /**
+     *  组件编码
+     *  枚举 {@link PageComponentEnum#getCode()}
+     */
+    private String componentCode;
+
+    /**
+     * 组件值:json 格式。包含配置和数据
+     */
+    private String componentValue;
+
+    /**
+     * 状态
+     * 枚举 {@link CommonStatusEnum}
+     */
+    private Integer status;
+}

+ 18 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/decorate/PageDecorateMapper.java

@@ -0,0 +1,18 @@
+package cn.iocoder.yudao.module.promotion.dal.mysql.decorate;
+
+import cn.iocoder.yudao.module.promotion.dal.dataobject.decorate.PageDecorateDO;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+@Mapper
+public interface PageDecorateMapper extends BaseMapperX<PageDecorateDO> {
+    default List<PageDecorateDO> selectByPageType(Integer type){
+        return selectList(PageDecorateDO::getType, type);
+    }
+}
+
+
+
+

+ 26 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/decorate/DecoratePageService.java

@@ -0,0 +1,26 @@
+package cn.iocoder.yudao.module.promotion.service.decorate;
+
+import cn.iocoder.yudao.module.promotion.controller.admin.decorate.vo.DecoratePageReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.decorate.vo.DecoratePageRespVO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.decorate.PageDecorateDO;
+
+import java.util.List;
+
+/**
+ * 页面装修 Service 接口
+ *
+ * @author jason
+ */
+public interface DecoratePageService {
+
+    /**
+     * 测试请求
+     */
+    List<PageDecorateDO> testReq(DecoratePageReqVO reqVO);
+
+    /**
+     * 测试响应
+     * @param type 页面类型
+     */
+    DecoratePageRespVO testResp(Integer type);
+}

+ 30 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/decorate/DecoratePageServiceImpl.java

@@ -0,0 +1,30 @@
+package cn.iocoder.yudao.module.promotion.service.decorate;
+
+import cn.iocoder.yudao.module.promotion.controller.admin.decorate.vo.DecoratePageReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.decorate.vo.DecoratePageRespVO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.decorate.PageDecorateDO;
+import cn.iocoder.yudao.module.promotion.dal.mysql.decorate.PageDecorateMapper;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+import static cn.iocoder.yudao.module.promotion.convert.decorate.DecoratePageConvert.INSTANCE;
+
+/**
+ * @author jason
+ */
+@Service
+public class DecoratePageServiceImpl implements DecoratePageService {
+    @Resource
+    private PageDecorateMapper pageDecorateMapper;
+    @Override
+    public List<PageDecorateDO> testReq(DecoratePageReqVO reqVO) {
+        return INSTANCE.convert(reqVO.getType(), reqVO.getComponents());
+    }
+
+    @Override
+    public DecoratePageRespVO testResp(Integer type) {
+        return INSTANCE.convert2(type,pageDecorateMapper.selectByPageType(type));
+    }
+}

+ 83 - 0
yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/decorate/DecoratePageServiceImplTest.java

@@ -0,0 +1,83 @@
+package cn.iocoder.yudao.module.promotion.service.decorate;
+
+import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
+import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
+import cn.iocoder.yudao.module.promotion.api.decorate.dto.CommonStyle;
+import cn.iocoder.yudao.module.promotion.api.decorate.dto.PageComponentDTO;
+import cn.iocoder.yudao.module.promotion.api.decorate.dto.RollingBannerComponent;
+import cn.iocoder.yudao.module.promotion.controller.admin.decorate.vo.DecoratePageReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.decorate.vo.DecoratePageRespVO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.decorate.PageDecorateDO;
+import cn.iocoder.yudao.module.promotion.dal.mysql.decorate.PageDecorateMapper;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.enums.CommonStatusEnum.ENABLE;
+import static cn.iocoder.yudao.module.promotion.enums.decorate.DecoratePageTypeEnum.INDEX;
+import static cn.iocoder.yudao.module.promotion.enums.decorate.PageComponentEnum.ROLLING_BANNER;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.eq;
+
+/**
+ * @author jason
+ */
+public class DecoratePageServiceImplTest extends BaseMockitoUnitTest {
+
+    @InjectMocks
+    private DecoratePageServiceImpl decoratePageService;
+
+    @Mock
+    private PageDecorateMapper pageDecorateMapper;
+
+    private PageComponentDTO<RollingBannerComponent.Config,
+            CommonStyle,
+            List<RollingBannerComponent.DataStructure>> bannerComponent;
+    @BeforeEach
+    public void init(){
+        CommonStyle commonStyle = new CommonStyle();
+        RollingBannerComponent.DataStructure banner1 = new RollingBannerComponent.DataStructure().setImg("http://127.0.0.1:8084/a.jpg")
+                .setPath("/pages/coupon_center/coupon_center")
+                .setStatus(ENABLE.getStatus());
+        List<RollingBannerComponent.DataStructure> banners = new ArrayList<>(1);
+        banners.add(banner1);
+        bannerComponent
+                = new PageComponentDTO<RollingBannerComponent.Config, CommonStyle, List<RollingBannerComponent.DataStructure>>().setTitle("首页横幅广告")
+                .setConfig(new RollingBannerComponent.Config().setEnabled(Boolean.TRUE))
+                .setStyle(commonStyle)
+                .setData(banners);
+    }
+    @Test
+    void testReq() {
+        // 准备请求参数
+        DecoratePageReqVO.ComponentReqVO cReq = new DecoratePageReqVO.ComponentReqVO()
+                .setComponentCode(ROLLING_BANNER.getCode())
+                .setValue(JsonUtils.toJsonString(bannerComponent));
+        List<DecoratePageReqVO.ComponentReqVO> cReqList = new ArrayList<>();
+        cReqList.add(cReq);
+        DecoratePageReqVO reqVO = new DecoratePageReqVO();
+        reqVO.setType(1);
+        reqVO.setComponents(cReqList);
+        System.out.printf("请求数据:%s%n",JsonUtils.toJsonPrettyString(reqVO));
+        List<PageDecorateDO> list = decoratePageService.testReq(reqVO);
+        assertThat(list).hasSize(1);
+    }
+    @Test
+    void testResp(){
+        List<PageDecorateDO> list = new ArrayList<>(1);
+        PageDecorateDO decorateDO = new PageDecorateDO()
+                .setType(INDEX.getType()).setComponentValue(JsonUtils.toJsonString(bannerComponent))
+                .setComponentCode(ROLLING_BANNER.getCode()).setId(1L);
+        list.add(decorateDO);
+        //mock 方法
+        Mockito.when(pageDecorateMapper.selectByPageType(eq(1))).thenReturn(list);
+
+        DecoratePageRespVO respVO = decoratePageService.testResp(1);
+        System.out.printf("响应数据:%s%n",JsonUtils.toJsonPrettyString(respVO));
+    }
+}