浏览代码

店铺装修相关代码(开发中)

zyy 1 周之前
父节点
当前提交
f5658683f3
共有 24 个文件被更改,包括 1083 次插入0 次删除
  1. 70 0
      fs-admin/src/main/java/com/fs/decoration/controller/DecorationComponentController.java
  2. 28 0
      fs-admin/src/main/java/com/fs/decoration/controller/DecorationComponentTypeController.java
  3. 53 0
      fs-admin/src/main/java/com/fs/decoration/controller/DecorationTemplateController.java
  4. 41 0
      fs-service/src/main/java/com/fs/decoration/domain/DecorationComponent.java
  5. 32 0
      fs-service/src/main/java/com/fs/decoration/domain/DecorationComponentType.java
  6. 38 0
      fs-service/src/main/java/com/fs/decoration/domain/DecorationTemplate.java
  7. 19 0
      fs-service/src/main/java/com/fs/decoration/dto/DecorationComponentQuery.java
  8. 34 0
      fs-service/src/main/java/com/fs/decoration/dto/DecorationComponentSaveReq.java
  9. 16 0
      fs-service/src/main/java/com/fs/decoration/dto/DecorationComponentStatusReq.java
  10. 31 0
      fs-service/src/main/java/com/fs/decoration/dto/DecorationTemplateSaveReq.java
  11. 43 0
      fs-service/src/main/java/com/fs/decoration/mapper/DecorationComponentMapper.java
  12. 15 0
      fs-service/src/main/java/com/fs/decoration/mapper/DecorationComponentTypeMapper.java
  13. 37 0
      fs-service/src/main/java/com/fs/decoration/mapper/DecorationTemplateMapper.java
  14. 38 0
      fs-service/src/main/java/com/fs/decoration/service/IDecorationComponentService.java
  15. 16 0
      fs-service/src/main/java/com/fs/decoration/service/IDecorationComponentTypeService.java
  16. 32 0
      fs-service/src/main/java/com/fs/decoration/service/IDecorationTemplateService.java
  17. 117 0
      fs-service/src/main/java/com/fs/decoration/service/impl/DecorationComponentServiceImpl.java
  18. 29 0
      fs-service/src/main/java/com/fs/decoration/service/impl/DecorationComponentTypeServiceImpl.java
  19. 95 0
      fs-service/src/main/java/com/fs/decoration/service/impl/DecorationTemplateServiceImpl.java
  20. 18 0
      fs-service/src/main/java/com/fs/decoration/vo/OptionVO.java
  21. 37 0
      fs-service/src/main/java/com/fs/decoration/vo/TemplateContentVO.java
  22. 123 0
      fs-service/src/main/resources/mapper/decoration/DecorationComponentMapper.xml
  23. 31 0
      fs-service/src/main/resources/mapper/decoration/DecorationComponentTypeMapper.xml
  24. 90 0
      fs-service/src/main/resources/mapper/decoration/DecorationTemplateMapper.xml

+ 70 - 0
fs-admin/src/main/java/com/fs/decoration/controller/DecorationComponentController.java

@@ -0,0 +1,70 @@
+package com.fs.decoration.controller;
+
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.decoration.dto.DecorationComponentQuery;
+import com.fs.decoration.dto.DecorationComponentSaveReq;
+import com.fs.decoration.dto.DecorationComponentStatusReq;
+import com.fs.decoration.service.IDecorationComponentService;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+
+/**
+ * 组件定义控制器
+ */
+@RestController
+@RequestMapping("/decoration/component")
+public class DecorationComponentController {
+
+    @Resource
+    private IDecorationComponentService decorationComponentService;
+
+    /**
+     * 查询组件列表
+     */
+    @GetMapping("/list")
+    public AjaxResult list(DecorationComponentQuery query) {
+        return AjaxResult.success(decorationComponentService.selectList(query));
+    }
+
+    /**
+     * 查询组件详情
+     */
+    @GetMapping("/{id}")
+    public AjaxResult getInfo(@PathVariable Long id) {
+        return AjaxResult.success(decorationComponentService.selectById(id));
+    }
+
+    /**
+     * 新增/修改组件
+     */
+    @PostMapping("/save")
+    public AjaxResult save(@RequestBody DecorationComponentSaveReq req) {
+        Long id = decorationComponentService.saveComponent(req);
+        return AjaxResult.success("保存成功", id);
+    }
+
+    /**
+     * 删除组件
+     */
+    @DeleteMapping("/{id}")
+    public AjaxResult remove(@PathVariable Long id) {
+        decorationComponentService.deleteById(id);
+        return AjaxResult.success("删除成功");
+    }
+
+    /**
+     * 修改组件状态
+     */
+    @PostMapping("/changeStatus")
+    public AjaxResult changeStatus(@RequestBody DecorationComponentStatusReq req) {
+        if (req.getId() == null) {
+            return AjaxResult.error("组件ID不能为空");
+        }
+        if (req.getStatus() == null) {
+            return AjaxResult.error("状态不能为空");
+        }
+        decorationComponentService.updateStatus(req.getId(), req.getStatus());
+        return AjaxResult.success("状态修改成功");
+    }
+}

+ 28 - 0
fs-admin/src/main/java/com/fs/decoration/controller/DecorationComponentTypeController.java

@@ -0,0 +1,28 @@
+package com.fs.decoration.controller;
+
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.decoration.service.IDecorationComponentTypeService;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+/**
+ * 组件类型控制器
+ */
+@RestController
+@RequestMapping("/decoration/componentType")
+public class DecorationComponentTypeController {
+
+    @Resource
+    private IDecorationComponentTypeService decorationComponentTypeService;
+
+    /**
+     * 查询组件类型下拉
+     */
+    @GetMapping("/options")
+    public AjaxResult options() {
+        return AjaxResult.success(decorationComponentTypeService.listOptions());
+    }
+}

+ 53 - 0
fs-admin/src/main/java/com/fs/decoration/controller/DecorationTemplateController.java

@@ -0,0 +1,53 @@
+package com.fs.decoration.controller;
+
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.decoration.dto.DecorationTemplateSaveReq;
+import com.fs.decoration.service.IDecorationTemplateService;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+
+/**
+ * 模板控制器
+ */
+@RestController
+@RequestMapping("/decoration/template")
+public class DecorationTemplateController {
+
+    @Resource
+    private IDecorationTemplateService decorationTemplateService;
+
+    /**
+     * 查询模板列表
+     */
+    @GetMapping("/list")
+    public AjaxResult list() {
+        return AjaxResult.success(decorationTemplateService.selectList());
+    }
+
+    /**
+     * 查询模板详情
+     */
+    @GetMapping("/{id}")
+    public AjaxResult getInfo(@PathVariable Long id) {
+        return AjaxResult.success(decorationTemplateService.selectById(id));
+    }
+
+    /**
+     * 新增/修改模板
+     */
+    @PostMapping("/save")
+    public AjaxResult save(@RequestBody DecorationTemplateSaveReq req) {
+        Long id = decorationTemplateService.saveTemplate(req);
+        return AjaxResult.success("保存成功", id);
+    }
+
+    /**
+     * 删除模板
+     */
+    @DeleteMapping("/{id}")
+    public AjaxResult remove(@PathVariable Long id) {
+        decorationTemplateService.deleteById(id);
+        return AjaxResult.success("删除成功");
+    }
+}

+ 41 - 0
fs-service/src/main/java/com/fs/decoration/domain/DecorationComponent.java

@@ -0,0 +1,41 @@
+package com.fs.decoration.domain;
+
+import lombok.Data;
+import java.util.Date;
+
+/**
+ * 组件定义实体
+ */
+@Data
+public class DecorationComponent {
+
+    /** 主键ID */
+    private Long id;
+
+    /** 组件编码,例如 banner、goodsList */
+    private String componentCode;
+
+    /** 组件名称,例如 顶部轮播 */
+    private String componentName;
+
+    /** 组件类型编码,例如 basic、goods */
+    private String componentTypeCode;
+
+    /** 图标 */
+    private String icon;
+
+    /** 缩略图 */
+    private String previewImage;
+
+    /** 状态:1启用,0停用 */
+    private Integer status;
+
+    /** 备注 */
+    private String remark;
+
+    /** 创建时间 */
+    private Date createTime;
+
+    /** 更新时间 */
+    private Date updateTime;
+}

+ 32 - 0
fs-service/src/main/java/com/fs/decoration/domain/DecorationComponentType.java

@@ -0,0 +1,32 @@
+package com.fs.decoration.domain;
+
+import lombok.Data;
+import java.util.Date;
+
+/**
+ * 组件类型实体
+ */
+@Data
+public class DecorationComponentType {
+
+    /** 主键ID */
+    private Long id;
+
+    /** 类型编码,例如 basic */
+    private String typeCode;
+
+    /** 类型名称,例如 基础组件 */
+    private String typeName;
+
+    /** 状态:1启用,0停用 */
+    private Integer status;
+
+    /** 备注 */
+    private String remark;
+
+    /** 创建时间 */
+    private Date createTime;
+
+    /** 更新时间 */
+    private Date updateTime;
+}

+ 38 - 0
fs-service/src/main/java/com/fs/decoration/domain/DecorationTemplate.java

@@ -0,0 +1,38 @@
+package com.fs.decoration.domain;
+
+import lombok.Data;
+import java.util.Date;
+
+/**
+ * 模板实体
+ */
+@Data
+public class DecorationTemplate {
+
+    /** 主键ID */
+    private Long id;
+
+    /** 模板名称 */
+    private String templateName;
+
+    /** 模板类型 */
+    private String templateType;
+
+    /** 模板封面 */
+    private String coverUrl;
+
+    /** 模板JSON */
+    private String templateData;
+
+    /** 状态:1启用,0停用 */
+    private Integer status;
+
+    /** 备注 */
+    private String remark;
+
+    /** 创建时间 */
+    private Date createTime;
+
+    /** 更新时间 */
+    private Date updateTime;
+}

+ 19 - 0
fs-service/src/main/java/com/fs/decoration/dto/DecorationComponentQuery.java

@@ -0,0 +1,19 @@
+package com.fs.decoration.dto;
+
+import lombok.Data;
+
+/**
+ * 组件查询参数
+ */
+@Data
+public class DecorationComponentQuery {
+
+    /** 组件名称,模糊查询 */
+    private String componentName;
+
+    /** 组件类型编码 */
+    private String componentTypeCode;
+
+    /** 状态 */
+    private Integer status;
+}

+ 34 - 0
fs-service/src/main/java/com/fs/decoration/dto/DecorationComponentSaveReq.java

@@ -0,0 +1,34 @@
+package com.fs.decoration.dto;
+
+import lombok.Data;
+
+/**
+ * 组件新增/修改参数
+ */
+@Data
+public class DecorationComponentSaveReq {
+
+    /** 主键ID,新增时为空 */
+    private Long id;
+
+    /** 组件编码 */
+    private String componentCode;
+
+    /** 组件名称 */
+    private String componentName;
+
+    /** 组件类型编码 */
+    private String componentTypeCode;
+
+    /** 图标 */
+    private String icon;
+
+    /** 缩略图 */
+    private String previewImage;
+
+    /** 状态 */
+    private Integer status;
+
+    /** 备注 */
+    private String remark;
+}

+ 16 - 0
fs-service/src/main/java/com/fs/decoration/dto/DecorationComponentStatusReq.java

@@ -0,0 +1,16 @@
+package com.fs.decoration.dto;
+
+import lombok.Data;
+
+/**
+ * 组件状态修改参数
+ */
+@Data
+public class DecorationComponentStatusReq {
+
+    /** 组件ID */
+    private Long id;
+
+    /** 状态:1启用,0停用 */
+    private Integer status;
+}

+ 31 - 0
fs-service/src/main/java/com/fs/decoration/dto/DecorationTemplateSaveReq.java

@@ -0,0 +1,31 @@
+package com.fs.decoration.dto;
+
+import lombok.Data;
+
+/**
+ * 模板保存参数
+ */
+@Data
+public class DecorationTemplateSaveReq {
+
+    /** 主键ID,新增时为空 */
+    private Long id;
+
+    /** 模板名称 */
+    private String templateName;
+
+    /** 模板类型 */
+    private String templateType;
+
+    /** 模板封面 */
+    private String coverUrl;
+
+    /** 模板JSON */
+    private String templateData;
+
+    /** 状态 */
+    private Integer status;
+
+    /** 备注 */
+    private String remark;
+}

+ 43 - 0
fs-service/src/main/java/com/fs/decoration/mapper/DecorationComponentMapper.java

@@ -0,0 +1,43 @@
+package com.fs.decoration.mapper;
+
+import com.fs.decoration.domain.DecorationComponent;
+import com.fs.decoration.dto.DecorationComponentQuery;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 组件定义 Mapper
+ */
+public interface DecorationComponentMapper {
+
+    /**
+     * 查询组件列表
+     */
+    List<DecorationComponent> selectList(DecorationComponentQuery query);
+
+    /**
+     * 根据ID查询组件
+     */
+    DecorationComponent selectById(@Param("id") Long id);
+
+    /**
+     * 根据组件编码查询组件
+     */
+    DecorationComponent selectByComponentCode(@Param("componentCode") String componentCode);
+
+    /**
+     * 新增组件
+     */
+    int insert(DecorationComponent entity);
+
+    /**
+     * 修改组件
+     */
+    int updateById(DecorationComponent entity);
+
+    /**
+     * 删除组件
+     */
+    int deleteById(@Param("id") Long id);
+}

+ 15 - 0
fs-service/src/main/java/com/fs/decoration/mapper/DecorationComponentTypeMapper.java

@@ -0,0 +1,15 @@
+package com.fs.decoration.mapper;
+
+import com.fs.decoration.domain.DecorationComponentType;
+import java.util.List;
+
+/**
+ * 组件类型 Mapper
+ */
+public interface DecorationComponentTypeMapper {
+
+    /**
+     * 查询启用的组件类型列表
+     */
+    List<DecorationComponentType> selectList();
+}

+ 37 - 0
fs-service/src/main/java/com/fs/decoration/mapper/DecorationTemplateMapper.java

@@ -0,0 +1,37 @@
+package com.fs.decoration.mapper;
+
+import com.fs.decoration.domain.DecorationTemplate;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 模板 Mapper
+ */
+public interface DecorationTemplateMapper {
+
+    /**
+     * 查询模板列表
+     */
+    List<DecorationTemplate> selectList();
+
+    /**
+     * 根据ID查询模板
+     */
+    DecorationTemplate selectById(@Param("id") Long id);
+
+    /**
+     * 新增模板
+     */
+    int insert(DecorationTemplate entity);
+
+    /**
+     * 修改模板
+     */
+    int updateById(DecorationTemplate entity);
+
+    /**
+     * 删除模板
+     */
+    int deleteById(@Param("id") Long id);
+}

+ 38 - 0
fs-service/src/main/java/com/fs/decoration/service/IDecorationComponentService.java

@@ -0,0 +1,38 @@
+package com.fs.decoration.service;
+
+import com.fs.decoration.domain.DecorationComponent;
+import com.fs.decoration.dto.DecorationComponentQuery;
+import com.fs.decoration.dto.DecorationComponentSaveReq;
+
+import java.util.List;
+
+/**
+ * 组件定义 Service
+ */
+public interface IDecorationComponentService {
+
+    /**
+     * 查询组件列表
+     */
+    List<DecorationComponent> selectList(DecorationComponentQuery query);
+
+    /**
+     * 查询组件详情
+     */
+    DecorationComponent selectById(Long id);
+
+    /**
+     * 新增/修改组件
+     */
+    Long saveComponent(DecorationComponentSaveReq req);
+
+    /**
+     * 删除组件
+     */
+    int deleteById(Long id);
+
+    /**
+     * 修改状态
+     */
+    int updateStatus(Long id, Integer status);
+}

+ 16 - 0
fs-service/src/main/java/com/fs/decoration/service/IDecorationComponentTypeService.java

@@ -0,0 +1,16 @@
+package com.fs.decoration.service;
+
+import com.fs.decoration.vo.OptionVO;
+
+import java.util.List;
+
+/**
+ * 组件类型 Service
+ */
+public interface IDecorationComponentTypeService {
+
+    /**
+     * 查询组件类型下拉
+     */
+    List<OptionVO> listOptions();
+}

+ 32 - 0
fs-service/src/main/java/com/fs/decoration/service/IDecorationTemplateService.java

@@ -0,0 +1,32 @@
+package com.fs.decoration.service;
+
+import com.fs.decoration.domain.DecorationTemplate;
+import com.fs.decoration.dto.DecorationTemplateSaveReq;
+
+import java.util.List;
+
+/**
+ * 模板 Service
+ */
+public interface IDecorationTemplateService {
+
+    /**
+     * 查询模板列表
+     */
+    List<DecorationTemplate> selectList();
+
+    /**
+     * 查询模板详情
+     */
+    DecorationTemplate selectById(Long id);
+
+    /**
+     * 新增/修改模板
+     */
+    Long saveTemplate(DecorationTemplateSaveReq req);
+
+    /**
+     * 删除模板
+     */
+    int deleteById(Long id);
+}

+ 117 - 0
fs-service/src/main/java/com/fs/decoration/service/impl/DecorationComponentServiceImpl.java

@@ -0,0 +1,117 @@
+package com.fs.decoration.service.impl;
+
+import com.fs.decoration.domain.DecorationComponent;
+import com.fs.decoration.dto.DecorationComponentQuery;
+import com.fs.decoration.dto.DecorationComponentSaveReq;
+import com.fs.decoration.mapper.DecorationComponentMapper;
+import com.fs.decoration.service.IDecorationComponentService;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * 组件定义 Service 实现
+ */
+@Service
+public class DecorationComponentServiceImpl implements IDecorationComponentService {
+
+    @Resource
+    private DecorationComponentMapper decorationComponentMapper;
+
+    @Override
+    public List<DecorationComponent> selectList(DecorationComponentQuery query) {
+        return decorationComponentMapper.selectList(query);
+    }
+
+    @Override
+    public DecorationComponent selectById(Long id) {
+        return decorationComponentMapper.selectById(id);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Long saveComponent(DecorationComponentSaveReq req) {
+        // 基础校验
+        if (req.getComponentCode() == null || req.getComponentCode().trim().isEmpty()) {
+            throw new RuntimeException("组件编码不能为空");
+        }
+        if (req.getComponentName() == null || req.getComponentName().trim().isEmpty()) {
+            throw new RuntimeException("组件名称不能为空");
+        }
+        if (req.getComponentTypeCode() == null || req.getComponentTypeCode().trim().isEmpty()) {
+            throw new RuntimeException("组件类型不能为空");
+        }
+
+        // 根据组件编码检查是否已存在
+        DecorationComponent exist = decorationComponentMapper.selectByComponentCode(req.getComponentCode());
+
+        // 新增
+        if (req.getId() == null) {
+            if (exist != null) {
+                throw new RuntimeException("组件编码已存在");
+            }
+
+            DecorationComponent entity = new DecorationComponent();
+            entity.setComponentCode(req.getComponentCode());
+            entity.setComponentName(req.getComponentName());
+            entity.setComponentTypeCode(req.getComponentTypeCode());
+            entity.setIcon(req.getIcon());
+            entity.setPreviewImage(req.getPreviewImage());
+            entity.setStatus(req.getStatus() == null ? 1 : req.getStatus());
+            entity.setRemark(req.getRemark());
+
+            decorationComponentMapper.insert(entity);
+            return entity.getId();
+        }
+
+        // 修改
+        DecorationComponent old = decorationComponentMapper.selectById(req.getId());
+        if (old == null) {
+            throw new RuntimeException("组件不存在");
+        }
+
+        // 如果存在同编码记录,但不是自己,说明编码冲突
+        if (exist != null && !exist.getId().equals(req.getId())) {
+            throw new RuntimeException("组件编码已存在");
+        }
+
+        DecorationComponent entity = new DecorationComponent();
+        entity.setId(req.getId());
+        entity.setComponentCode(req.getComponentCode());
+        entity.setComponentName(req.getComponentName());
+        entity.setComponentTypeCode(req.getComponentTypeCode());
+        entity.setIcon(req.getIcon());
+        entity.setPreviewImage(req.getPreviewImage());
+        entity.setStatus(req.getStatus() == null ? old.getStatus() : req.getStatus());
+        entity.setRemark(req.getRemark());
+
+        decorationComponentMapper.updateById(entity);
+        return entity.getId();
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int deleteById(Long id) {
+        DecorationComponent old = decorationComponentMapper.selectById(id);
+        if (old == null) {
+            throw new RuntimeException("组件不存在");
+        }
+        return decorationComponentMapper.deleteById(id);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int updateStatus(Long id, Integer status) {
+        DecorationComponent old = decorationComponentMapper.selectById(id);
+        if (old == null) {
+            throw new RuntimeException("组件不存在");
+        }
+
+        DecorationComponent entity = new DecorationComponent();
+        entity.setId(id);
+        entity.setStatus(status);
+        return decorationComponentMapper.updateById(entity);
+    }
+}

+ 29 - 0
fs-service/src/main/java/com/fs/decoration/service/impl/DecorationComponentTypeServiceImpl.java

@@ -0,0 +1,29 @@
+package com.fs.decoration.service.impl;
+
+import com.fs.decoration.domain.DecorationComponentType;
+import com.fs.decoration.mapper.DecorationComponentTypeMapper;
+import com.fs.decoration.service.IDecorationComponentTypeService;
+import com.fs.decoration.vo.OptionVO;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 组件类型 Service 实现
+ */
+@Service
+public class DecorationComponentTypeServiceImpl implements IDecorationComponentTypeService {
+
+    @Resource
+    private DecorationComponentTypeMapper decorationComponentTypeMapper;
+
+    @Override
+    public List<OptionVO> listOptions() {
+        List<DecorationComponentType> list = decorationComponentTypeMapper.selectList();
+        return list.stream()
+                .map(item -> new OptionVO(item.getTypeCode(), item.getTypeName()))
+                .collect(Collectors.toList());
+    }
+}

+ 95 - 0
fs-service/src/main/java/com/fs/decoration/service/impl/DecorationTemplateServiceImpl.java

@@ -0,0 +1,95 @@
+package com.fs.decoration.service.impl;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fs.decoration.domain.DecorationTemplate;
+import com.fs.decoration.dto.DecorationTemplateSaveReq;
+import com.fs.decoration.mapper.DecorationTemplateMapper;
+import com.fs.decoration.service.IDecorationTemplateService;
+import com.fs.decoration.vo.TemplateContentVO;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * 模板 Service 实现
+ */
+@Service
+public class DecorationTemplateServiceImpl implements IDecorationTemplateService {
+
+    @Resource
+    private DecorationTemplateMapper decorationTemplateMapper;
+
+    /** 用于校验 templateData JSON 结构 */
+    private final ObjectMapper objectMapper = new ObjectMapper();
+
+    @Override
+    public List<DecorationTemplate> selectList() {
+        return decorationTemplateMapper.selectList();
+    }
+
+    @Override
+    public DecorationTemplate selectById(Long id) {
+        return decorationTemplateMapper.selectById(id);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Long saveTemplate(DecorationTemplateSaveReq req) {
+        if (req.getTemplateName() == null || req.getTemplateName().trim().isEmpty()) {
+            throw new RuntimeException("模板名称不能为空");
+        }
+        if (req.getTemplateData() == null || req.getTemplateData().trim().isEmpty()) {
+            throw new RuntimeException("模板数据不能为空");
+        }
+
+        // 校验模板 JSON 格式是否正确
+        validateTemplateData(req.getTemplateData());
+
+        DecorationTemplate entity = new DecorationTemplate();
+        entity.setId(req.getId());
+        entity.setTemplateName(req.getTemplateName());
+        entity.setTemplateType(req.getTemplateType());
+        entity.setCoverUrl(req.getCoverUrl());
+        entity.setTemplateData(req.getTemplateData());
+        entity.setStatus(req.getStatus() == null ? 1 : req.getStatus());
+        entity.setRemark(req.getRemark());
+
+        if (req.getId() == null) {
+            decorationTemplateMapper.insert(entity);
+        } else {
+            DecorationTemplate old = decorationTemplateMapper.selectById(req.getId());
+            if (old == null) {
+                throw new RuntimeException("模板不存在");
+            }
+            decorationTemplateMapper.updateById(entity);
+        }
+
+        return entity.getId();
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int deleteById(Long id) {
+        DecorationTemplate old = decorationTemplateMapper.selectById(id);
+        if (old == null) {
+            throw new RuntimeException("模板不存在");
+        }
+        return decorationTemplateMapper.deleteById(id);
+    }
+
+    /**
+     * 校验模板 JSON 格式
+     */
+    private void validateTemplateData(String templateData) {
+        try {
+            TemplateContentVO content = objectMapper.readValue(templateData, TemplateContentVO.class);
+            if (content == null) {
+                throw new RuntimeException("模板JSON不能为空");
+            }
+        } catch (Exception e) {
+            throw new RuntimeException("模板JSON格式错误:" + e.getMessage());
+        }
+    }
+}

+ 18 - 0
fs-service/src/main/java/com/fs/decoration/vo/OptionVO.java

@@ -0,0 +1,18 @@
+package com.fs.decoration.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+/**
+ * 下拉选项VO
+ */
+@Data
+@AllArgsConstructor
+public class OptionVO {
+
+    /** value 值 */
+    private String value;
+
+    /** label 文本 */
+    private String label;
+}

+ 37 - 0
fs-service/src/main/java/com/fs/decoration/vo/TemplateContentVO.java

@@ -0,0 +1,37 @@
+package com.fs.decoration.vo;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 模板JSON结构校验VO
+ */
+@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class TemplateContentVO {
+
+    /** 页面配置 */
+    private PageConfigVO pageConfig;
+
+    /** 页面组件列表 */
+    private List<ComponentItemVO> components;
+
+    @Data
+    @JsonIgnoreProperties(ignoreUnknown = true)
+    public static class PageConfigVO {
+        /** 模板名称 */
+        private String templateName;
+    }
+
+    @Data
+    @JsonIgnoreProperties(ignoreUnknown = true)
+    public static class ComponentItemVO {
+        /** 页面中组件实例ID */
+        private String id;
+
+        /** 组件编码 */
+        private String componentCode;
+    }
+}

+ 123 - 0
fs-service/src/main/resources/mapper/decoration/DecorationComponentMapper.xml

@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.decoration.mapper.DecorationComponentMapper">
+
+    <resultMap id="DecorationComponentResultMap" type="com.fs.decoration.domain.DecorationComponent">
+        <id property="id" column="id"/>
+        <result property="componentCode" column="component_code"/>
+        <result property="componentName" column="component_name"/>
+        <result property="componentTypeCode" column="component_type_code"/>
+        <result property="icon" column="icon"/>
+        <result property="previewImage" column="preview_image"/>
+        <result property="status" column="status"/>
+        <result property="remark" column="remark"/>
+        <result property="createTime" column="create_time"/>
+        <result property="updateTime" column="update_time"/>
+    </resultMap>
+
+    <select id="selectList" resultMap="DecorationComponentResultMap">
+        select
+        id,
+        component_code,
+        component_name,
+        component_type_code,
+        icon,
+        preview_image,
+        status,
+        remark,
+        create_time,
+        update_time
+        from decoration_component
+        where 1 = 1
+        <if test="componentName != null and componentName != ''">
+            and component_name like concat('%', #{componentName}, '%')
+        </if>
+        <if test="componentTypeCode != null and componentTypeCode != ''">
+            and component_type_code = #{componentTypeCode}
+        </if>
+        <if test="status != null">
+            and status = #{status}
+        </if>
+        order by id desc
+    </select>
+
+    <select id="selectById" resultMap="DecorationComponentResultMap">
+        select
+            id,
+            component_code,
+            component_name,
+            component_type_code,
+            icon,
+            preview_image,
+            status,
+            remark,
+            create_time,
+            update_time
+        from decoration_component
+        where id = #{id}
+    </select>
+
+    <select id="selectByComponentCode" resultMap="DecorationComponentResultMap">
+        select
+            id,
+            component_code,
+            component_name,
+            component_type_code,
+            icon,
+            preview_image,
+            status,
+            remark,
+            create_time,
+            update_time
+        from decoration_component
+        where component_code = #{componentCode}
+            limit 1
+    </select>
+
+    <insert id="insert" useGeneratedKeys="true" keyProperty="id">
+        insert into decoration_component (
+            component_code,
+            component_name,
+            component_type_code,
+            icon,
+            preview_image,
+            status,
+            remark,
+            create_time,
+            update_time
+        ) values (
+                     #{componentCode},
+                     #{componentName},
+                     #{componentTypeCode},
+                     #{icon},
+                     #{previewImage},
+                     #{status},
+                     #{remark},
+                     now(),
+                     now()
+                 )
+    </insert>
+
+    <update id="updateById">
+        update decoration_component
+        <set>
+            <if test="componentCode != null">component_code = #{componentCode},</if>
+            <if test="componentName != null">component_name = #{componentName},</if>
+            <if test="componentTypeCode != null">component_type_code = #{componentTypeCode},</if>
+            <if test="icon != null">icon = #{icon},</if>
+            <if test="previewImage != null">preview_image = #{previewImage},</if>
+            <if test="status != null">status = #{status},</if>
+            <if test="remark != null">remark = #{remark},</if>
+            update_time = now()
+        </set>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteById">
+        delete from decoration_component
+        where id = #{id}
+    </delete>
+
+</mapper>

+ 31 - 0
fs-service/src/main/resources/mapper/decoration/DecorationComponentTypeMapper.xml

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.decoration.mapper.DecorationComponentTypeMapper">
+
+    <resultMap id="DecorationComponentTypeResultMap" type="com.fs.decoration.domain.DecorationComponentType">
+        <id property="id" column="id"/>
+        <result property="typeCode" column="type_code"/>
+        <result property="typeName" column="type_name"/>
+        <result property="status" column="status"/>
+        <result property="remark" column="remark"/>
+        <result property="createTime" column="create_time"/>
+        <result property="updateTime" column="update_time"/>
+    </resultMap>
+
+    <select id="selectList" resultMap="DecorationComponentTypeResultMap">
+        select
+            id,
+            type_code,
+            type_name,
+            status,
+            remark,
+            create_time,
+            update_time
+        from decoration_component_type
+        where status = 1
+        order by id asc
+    </select>
+
+</mapper>

+ 90 - 0
fs-service/src/main/resources/mapper/decoration/DecorationTemplateMapper.xml

@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.decoration.mapper.DecorationTemplateMapper">
+
+    <resultMap id="DecorationTemplateResultMap" type="com.fs.decoration.domain.DecorationTemplate">
+        <id property="id" column="id"/>
+        <result property="templateName" column="template_name"/>
+        <result property="templateType" column="template_type"/>
+        <result property="coverUrl" column="cover_url"/>
+        <result property="templateData" column="template_data"/>
+        <result property="status" column="status"/>
+        <result property="remark" column="remark"/>
+        <result property="createTime" column="create_time"/>
+        <result property="updateTime" column="update_time"/>
+    </resultMap>
+
+    <select id="selectList" resultMap="DecorationTemplateResultMap">
+        select
+            id,
+            template_name,
+            template_type,
+            cover_url,
+            template_data,
+            status,
+            remark,
+            create_time,
+            update_time
+        from decoration_template
+        order by id desc
+    </select>
+
+    <select id="selectById" resultMap="DecorationTemplateResultMap">
+        select
+            id,
+            template_name,
+            template_type,
+            cover_url,
+            template_data,
+            status,
+            remark,
+            create_time,
+            update_time
+        from decoration_template
+        where id = #{id}
+    </select>
+
+    <insert id="insert" useGeneratedKeys="true" keyProperty="id">
+        insert into decoration_template (
+            template_name,
+            template_type,
+            cover_url,
+            template_data,
+            status,
+            remark,
+            create_time,
+            update_time
+        ) values (
+                     #{templateName},
+                     #{templateType},
+                     #{coverUrl},
+                     #{templateData},
+                     #{status},
+                     #{remark},
+                     now(),
+                     now()
+                 )
+    </insert>
+
+    <update id="updateById">
+        update decoration_template
+        <set>
+            <if test="templateName != null">template_name = #{templateName},</if>
+            <if test="templateType != null">template_type = #{templateType},</if>
+            <if test="coverUrl != null">cover_url = #{coverUrl},</if>
+            <if test="templateData != null">template_data = #{templateData},</if>
+            <if test="status != null">status = #{status},</if>
+            <if test="remark != null">remark = #{remark},</if>
+            update_time = now()
+        </set>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteById">
+        delete from decoration_template
+        where id = #{id}
+    </delete>
+
+</mapper>