diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java
index 54d4be9d9..11a5ee078 100644
--- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java
+++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java
@@ -27,8 +27,6 @@ public interface WebFilterOrderEnum {
 
     int TENANT_SECURITY_FILTER = -99; // 需要保证在 Spring Security 过滤器后面
 
-    int ACTIVITI_FILTER = -98; // 需要保证在 Spring Security 过滤后面
-
     int FLOWABLE_FILTER = -98; // 需要保证在 Spring Security 过滤后面
 
     int DEMO_FILTER = Integer.MAX_VALUE;
diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/enums/GlobalErrorCodeConstants.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/enums/GlobalErrorCodeConstants.java
index 61533de60..962a94663 100644
--- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/enums/GlobalErrorCodeConstants.java
+++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/enums/GlobalErrorCodeConstants.java
@@ -37,15 +37,4 @@ public interface GlobalErrorCodeConstants {
 
     ErrorCode UNKNOWN = new ErrorCode(999, "未知错误");
 
-    /**
-     * 是否为服务端错误,参考 HTTP 5XX 错误码段
-     *
-     * @param code 错误码
-     * @return 是否
-     */
-   static boolean isServerErrorCode(Integer code) {
-       return code != null
-               && code >= INTERNAL_SERVER_ERROR.getCode() && code <= INTERNAL_SERVER_ERROR.getCode() + 99;
-   }
-
 }
diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/CommonResult.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/CommonResult.java
index cb82d301a..bfb291b6d 100644
--- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/CommonResult.java
+++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/CommonResult.java
@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.framework.common.pojo;
 
 import cn.iocoder.yudao.framework.common.exception.ErrorCode;
-import cn.iocoder.yudao.framework.common.exception.ServerException;
 import cn.iocoder.yudao.framework.common.exception.ServiceException;
 import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
 import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -92,10 +91,6 @@ public class CommonResult<T> implements Serializable {
         if (isSuccess()) {
             return;
         }
-        // 服务端异常
-        if (GlobalErrorCodeConstants.isServerErrorCode(code)) {
-            throw new ServerException(code, msg);
-        }
         // 业务异常
         throw new ServiceException(code, msg);
     }
diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java
index 62e0e4441..a55af427c 100644
--- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java
+++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java
@@ -4,6 +4,7 @@ import cn.hutool.core.date.LocalDateTimeUtil;
 
 import java.time.Duration;
 import java.time.LocalDateTime;
+import java.time.LocalTime;
 
 /**
  * 时间工具类,用于 {@link java.time.LocalDateTime}
@@ -50,7 +51,7 @@ public class LocalDateTimeUtils {
      * 判断当前时间是否在该时间范围内
      *
      * @param startTime 开始时间
-     * @param endTime 结束时间
+     * @param endTime   结束时间
      * @return 是否
      */
     public static boolean isBetween(LocalDateTime startTime, LocalDateTime endTime) {
@@ -60,4 +61,24 @@ public class LocalDateTimeUtils {
         return LocalDateTimeUtil.isIn(LocalDateTime.now(), startTime, endTime);
     }
 
+    /**
+     * 检查时间重叠 不包含日期
+     *
+     * @param startTime1 需要校验的开始时间
+     * @param endTime1   需要校验的结束时间
+     * @param startTime2 校验所需的开始时间
+     * @param endTime2   校验所需的结束时间
+     * @return 是否重叠
+     */
+    // TODO @puhui999:LocalDateTimeUtil.isOverlap() 是不是可以满足呀?
+    public static boolean checkTimeOverlap(LocalTime startTime1, LocalTime endTime1, LocalTime startTime2, LocalTime endTime2) {
+        // 判断时间是否重叠
+        // 开始时间在已配置时段的结束时间之前 且 结束时间在已配置时段的开始时间之后 []
+        return startTime1.isBefore(endTime2) && endTime1.isAfter(startTime2)
+                // 开始时间在已配置时段的开始时间之前 且 结束时间在已配置时段的开始时间之后 (] 或 ()
+                || startTime1.isBefore(startTime2) && endTime1.isAfter(startTime2)
+                // 开始时间在已配置时段的结束时间之前 且 结束时间在已配值时段的结束时间之后 [) 或 ()
+                || startTime1.isBefore(endTime2) && endTime1.isAfter(endTime2);
+    }
+
 }
diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java
index c9dc5a2d9..56f9aeaa6 100644
--- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java
+++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java
@@ -21,6 +21,7 @@ public class YudaoJacksonAutoConfiguration {
     @Bean
     public BeanPostProcessor objectMapperBeanPostProcessor() {
         return new BeanPostProcessor() {
+
             @Override
             public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                 if (!(bean instanceof ObjectMapper)) {
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
index 709a86a50..1131135db 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
@@ -17,12 +17,9 @@ import org.flowable.task.api.Task;
 import org.flowable.task.api.history.HistoricTaskInstance;
 import org.mapstruct.*;
 import org.mapstruct.factory.Mappers;
-import org.springframework.beans.BeanUtils;
 
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
-import java.util.stream.Collectors;
 
 /**
  * Bpm 任务 Convert
@@ -34,37 +31,9 @@ public interface BpmTaskConvert {
 
     BpmTaskConvert INSTANCE = Mappers.getMapper(BpmTaskConvert.class);
 
-    /**
-     * 复制对象
-     *
-     * @param source 源 要复制的对象
-     * @param target 目标 复制到此对象
-     * @param <T>
-     *
-     * @return
-     */
-    public static <T> T copy(Object source, Class<T> target) {
-        if (source == null || target == null) {
-            return null;
-        }
-        try {
-            T newInstance = target.getDeclaredConstructor().newInstance();
-            BeanUtils.copyProperties(source, newInstance);
-            return newInstance;
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    default <T, K> List<K> copyList(List<T> source, Class<K> target) {
-        if (null == source || source.isEmpty()) {
-            return Collections.emptyList();
-        }
-        return source.stream().map(e -> copy(e, target)).collect(Collectors.toList());
-    }
-
     default List<BpmTaskTodoPageItemRespVO> convertList1(List<Task> tasks,
-        Map<String, ProcessInstance> processInstanceMap, Map<Long, AdminUserRespDTO> userMap) {
+                                                         Map<String, ProcessInstance> processInstanceMap,
+                                                         Map<Long, AdminUserRespDTO> userMap) {
         return CollectionUtils.convertList(tasks, task -> {
             BpmTaskTodoPageItemRespVO respVO = convert1(task);
             ProcessInstance processInstance = processInstanceMap.get(task.getProcessInstanceId());
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmActivityDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmActivityDO.java
deleted file mode 100644
index 02e67e8d3..000000000
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmActivityDO.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package cn.iocoder.yudao.module.bpm.dal.dataobject.task;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import lombok.*;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.time.LocalDateTime;
-
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT;
-
-/**
- * 任务流程关联表
- *
- * @author kemengkai
- * @create 2022-05-09 10:33
- */
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class BpmActivityDO {
-
-    /**
-     * 任务流程关联id
-     */
-    private String id;
-
-    /**
-     * 审批结果
-     */
-    private Integer rev;
-
-    /**
-     * 任务流程部署id
-     */
-    private String procDefId;
-
-    /**
-     * 任务流程id
-     */
-    private String processInstanceId;
-
-    /**
-     * 任务执行id
-     */
-    private String executionId;
-
-    /**
-     * 任务key
-     */
-    private String activityId;
-
-    /**
-     * 任务id
-     */
-    private String taskId;
-
-    /**
-     * 调用流程id
-     */
-    private String callProcInstId;
-
-    /**
-     * 任务名称
-     */
-    private String activityName;
-
-    /**
-     * 任务类型
-     */
-    private String activityType;
-
-    /**
-     * 任务审批人id
-     */
-    private String assignee;
-
-    /**
-     * 任务开始时间
-     */
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
-    private LocalDateTime startTime;
-
-    /**
-     * 任务结束时间
-     */
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
-    private LocalDateTime endTime;
-
-    private Integer transactionOrder;
-
-    private LocalDateTime duration;
-
-    /**
-     * 删除结果
-     */
-    private String deleteReason;
-
-    /**
-     * 租户id
-     */
-    private String tenantId;
-}
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/CodegenPreviewRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/CodegenPreviewRespVO.java
index b349b1769..ffd924a0c 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/CodegenPreviewRespVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/CodegenPreviewRespVO.java
@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
-@Schema(description = "管理后台 - 代码生成预览 Response VO,注意,每个文件都是一个该对象")
+@Schema(description = "管理后台 - 代码生成预览 Response VO,注意,每个文件都是一个该对象")
 @Data
 public class CodegenPreviewRespVO {
 
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/column/CodegenColumnBaseVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/column/CodegenColumnBaseVO.java
index d0b2d046a..c46d9fa35 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/column/CodegenColumnBaseVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/column/CodegenColumnBaseVO.java
@@ -70,7 +70,7 @@ public class CodegenColumnBaseVO {
     @NotNull(message = "是否为 List 查询操作的字段不能为空")
     private Boolean listOperation;
 
-    @Schema(description = "List 查询操作的条件类型,参见 CodegenColumnListConditionEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "LIKE")
+    @Schema(description = "List 查询操作的条件类型,参见 CodegenColumnListConditionEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "LIKE")
     @NotNull(message = "List 查询操作的条件类型不能为空")
     private String listOperationCondition;
 
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTableBaseVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTableBaseVO.java
index 76c8d6844..ede10fccd 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTableBaseVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTableBaseVO.java
@@ -12,7 +12,7 @@ import javax.validation.constraints.NotNull;
 @Data
 public class CodegenTableBaseVO {
 
-    @Schema(description = "生成场景,参见 CodegenSceneEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "生成场景,参见 CodegenSceneEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "导入类型不能为空")
     private Integer scene;
 
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTablePageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTablePageReqVO.java
index ece0a9eac..032a9d82f 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTablePageReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTablePageReqVO.java
@@ -17,13 +17,13 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
 @ToString(callSuper = true)
 public class CodegenTablePageReqVO extends PageParam {
 
-    @Schema(description = "表名称,模糊匹配", example = "yudao")
+    @Schema(description = "表名称,模糊匹配", example = "yudao")
     private String tableName;
 
-    @Schema(description = "表描述,模糊匹配", example = "芋道")
+    @Schema(description = "表描述,模糊匹配", example = "芋道")
     private String tableComment;
 
-    @Schema(description = "实体,模糊匹配", example = "Yudao")
+    @Schema(description = "实体,模糊匹配", example = "Yudao")
     private String className;
 
     @Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigExportReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigExportReqVO.java
index f0f4b4ff3..78d289a5b 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigExportReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigExportReqVO.java
@@ -15,10 +15,10 @@ public class ConfigExportReqVO {
     @Schema(description = "参数名称", example = "模糊匹配")
     private String name;
 
-    @Schema(description = "参数键名,模糊匹配", example = "yunai.db.username")
+    @Schema(description = "参数键名,模糊匹配", example = "yunai.db.username")
     private String key;
 
-    @Schema(description = "参数类型,参见 SysConfigTypeEnum 枚举", example = "1")
+    @Schema(description = "参数类型,参见 SysConfigTypeEnum 枚举", example = "1")
     private Integer type;
 
     @Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigPageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigPageReqVO.java
index 8f87d6ee9..8caec39d1 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigPageReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigPageReqVO.java
@@ -17,13 +17,13 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
 @ToString(callSuper = true)
 public class ConfigPageReqVO extends PageParam {
 
-    @Schema(description = "数据源名称,模糊匹配", example = "名称")
+    @Schema(description = "数据源名称,模糊匹配", example = "名称")
     private String name;
 
-    @Schema(description = "参数键名,模糊匹配", example = "yunai.db.username")
+    @Schema(description = "参数键名,模糊匹配", example = "yunai.db.username")
     private String key;
 
-    @Schema(description = "参数类型,参见 SysConfigTypeEnum 枚举", example = "1")
+    @Schema(description = "参数类型,参见 SysConfigTypeEnum 枚举", example = "1")
     private Integer type;
 
     @Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java
index cf8b1e3ac..8c3d51e7e 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java
@@ -21,7 +21,7 @@ public class ConfigRespVO extends ConfigBaseVO {
     @Size(max = 100, message = "参数键名长度不能超过100个字符")
     private String key;
 
-    @Schema(description = "参数类型,参见 SysConfigTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "参数类型,参见 SysConfigTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer type;
 
     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式")
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigCreateReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigCreateReqVO.java
index f3132e970..496e32237 100755
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigCreateReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigCreateReqVO.java
@@ -14,7 +14,7 @@ import java.util.Map;
 @ToString(callSuper = true)
 public class FileConfigCreateReqVO extends FileConfigBaseVO {
 
-    @Schema(description = "存储器,参见 FileStorageEnum 枚举类参见 FileStorageEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "存储器,参见 FileStorageEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "存储器不能为空")
     private Integer storage;
 
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigPageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigPageReqVO.java
index 9d254adb1..f2314a469 100755
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigPageReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigPageReqVO.java
@@ -23,8 +23,8 @@ public class FileConfigPageReqVO extends PageParam {
     @Schema(description = "存储器", example = "1")
     private Integer storage;
 
+    @Schema(description = "创建时间", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]")
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    @Schema(description = "创建时间")
     private LocalDateTime[] createTime;
 
 }
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigRespVO.java
index 178317126..c64556728 100755
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigRespVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigRespVO.java
@@ -18,7 +18,7 @@ public class FileConfigRespVO extends FileConfigBaseVO {
     @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Long id;
 
-    @Schema(description = "存储器,参见 FileStorageEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "存储器,参见 FileStorageEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "存储器不能为空")
     private Integer storage;
 
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePageReqVO.java
index fa8b84eef..21c117867 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePageReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePageReqVO.java
@@ -17,14 +17,14 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
 @ToString(callSuper = true)
 public class FilePageReqVO extends PageParam {
 
-    @Schema(description = "文件路径,模糊匹配", example = "yudao")
+    @Schema(description = "文件路径,模糊匹配", example = "yudao")
     private String path;
 
-    @Schema(description = "文件类型,模糊匹配", example = "application/octet-stream")
+    @Schema(description = "文件类型,模糊匹配", example = "jpg")
     private String type;
 
+    @Schema(description = "创建时间", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]")
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    @Schema(description = "创建时间")
     private LocalDateTime[] createTime;
 
 }
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobPageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobPageReqVO.java
index 670c30f5c..332833519 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobPageReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobPageReqVO.java
@@ -12,13 +12,13 @@ import lombok.ToString;
 @ToString(callSuper = true)
 public class JobPageReqVO extends PageParam {
 
-    @Schema(description = "任务名称,模糊匹配", example = "测试任务")
+    @Schema(description = "任务名称,模糊匹配", example = "测试任务")
     private String name;
 
-    @Schema(description = "任务状态,参见 JobStatusEnum 枚举", example = "1")
+    @Schema(description = "任务状态,参见 JobStatusEnum 枚举", example = "1")
     private Integer status;
 
-    @Schema(description = "处理器的名字,模糊匹配", example = "sysUserSessionTimeoutJob")
+    @Schema(description = "处理器的名字,模糊匹配", example = "sysUserSessionTimeoutJob")
     private String handlerName;
 
 }
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogBaseVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogBaseVO.java
index 1119c7daf..5a74d38db 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogBaseVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogBaseVO.java
@@ -43,7 +43,7 @@ public class JobLogBaseVO {
     @Schema(description = "执行时长", example = "123")
     private Integer duration;
 
-    @Schema(description = "任务状态,参见 JobLogStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "任务状态,参见 JobLogStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "任务状态不能为空")
     private Integer status;
 
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogExportReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogExportReqVO.java
index 6f5c7f69f..3156e2bc3 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogExportReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogExportReqVO.java
@@ -8,14 +8,14 @@ import java.time.LocalDateTime;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
-@Schema(description = "管理后台 - 定时任务 Excel 导出 Request VO,参数和 JobLogPageReqVO 是一致的")
+@Schema(description = "管理后台 - 定时任务 Excel 导出 Request VO,参数和 JobLogPageReqVO 是一致的")
 @Data
 public class JobLogExportReqVO {
 
     @Schema(description = "任务编号", example = "10")
     private Long jobId;
 
-    @Schema(description = "处理器的名字,模糊匹配")
+    @Schema(description = "处理器的名字,模糊匹配")
     private String handlerName;
 
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@@ -26,7 +26,7 @@ public class JobLogExportReqVO {
     @Schema(description = "结束执行时间")
     private LocalDateTime endTime;
 
-    @Schema(description = "任务状态,参见 JobLogStatusEnum 枚举")
+    @Schema(description = "任务状态,参见 JobLogStatusEnum 枚举")
     private Integer status;
 
 }
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogPageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogPageReqVO.java
index 84bf9ca34..1d3d49600 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogPageReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogPageReqVO.java
@@ -20,7 +20,7 @@ public class JobLogPageReqVO extends PageParam {
     @Schema(description = "任务编号", example = "10")
     private Long jobId;
 
-    @Schema(description = "处理器的名字,模糊匹配")
+    @Schema(description = "处理器的名字,模糊匹配")
     private String handlerName;
 
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@@ -31,7 +31,7 @@ public class JobLogPageReqVO extends PageParam {
     @Schema(description = "结束执行时间")
     private LocalDateTime endTime;
 
-    @Schema(description = "任务状态,参见 JobLogStatusEnum 枚举")
+    @Schema(description = "任务状态,参见 JobLogStatusEnum 枚举")
     private Integer status;
 
 }
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogBaseVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogBaseVO.java
index 5830193ba..daa3e72b7 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogBaseVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogBaseVO.java
@@ -24,7 +24,7 @@ public class ApiAccessLogBaseVO {
     @NotNull(message = "用户编号不能为空")
     private Long userId;
 
-    @Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    @Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
     @NotNull(message = "用户类型不能为空")
     private Integer userType;
 
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExportReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExportReqVO.java
index 8894b82f8..8010e3586 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExportReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExportReqVO.java
@@ -8,7 +8,7 @@ import java.time.LocalDateTime;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
-@Schema(description = "管理后台 - API 访问日志 Excel 导出 Request VO,参数和 ApiAccessLogPageReqVO 是一致的")
+@Schema(description = "管理后台 - API 访问日志 Excel 导出 Request VO,参数和 ApiAccessLogPageReqVO 是一致的")
 @Data
 public class ApiAccessLogExportReqVO {
 
@@ -21,11 +21,11 @@ public class ApiAccessLogExportReqVO {
     @Schema(description = "应用名", example = "dashboard")
     private String applicationName;
 
-    @Schema(description = "请求地址,模糊匹配", example = "/xxx/yyy")
+    @Schema(description = "请求地址,模糊匹配", example = "/xxx/yyy")
     private String requestUrl;
 
+    @Schema(description = "开始时间", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]")
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    @Schema(description = "开始请求时间")
     private LocalDateTime[] beginTime;
 
     @Schema(description = "执行时长,大于等于,单位:毫秒", example = "100")
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogPageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogPageReqVO.java
index daf2c616e..c17c11122 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogPageReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogPageReqVO.java
@@ -26,11 +26,11 @@ public class ApiAccessLogPageReqVO extends PageParam {
     @Schema(description = "应用名", example = "dashboard")
     private String applicationName;
 
-    @Schema(description = "请求地址,模糊匹配", example = "/xxx/yyy")
+    @Schema(description = "请求地址,模糊匹配", example = "/xxx/yyy")
     private String requestUrl;
 
+    @Schema(description = "开始时间", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]")
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    @Schema(description = "开始请求时间")
     private LocalDateTime[] beginTime;
 
     @Schema(description = "执行时长,大于等于,单位:毫秒", example = "100")
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExportReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExportReqVO.java
index dbc386729..792f2d7c0 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExportReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExportReqVO.java
@@ -8,7 +8,7 @@ import java.time.LocalDateTime;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
-@Schema(description = "管理后台 - API 错误日志 Excel 导出 Request VO,参数和 ApiErrorLogPageReqVO 是一致的")
+@Schema(description = "管理后台 - API 错误日志 Excel 导出 Request VO,参数和 ApiErrorLogPageReqVO 是一致的")
 @Data
 public class ApiErrorLogExportReqVO {
 
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoExportReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoExportReqVO.java
index 8e10484e3..f219499ff 100755
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoExportReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoExportReqVO.java
@@ -7,7 +7,7 @@ import org.springframework.format.annotation.DateTimeFormat;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
-@Schema(description = "管理后台 - 字典类型 Excel 导出 Request VO,参数和 TestDemoPageReqVO 是一致的")
+@Schema(description = "管理后台 - 字典类型 Excel 导出 Request VO,参数和 TestDemoPageReqVO 是一致的")
 @Data
 public class TestDemoExportReqVO {
 
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImpl.java
index 17fb5cea3..9e8933520 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImpl.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImpl.java
@@ -57,7 +57,7 @@ public class DatabaseTableServiceImpl implements DatabaseTableService {
             strategyConfig.addExclude("ACT_[\\S\\s]+|QRTZ_[\\S\\s]+|FLW_[\\S\\s]+");
         }
 
-        GlobalConfig globalConfig = new GlobalConfig.Builder().dateType(DateType.TIME_PACK).build(); // 只使用 Date 类型,不使用 LocalDate
+        GlobalConfig globalConfig = new GlobalConfig.Builder().dateType(DateType.TIME_PACK).build(); // 只使用 LocalDateTime 类型,不使用 LocalDate
         ConfigBuilder builder = new ConfigBuilder(null, dataSourceConfig, strategyConfig.build(),
                 null, globalConfig, null);
         // 按照名字排序
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImpl.java
index 70f2ebc5d..f476b5a72 100755
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImpl.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImpl.java
@@ -79,7 +79,7 @@ public class TestDemoServiceImpl implements TestDemoService {
 
     @Override
     public PageResult<TestDemoDO> getTestDemoPage(TestDemoPageReqVO pageReqVO) {
-        testDemoMapper.selectList2();
+//        testDemoMapper.selectList2();
         return testDemoMapper.selectPage(pageReqVO);
     }
 
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java
index 21fcf7d96..2ed262cde 100644
--- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java
@@ -30,14 +30,13 @@ public interface ProductSkuApi {
      */
     List<ProductSkuRespDTO> getSkuList(Collection<Long> ids);
 
-    // TODO puhui999:入参用 Collection<Long> 更通用
     /**
      * 批量查询 SKU 数组
      *
      * @param spuIds SPU 编号列表
      * @return SKU 数组
      */
-    List<ProductSkuRespDTO> getSkuListBySpuId(List<Long> spuIds);
+    List<ProductSkuRespDTO> getSkuListBySpuId(Collection<Long> spuIds);
 
     /**
      * 更新 SKU 库存
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
index d97a2613f..1f2670d76 100644
--- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
@@ -45,10 +45,8 @@ public interface ErrorCodeConstants {
     ErrorCode SKU_STOCK_NOT_ENOUGH = new ErrorCode(1008006004, "商品 SKU 库存不足");
 
     // ========== 商品 评价 1008007000 ==========
-    ErrorCode COMMENT_NOT_EXISTS = new ErrorCode(1008007000, "商品 评价 不存在");
-    ErrorCode ORDER_SPU_COMMENT_EXISTS = new ErrorCode(1008007001, "订单 商品评价 已存在");
-    ErrorCode COMMENT_ERROR_OPT = new ErrorCode(1008007002, "商品评价非法操作");
-    ErrorCode COMMENT_ADDITIONAL_EXISTS  = new ErrorCode(1008007003, "商品追加评价已存在");
+    ErrorCode COMMENT_NOT_EXISTS = new ErrorCode(1008007000, "商品评价不存在");
+    ErrorCode COMMENT_ORDER_EXISTS = new ErrorCode(1008007001, "订单的商品评价已存在");
 
     // ========== 商品 收藏 1008008000 ==========
     ErrorCode FAVORITE_EXISTS = new ErrorCode(1008008000, "该商品已经被收藏");
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java
index 4a8425f61..bd0258efa 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java
@@ -43,7 +43,7 @@ public class ProductSkuApiImpl implements ProductSkuApi {
     }
 
     @Override
-    public List<ProductSkuRespDTO> getSkuListBySpuId(List<Long> spuIds) {
+    public List<ProductSkuRespDTO> getSkuListBySpuId(Collection<Long> spuIds) {
         if (CollUtil.isEmpty(spuIds)) {
             return Collections.emptyList();
         }
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentBaseVO.java
index c2e791a44..24d6a5456 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentBaseVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentBaseVO.java
@@ -26,23 +26,10 @@ public class ProductCommentBaseVO {
     @NotNull(message = "评价人头像不能为空")
     private String userAvatar;
 
-    // TODO @puhui:spuId、spuName 是不是只有 ProductCommentRespVO 有呀。
-    @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑透气小短袖")
-    @NotNull(message = "商品 SPU 编号不能为空")
-    private Long spuId;
-
-    @Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
-    @NotNull(message = "商品 SPU 名称不能为空")
-    private String spuName;
-
     @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "商品 SKU 编号不能为空")
     private Long skuId;
 
-    @Schema(description = "评分星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
-    @NotNull(message = "评分星级不能为空")
-    private Integer scores;
-
     @Schema(description = "描述星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
     @NotNull(message = "描述星级不能为空")
     private Integer descriptionScores;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentPageReqVO.java
index f6e913fea..3791f572e 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentPageReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentPageReqVO.java
@@ -35,9 +35,8 @@ public class ProductCommentPageReqVO extends PageParam {
     @InEnum(ProductCommentScoresEnum.class)
     private Integer scores;
 
-    // TODO @puhui999:replyStatus 哈
     @Schema(description = "商家是否回复", example = "true")
-    private Boolean replied;
+    private Boolean replyStatus;
 
     @Schema(description = "创建时间")
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentRespVO.java
index a75e9ec0c..9205e34cc 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentRespVO.java
@@ -5,6 +5,7 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.ToString;
 
+import javax.validation.constraints.NotNull;
 import java.time.LocalDateTime;
 
 @Schema(description = "管理后台 - 商品评价 Response VO")
@@ -40,4 +41,15 @@ public class ProductCommentRespVO extends ProductCommentBaseVO {
     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime createTime;
 
+    @Schema(description = "评分星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
+    private Integer scores;
+
+    @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑透气小短袖")
+    @NotNull(message = "商品 SPU 编号不能为空")
+    private Long spuId;
+
+    @Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
+    @NotNull(message = "商品 SPU 名称不能为空")
+    private String spuName;
+
 }
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
index 0df57ca4f..e1c70f01c 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
@@ -21,6 +21,7 @@ import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
 import javax.validation.Valid;
 import java.io.IOException;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
@@ -29,11 +30,6 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
 
-/**
- * 商品 SPU 相关接口
- *
- * @author HUIHUI
- */
 @Tag(name = "管理后台 - 商品 SPU")
 @RestController
 @RequestMapping("/product/spu")
@@ -100,6 +96,15 @@ public class ProductSpuController {
         return success(ProductSpuConvert.INSTANCE.convertList02(list));
     }
 
+    @GetMapping("/list")
+    @Operation(summary = "获得商品 SPU 详情列表")
+    @Parameter(name = "spuIds", description = "spu 编号列表", required = true, example = "[1,2,3]")
+    @PreAuthorize("@ss.hasPermission('product:spu:query')")
+    public CommonResult<List<ProductSpuDetailRespVO>> getSpuList(@RequestParam("spuIds") Collection<Long> spuIds) {
+        return success(ProductSpuConvert.INSTANCE.convertForSpuDetailRespListVO(
+                productSpuService.getSpuList(spuIds), productSkuService.getSkuListBySpuId(spuIds)));
+    }
+
     @GetMapping("/page")
     @Operation(summary = "获得商品 SPU 分页")
     @PreAuthorize("@ss.hasPermission('product:spu:query')")
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuCreateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuCreateReqVO.java
index b2fef56e2..baf6adfab 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuCreateReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuCreateReqVO.java
@@ -9,11 +9,6 @@ import lombok.ToString;
 import javax.validation.Valid;
 import java.util.List;
 
-/**
- * 商品 SPU 创建 Request VO
- *
- * @author HUIHUI
- */
 @Schema(description = "管理后台 - 商品 SPU 创建 Request VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java
index eff229c9d..1be96632d 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java
@@ -8,12 +8,6 @@ import lombok.ToString;
 
 import java.util.List;
 
-/**
- * 商品 SPU 详细 Response VO
- * 包括关联的 SKU 等信息
- *
- * @author HUIHUI
- */
 @Schema(description = "管理后台 - 商品 SPU 详细 Response VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuExportReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuExportReqVO.java
index f1da656d1..3b3dccd7e 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuExportReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuExportReqVO.java
@@ -10,12 +10,7 @@ import java.time.LocalDateTime;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
-/**
- * 商品Spu导出 Request VO,参数和 ProductSpuPageReqVO 是一致的
- *
- * @author HUIHUI
- */
-@Schema(description = "管理后台 - 商品Spu导出 Request VO,参数和 ProductSpuPageReqVO 是一致的")
+@Schema(description = "管理后台 - 商品 SPU 导出 Request VO,参数和 ProductSpuPageReqVO 是一致的")
 @Data
 @NoArgsConstructor
 @AllArgsConstructor
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java
index d428164dd..81cff4210 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java
@@ -11,11 +11,6 @@ import java.time.LocalDateTime;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
-/**
- * 商品 SPU 分页 Request VO
- *
- * @author HUIHUI
- */
 @Schema(description = "管理后台 - 商品 SPU 分页 Request VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java
index 346614ad0..bd35d5b9a 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java
@@ -7,11 +7,6 @@ import lombok.ToString;
 
 import java.time.LocalDateTime;
 
-/**
- * 商品 SPU Response VO
- *
- * @author HUIHUI
- */
 @Schema(description = "管理后台 - 商品 SPU Response VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSimpleRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSimpleRespVO.java
index 1c943a912..7d9d0d05d 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSimpleRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSimpleRespVO.java
@@ -4,11 +4,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.ToString;
 
-/**
- * 商品 SPU 精简 Response VO
- *  TODO 商品 SPU 精简 VO 暂时没有使用到,用到的时候再按需添加\修改属性
- * @author HUIHUI
- */
 @Schema(description = "管理后台 - 商品 SPU 精简 Response VO")
 @Data
 @ToString(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateReqVO.java
index c7c424fa0..bb69eb4cf 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateReqVO.java
@@ -12,11 +12,6 @@ import javax.validation.Valid;
 import javax.validation.constraints.NotNull;
 import java.util.List;
 
-/**
- * 商品 SPU 更新 Request VO
- *
- * @author HUIHUI
- */
 @Schema(description = "管理后台 - 商品 SPU 更新 Request VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java
index 57bda636c..e36e68466 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java
@@ -7,11 +7,6 @@ import lombok.Data;
 
 import javax.validation.constraints.NotNull;
 
-/**
- * 商品 SPU Status 更新 Request VO
- *
- * @author HUIHUI
- */
 @Schema(description = "管理后台 - 商品 SPU Status 更新 Request VO")
 @Data
 public class ProductSpuUpdateStatusReqVO{
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java
index 1bcd4a138..86df8f4bd 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java
@@ -1,18 +1,18 @@
 package cn.iocoder.yudao.module.product.controller.app.comment;
 
 import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.ObjectUtil;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO;
 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStatisticsRespVO;
 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO;
-import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
 import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert;
 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
 import cn.iocoder.yudao.module.product.service.comment.ProductCommentService;
 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
+import com.google.common.collect.Maps;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.Parameters;
@@ -26,11 +26,9 @@ import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
 import javax.validation.Valid;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 
@@ -53,34 +51,24 @@ public class AppProductCommentController {
             @Parameter(name = "spuId", description = "商品 SPU 编号", required = true, example = "1024"),
             @Parameter(name = "count", description = "数量", required = true, example = "10")
     })
-    public CommonResult<List<AppProductCommentRespVO>> getCommentList(@RequestParam("spuId") Long spuId,
-                                                                      @RequestParam(value = "count", defaultValue = "10") Integer count) {
+    public CommonResult<List<AppProductCommentRespVO>> getCommentList(
+            @RequestParam("spuId") Long spuId,
+            @RequestParam(value = "count", defaultValue = "10") Integer count) {
         return success(productCommentService.getCommentList(spuId, count));
     }
 
     @GetMapping("/page")
     @Operation(summary = "获得商品评价分页")
     public CommonResult<PageResult<AppProductCommentRespVO>> getCommentPage(@Valid AppCommentPageReqVO pageVO) {
-        PageResult<AppProductCommentRespVO> page = productCommentService.getCommentPage(pageVO, Boolean.TRUE);
-        // TODO @puhui CollUtils 有简化 convertmap 和 list 的方法
-        Set<Long> skuIds = page.getList().stream().map(AppProductCommentRespVO::getSkuId).collect(Collectors.toSet());
+        // TODO @puhui999:写到 convert 里,可以更简洁哈。
+        PageResult<ProductCommentDO> commentDOPage = productCommentService.getCommentPage(pageVO, Boolean.TRUE);
+        Set<Long> skuIds = CollectionUtils.convertSet(commentDOPage.getList(), ProductCommentDO::getSkuId);
         List<ProductSkuDO> skuList = productSkuService.getSkuList(skuIds);
-        Map<Long, ProductSkuDO> skuDOMap = new HashMap<>(skuIds.size());
+        Map<Long, ProductSkuDO> skuDOMap = Maps.newLinkedHashMapWithExpectedSize(skuIds.size());
         if (CollUtil.isNotEmpty(skuList)) {
-            skuDOMap.putAll(skuList.stream().collect(Collectors.toMap(ProductSkuDO::getId, c -> c)));
+            skuDOMap.putAll(CollectionUtils.convertMap(skuList, ProductSkuDO::getId, c -> c));
         }
-        // TODO @puihui999:下面也可以放到 convert 里哈
-        page.getList().forEach(item -> {
-            // 判断用户是否选择匿名
-            if (ObjectUtil.equal(item.getAnonymous(), true)) {
-                item.setUserNickname(ProductCommentDO.NICKNAME_ANONYMOUS);
-            }
-            ProductSkuDO productSkuDO = skuDOMap.get(item.getSkuId());
-            if (productSkuDO != null) {
-                List<AppProductPropertyValueDetailRespVO> skuProperties = ProductCommentConvert.INSTANCE.convertList01(productSkuDO.getProperties());
-                item.setSkuProperties(skuProperties);
-            }
-        });
+        PageResult<AppProductCommentRespVO> page = ProductCommentConvert.INSTANCE.convertPage02(commentDOPage, skuDOMap);
         return success(page);
     }
 
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentRespVO.java
index d13a2b0ac..2ea3af496 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentRespVO.java
@@ -10,11 +10,6 @@ import javax.validation.constraints.Size;
 import java.time.LocalDateTime;
 import java.util.List;
 
-/**
- * 用户 App - 商品评价详情 Response VO
- *
- * @author HUIHUI
- */
 @Schema(description = "用户 App - 商品评价详情 Response VO")
 @Data
 @ToString(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java
index 170a3f0f4..4e195209c 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java
@@ -1,6 +1,8 @@
 package cn.iocoder.yudao.module.product.convert.comment;
 
+import cn.hutool.core.util.ObjectUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
 import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentCreateReqVO;
@@ -19,6 +21,7 @@ import org.mapstruct.factory.Mappers;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.List;
+import java.util.Map;
 
 /**
  * 商品评价 Convert
@@ -32,19 +35,33 @@ public interface ProductCommentConvert {
 
     ProductCommentRespVO convert(ProductCommentDO bean);
 
-    // TODO @puhui999:这里貌似字段对上,就不用 mapping 了;可以测试下看看哈
-    @Mapping(target = "goodCount", source = "goodCount")
-    @Mapping(target = "mediocreCount", source = "mediocreCount")
-    @Mapping(target = "negativeCount", source = "negativeCount")
+    @Mapping(target = "scores", expression = "java(calculateOverallScore(goodCount, mediocreCount, negativeCount))")
     AppCommentStatisticsRespVO convert(Long goodCount, Long mediocreCount, Long negativeCount);
-
+    @Named("calculateOverallScore")
+    default double calculateOverallScore(long goodCount, long mediocreCount, long negativeCount) {
+        return (goodCount * 5 + mediocreCount * 3 + negativeCount) / (double) (goodCount + mediocreCount + negativeCount);
+    }
+    
     List<ProductCommentRespVO> convertList(List<ProductCommentDO> list);
 
-    List<AppProductPropertyValueDetailRespVO> convertList01(List<ProductSkuDO.Property> properties);
-
     PageResult<ProductCommentRespVO> convertPage(PageResult<ProductCommentDO> page);
 
-    PageResult<AppProductCommentRespVO> convertPage02(PageResult<ProductCommentDO> pageResult);
+    PageResult<AppProductCommentRespVO> convertPage01(PageResult<ProductCommentDO> pageResult);
+
+    default PageResult<AppProductCommentRespVO> convertPage02(PageResult<ProductCommentDO> pageResult,
+                                                              Map<Long, ProductSkuDO> skuMap) {
+        PageResult<AppProductCommentRespVO> page = convertPage01(pageResult);
+        page.getList().forEach(item -> {
+            // 判断用户是否选择匿名
+            if (ObjectUtil.equal(item.getAnonymous(), true)) {
+                item.setUserNickname(ProductCommentDO.NICKNAME_ANONYMOUS);
+            }
+            MapUtils.findAndThen(skuMap, item.getSkuId(),
+                    sku -> item.setSkuProperties(convertList01(sku.getProperties())));
+        });
+        return page;
+    }
+    List<AppProductPropertyValueDetailRespVO> convertList01(List<ProductSkuDO.Property> properties);
 
     /**
      * 计算综合评分
@@ -63,14 +80,19 @@ public interface ProductCommentConvert {
 
     ProductCommentDO convert(ProductCommentCreateReqDTO createReqDTO);
 
-    @Mapping(target = "scores", expression = "java(convertScores(createReqDTO.getDescriptionScores(), createReqDTO.getBenefitScores()))")
+    @Mapping(target = "scores",
+            expression = "java(convertScores(createReqDTO.getDescriptionScores(), createReqDTO.getBenefitScores()))")
     default ProductCommentDO convert(ProductCommentCreateReqDTO createReqDTO, ProductSpuDO spuDO, MemberUserRespDTO user) {
         ProductCommentDO commentDO = convert(createReqDTO);
-        commentDO.setUserId(user.getId());
-        commentDO.setUserNickname(user.getNickname());
-        commentDO.setUserAvatar(user.getAvatar());
-        commentDO.setSpuId(spuDO.getId());
-        commentDO.setSpuName(spuDO.getName());
+        if (user != null) {
+            commentDO.setUserId(user.getId());
+            commentDO.setUserNickname(user.getNickname());
+            commentDO.setUserAvatar(user.getAvatar());
+        }
+        if (spuDO != null) {
+            commentDO.setSpuId(spuDO.getId());
+            commentDO.setSpuName(spuDO.getName());
+        }
         return commentDO;
     }
 
@@ -78,7 +100,8 @@ public interface ProductCommentConvert {
     @Mapping(target = "orderId", constant = "0L")
     @Mapping(target = "orderItemId", constant = "0L")
     @Mapping(target = "anonymous", expression = "java(Boolean.FALSE)")
-    @Mapping(target = "scores", expression = "java(convertScores(createReq.getDescriptionScores(), createReq.getBenefitScores()))")
+    @Mapping(target = "scores",
+            expression = "java(convertScores(createReq.getDescriptionScores(), createReq.getBenefitScores()))")
     ProductCommentDO convert(ProductCommentCreateReqVO createReq);
 
     List<AppProductCommentRespVO> convertList02(List<ProductCommentDO> list);
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
index aaad240a4..5149b699c 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
@@ -18,8 +18,10 @@ import org.mapstruct.factory.Mappers;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 import static cn.hutool.core.util.ObjectUtil.defaultIfNull;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap;
 
 /**
  * 商品 SPU Convert
@@ -107,4 +109,16 @@ public interface ProductSpuConvert {
         return detailRespVO;
     }
 
+    default List<ProductSpuDetailRespVO> convertForSpuDetailRespListVO(List<ProductSpuDO> spus, List<ProductSkuDO> skus) {
+        List<ProductSpuDetailRespVO> vos = new ArrayList<>(spus.size());
+        Map<Long, List<ProductSkuDO>> skuMultiMap = convertMultiMap(skus, ProductSkuDO::getSpuId);
+        // TODO @puhui999:可以直接使用 CollUtils.convertList
+        spus.forEach(spu -> {
+            ProductSpuDetailRespVO detailRespVO = convert03(spu);
+            detailRespVO.setSkus(ProductSkuConvert.INSTANCE.convertList(skuMultiMap.get(spu.getId())));
+            vos.add(detailRespVO);
+        });
+        return vos;
+    }
+
 }
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java
index 1426073a5..d6df94207 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java
@@ -26,6 +26,7 @@ public interface ProductCommentMapper extends BaseMapperX<ProductCommentDO> {
     }
 
     static void appendTabQuery(LambdaQueryWrapperX<ProductCommentDO> queryWrapper, Integer type) {
+        // TODO @puhui999:是不是不用 apply 拉?直接用 mybatis 的方法就好啦
         // 构建好评查询语句:好评计算 总评 >= 4
         if (ObjectUtil.equal(type, AppCommentPageReqVO.GOOD_COMMENT)) {
             queryWrapper.apply("scores >= 4");
@@ -51,11 +52,11 @@ public interface ProductCommentMapper extends BaseMapperX<ProductCommentDO> {
         return selectPage(reqVO, queryWrapper);
     }
 
-    default ProductCommentDO selectByUserIdAndOrderItemIdAndSpuId(Long userId, Long orderItemId, Long spuId) {
+    default ProductCommentDO selectByUserIdAndOrderItemIdAndSpuId(Long userId, Long orderItemId, Long skuId) {
         return selectOne(new LambdaQueryWrapperX<ProductCommentDO>()
                 .eq(ProductCommentDO::getUserId, userId)
                 .eq(ProductCommentDO::getOrderItemId, orderItemId)
-                .eq(ProductCommentDO::getSpuId, spuId));
+                .eq(ProductCommentDO::getSpuId, skuId));
     }
 
     default Long selectCountBySpuId(Long spuId, Boolean visible, Integer type) {
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentService.java
index 7f615677c..2c2b35197 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentService.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentService.java
@@ -54,7 +54,7 @@ public interface ProductCommentService {
      * @param visible 是否可见
      * @return 商品评价分页
      */
-    PageResult<AppProductCommentRespVO> getCommentPage(AppCommentPageReqVO pageVO, Boolean visible);
+    PageResult<ProductCommentDO> getCommentPage(AppCommentPageReqVO pageVO, Boolean visible);
 
     /**
      * 创建商品评论
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java
index b0822e96c..97a3d1562 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java
@@ -81,7 +81,7 @@ public class ProductCommentServiceImpl implements ProductCommentService {
     @Transactional(rollbackFor = Exception.class)
     public void createComment(ProductCommentCreateReqVO createReqVO) {
         // 校验评论
-        validateComment(createReqVO.getSpuId(), createReqVO.getUserId(), createReqVO.getOrderItemId());
+        validateComment(createReqVO.getSkuId(), createReqVO.getUserId(), createReqVO.getOrderItemId());
 
         ProductCommentDO commentDO = ProductCommentConvert.INSTANCE.convert(createReqVO);
         productCommentMapper.insert(commentDO);
@@ -108,11 +108,11 @@ public class ProductCommentServiceImpl implements ProductCommentService {
         return commentDO.getId();
     }
 
-    private void validateComment(Long spuId, Long userId, Long orderItemId) {
+    private void validateComment(Long skuId, Long userId, Long orderItemId) {
         // 判断当前订单的当前商品用户是否评价过
-        ProductCommentDO exist = productCommentMapper.selectByUserIdAndOrderItemIdAndSpuId(userId, orderItemId, spuId);
+        ProductCommentDO exist = productCommentMapper.selectByUserIdAndOrderItemIdAndSpuId(userId, orderItemId, skuId);
         if (null != exist) {
-            throw exception(ORDER_SPU_COMMENT_EXISTS);
+            throw exception(COMMENT_ORDER_EXISTS);
         }
     }
 
@@ -141,23 +141,17 @@ public class ProductCommentServiceImpl implements ProductCommentService {
                 productCommentMapper.selectCountBySpuId(spuId, visible, AppCommentPageReqVO.MEDIOCRE_COMMENT),
                 // 查询商品 id = spuId 的所有差评数量
                 productCommentMapper.selectCountBySpuId(spuId, visible, AppCommentPageReqVO.NEGATIVE_COMMENT)
-        ).setScores(3.0); // TODO @puhui999:这里要实现下;;
+        );
     }
 
     @Override
     public List<AppProductCommentRespVO> getCommentList(Long spuId, Integer count) {
-        // 校验商品 spu 是否存在
-        // TODO @puhui 这里校验可以去掉哈。
-        ProductSpuDO spuDO = validateSpu(spuId);
-        return ProductCommentConvert.INSTANCE.convertList02(productCommentMapper.selectCommentList(spuDO.getId(), count).getList());
+        return ProductCommentConvert.INSTANCE.convertList02(productCommentMapper.selectCommentList(spuId, count).getList());
     }
 
-    // TODO @puhui 可以放到 controller 去 convert 哈
     @Override
-    public PageResult<AppProductCommentRespVO> getCommentPage(AppCommentPageReqVO pageVO, Boolean visible) {
-        // TODO @puhui 可以放到 controller 去 convert 哈
-        return ProductCommentConvert.INSTANCE.convertPage02(
-                productCommentMapper.selectPage(pageVO, visible));
+    public PageResult<ProductCommentDO> getCommentPage(AppCommentPageReqVO pageVO, Boolean visible) {
+        return productCommentMapper.selectPage(pageVO, visible);
     }
 
     @Override
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
index 4c106d1bc..fbc9830bf 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
@@ -90,7 +90,7 @@ public interface ProductSkuService {
      * @param spuIds spu 编码集合
      * @return 商品 sku 集合
      */
-    List<ProductSkuDO> getSkuListBySpuId(List<Long> spuIds);
+    List<ProductSkuDO> getSkuListBySpuId(Collection<Long> spuIds);
 
     /**
      * 通过 spuId 删除 sku 信息
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
index 3f77fbe8d..7c6c5030e 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
@@ -148,7 +148,7 @@ public class ProductSkuServiceImpl implements ProductSkuService {
     }
 
     @Override
-    public List<ProductSkuDO> getSkuListBySpuId(List<Long> spuIds) {
+    public List<ProductSkuDO> getSkuListBySpuId(Collection<Long> spuIds) {
         return productSkuMapper.selectListBySpuId(spuIds);
     }
 
diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java
index 8d3a3d5b8..2f55af837 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java
@@ -10,7 +10,6 @@ import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommen
 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO;
 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO;
 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStatisticsRespVO;
-import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO;
 import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert;
 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
 import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper;
@@ -128,7 +127,7 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest {
         productCommentPageReqVO.setSpuId(spuId);
         productCommentPageReqVO.setSpuName("感冒药");
         productCommentPageReqVO.setScores(ProductCommentScoresEnum.FOUR.getScores());
-        productCommentPageReqVO.setReplied(Boolean.TRUE);
+        productCommentPageReqVO.setReplyStatus(Boolean.TRUE);
 
         PageResult<ProductCommentDO> commentPage = productCommentService.getCommentPage(productCommentPageReqVO);
         PageResult<ProductCommentRespVO> result = ProductCommentConvert.INSTANCE.convertPage(productCommentMapper.selectPage(productCommentPageReqVO));
@@ -138,15 +137,15 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest {
         assertEquals(8, all.getTotal());
 
         // 测试获取所有商品分页评论数据
-        PageResult<AppProductCommentRespVO> result1 = productCommentService.getCommentPage(new AppCommentPageReqVO(), Boolean.TRUE);
+        PageResult<ProductCommentDO> result1 = productCommentService.getCommentPage(new AppCommentPageReqVO(), Boolean.TRUE);
         assertEquals(7, result1.getTotal());
 
         // 测试获取所有商品分页中评数据
-        PageResult<AppProductCommentRespVO> result2 = productCommentService.getCommentPage(new AppCommentPageReqVO().setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE);
+        PageResult<ProductCommentDO> result2 = productCommentService.getCommentPage(new AppCommentPageReqVO().setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE);
         assertEquals(2, result2.getTotal());
 
         // 测试获取指定 spuId 商品分页中评数据
-        PageResult<AppProductCommentRespVO> result3 = productCommentService.getCommentPage(new AppCommentPageReqVO().setSpuId(spuId).setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE);
+        PageResult<ProductCommentDO> result3 = productCommentService.getCommentPage(new AppCommentPageReqVO().setSpuId(spuId).setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE);
         assertEquals(2, result3.getTotal());
 
         // 测试分页 tab count
diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java
new file mode 100644
index 000000000..ae1cf7f18
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java
@@ -0,0 +1,49 @@
+package cn.iocoder.yudao.module.promotion.api.combination;
+
+import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordReqDTO;
+
+import javax.validation.Valid;
+
+// TODO @puhui999:CombinationRecordApi 分成活动、记录哈
+// TODO @芋艿:后面也再撸撸这几个接口
+/**
+ * 拼团活动 API 接口
+ *
+ * @author HUIHUI
+ */
+public interface CombinationApi {
+
+    /**
+     * 创建开团记录
+     *
+     * @param reqDTO 请求 DTO
+     */
+    void createRecord(@Valid CombinationRecordReqDTO reqDTO);
+
+    /**
+     * 获取开团记录状态
+     *
+     * @param userId  用户编号
+     * @param orderId 订单编号
+     */
+    boolean validateRecordStatusIsSuccess(Long userId, Long orderId);
+
+    /**
+     * 更新开团记录状态
+     *
+     * @param userId  用户编号
+     * @param orderId 订单编号
+     * @param status  状态值
+     */
+    void updateRecordStatus(Long userId, Long orderId, Integer status);
+
+    /**
+     * 更新开团记录状态和开始时间
+     *
+     * @param userId  用户编号
+     * @param orderId 订单编号
+     * @param status  状态值
+     */
+    void updateRecordStatusAndStartTime(Long userId, Long orderId, Integer status);
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordReqDTO.java
new file mode 100644
index 000000000..122a9a89a
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordReqDTO.java
@@ -0,0 +1,78 @@
+package cn.iocoder.yudao.module.promotion.api.combination.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+// TODO @puhui999:CombinationRecordCreateReqDTO,这样更容易知道是创建噢
+/**
+ * 拼团记录 Request DTO
+ *
+ * @author HUIHUI
+ */
+@Data
+public class CombinationRecordReqDTO {
+
+    /**
+     * 拼团活动编号
+     */
+    @NotNull(message = "拼团活动编号不能为空")
+    private Long activityId;
+    /**
+     * spu 编号
+     */
+    @NotNull(message = "spu 编号不能为空")
+    private Long spuId;
+    /**
+     * sku 编号
+     */
+    @NotNull(message = "sku 编号不能为空")
+    private Long skuId;
+    /**
+     * 用户编号
+     */
+    @NotNull(message = "用户编号不能为空")
+    private Long userId;
+    /**
+     * 订单编号
+     */
+    @NotNull(message = "订单编号不能为空")
+    private Long orderId;
+    /**
+     * 团长编号
+     */
+    @NotNull(message = "团长编号不能为空")
+    private Long headId;
+    /**
+     * 商品名字
+     */
+    @NotEmpty(message = "商品名字不能为空")
+    private String spuName;
+    /**
+     * 商品图片
+     */
+    @NotEmpty(message = "商品图片不能为空")
+    private String picUrl;
+    /**
+     * 拼团商品单价
+     */
+    @NotNull(message = "拼团商品单价不能为空")
+    private Integer combinationPrice;
+    /**
+     * 用户昵称
+     */
+    @NotEmpty(message = "用户昵称不能为空")
+    private String nickname;
+    /**
+     * 用户头像
+     */
+    @NotEmpty(message = "用户头像不能为空")
+    private String avatar;
+    /**
+     * 开团状态:正在开团 拼团成功 拼团失败 TODO 等待支付
+     */
+    @NotNull(message = "开团状态不能为空")
+    private Integer status;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
index 945709697..a504d810c 100644
--- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
@@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
 
 /**
  * Promotion 错误码枚举类
- *
+ * <p>
  * promotion 系统,使用 1-013-000-000 段
  */
 public interface ErrorCodeConstants {
@@ -42,8 +42,7 @@ public interface ErrorCodeConstants {
     ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013006004, "满减送活动已关闭,不能重复关闭");
     ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1013006005, "满减送活动已结束,不能关闭");
 
-    // ========== Price 相关 1013007000 ============
-    ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1013007000, "支付价格计算异常,原因:价格小于等于 0");
+    // ========== TODO 空着 1013007000 ============
 
     // ========== 秒杀活动 1013008000 ==========
     ErrorCode SECKILL_ACTIVITY_NOT_EXISTS = new ErrorCode(1013008000, "秒杀活动不存在");
@@ -58,5 +57,13 @@ public interface ErrorCodeConstants {
     ErrorCode SECKILL_TIME_CONFLICTS = new ErrorCode(1013009001, "秒杀时段冲突");
     ErrorCode SECKILL_TIME_EQUAL = new ErrorCode(1013009002, "秒杀时段开始时间和结束时间不能相等");
     ErrorCode SECKILL_START_TIME_BEFORE_END_TIME = new ErrorCode(1013009003, "秒杀时段开始时间不能在结束时间之后");
+    ErrorCode SECKILL_TIME_DISABLE = new ErrorCode(1013009004, "秒杀时段已关闭");
+
+    // ========== 拼团活动 1013010000 ==========
+    ErrorCode COMBINATION_ACTIVITY_NOT_EXISTS = new ErrorCode(1013010000, "拼团活动不存在");
+    ErrorCode COMBINATION_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013010001, "存在商品参加了其它拼团活动");
+    ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013010002, "拼团活动已关闭不能修改");
+    ErrorCode COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013010003, "拼团活动未关闭或未结束,不能删除");
+    ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1013010004, "拼团不存在");
 
 }
diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/combination/CombinationRecordStatusEnum.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/combination/CombinationRecordStatusEnum.java
new file mode 100644
index 000000000..ee9fc4144
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/combination/CombinationRecordStatusEnum.java
@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.module.promotion.enums.combination;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * 拼团状态枚举
+ *
+ * @author HUIHUI
+ */
+@AllArgsConstructor
+@Getter
+public enum CombinationRecordStatusEnum implements IntArrayValuable {
+
+    WAITING(0, "未付款"),
+    IN_PROGRESS(1, "进行中"),
+    SUCCESS(2, "拼团成功"),
+    FAILED(3, "拼团失败");
+
+    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CombinationRecordStatusEnum::getStatus).toArray();
+
+    /**
+     * 状态值
+     */
+    private final Integer status;
+    /**
+     * 状态名
+     */
+    private final String name;
+
+    @Override
+    public int[] array() {
+        return ARRAYS;
+    }
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java
new file mode 100644
index 000000000..ea3cdc35a
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java
@@ -0,0 +1,42 @@
+package cn.iocoder.yudao.module.promotion.api.combination;
+
+import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordReqDTO;
+import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
+
+/**
+ * 拼团活动 API 实现类
+ *
+ * @author HUIHUI
+ */
+@Service
+public class CombinationApiImpl implements CombinationApi {
+
+    @Resource
+    private CombinationActivityService activityService;
+
+    @Override
+    public void createRecord(CombinationRecordReqDTO reqDTO) {
+        activityService.createRecord(reqDTO);
+    }
+
+    @Override
+    public boolean validateRecordStatusIsSuccess(Long userId, Long orderId) {
+        return activityService.validateRecordStatusIsSuccess(userId, orderId);
+    }
+
+    @Override
+    public void updateRecordStatus(Long userId, Long orderId, Integer status) {
+        activityService.updateRecordStatusByUserIdAndOrderId(userId, orderId, status);
+    }
+
+    @Override
+    public void updateRecordStatusAndStartTime(Long userId, Long orderId, Integer status) {
+        activityService.updateRecordStatusAndStartTimeByUserIdAndOrderId(userId, orderId, status, LocalDateTime.now());
+    }
+
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java
new file mode 100644
index 000000000..53fa9dedf
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java
@@ -0,0 +1,114 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.combination;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
+import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
+import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.*;
+import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationActivityDO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationProductDO;
+import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+import static cn.hutool.core.collection.CollectionUtil.newArrayList;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
+
+@Tag(name = "管理后台 - 拼团活动")
+@RestController
+@RequestMapping("/promotion/combination-activity")
+@Validated
+public class CombinationActivityController {
+
+    @Resource
+    private CombinationActivityService combinationActivityService;
+    @Resource
+    private ProductSpuApi spuApi;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建拼团活动")
+    @PreAuthorize("@ss.hasPermission('promotion:combination-activity:create')")
+    public CommonResult<Long> createCombinationActivity(@Valid @RequestBody CombinationActivityCreateReqVO createReqVO) {
+        return success(combinationActivityService.createCombinationActivity(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新拼团活动")
+    @PreAuthorize("@ss.hasPermission('promotion:combination-activity:update')")
+    public CommonResult<Boolean> updateCombinationActivity(@Valid @RequestBody CombinationActivityUpdateReqVO updateReqVO) {
+        combinationActivityService.updateCombinationActivity(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除拼团活动")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('promotion:combination-activity:delete')")
+    public CommonResult<Boolean> deleteCombinationActivity(@RequestParam("id") Long id) {
+        combinationActivityService.deleteCombinationActivity(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得拼团活动")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')")
+    public CommonResult<CombinationActivityRespVO> getCombinationActivity(@RequestParam("id") Long id) {
+        CombinationActivityDO activity = combinationActivityService.getCombinationActivity(id);
+        List<CombinationProductDO> products = combinationActivityService.getProductsByActivityIds(newArrayList(id));
+        return success(CombinationActivityConvert.INSTANCE.convert(activity, products));
+    }
+
+    @GetMapping("/list")
+    @Operation(summary = "获得拼团活动列表")
+    @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
+    @PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')")
+    public CommonResult<List<CombinationActivityRespVO>> getCombinationActivityList(@RequestParam("ids") Collection<Long> ids) {
+        List<CombinationActivityDO> list = combinationActivityService.getCombinationActivityList(ids);
+        return success(CombinationActivityConvert.INSTANCE.convertList(list));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得拼团活动分页")
+    @PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')")
+    public CommonResult<PageResult<CombinationActivityRespVO>> getCombinationActivityPage(
+            @Valid CombinationActivityPageReqVO pageVO) {
+        PageResult<CombinationActivityDO> pageResult = combinationActivityService.getCombinationActivityPage(pageVO);
+        // TODO @puhui999:可以不一定 aIds,直接批量查询结果出来;下面也是类似;
+        Set<Long> aIds = CollectionUtils.convertSet(pageResult.getList(), CombinationActivityDO::getId);
+        List<CombinationProductDO> products = combinationActivityService.getProductsByActivityIds(aIds);
+        Set<Long> spuIds = CollectionUtils.convertSet(pageResult.getList(), CombinationActivityDO::getSpuId);
+        List<ProductSpuRespDTO> spus = spuApi.getSpuList(spuIds);
+        return success(CombinationActivityConvert.INSTANCE.convertPage(pageResult, products, spus));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出拼团活动 Excel")
+    @PreAuthorize("@ss.hasPermission('promotion:combination-activity:export')")
+    @OperateLog(type = EXPORT)
+    public void exportCombinationActivityExcel(@Valid CombinationActivityExportReqVO exportReqVO,
+                                               HttpServletResponse response) throws IOException {
+        List<CombinationActivityDO> list = combinationActivityService.getCombinationActivityList(exportReqVO);
+        // 导出 Excel
+        List<CombinationActivityExcelVO> datas = CombinationActivityConvert.INSTANCE.convertList02(list);
+        ExcelUtils.write(response, "拼团活动.xls", "数据", CombinationActivityExcelVO.class, datas);
+    }
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityBaseVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityBaseVO.java
new file mode 100644
index 000000000..4ca519fed
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityBaseVO.java
@@ -0,0 +1,49 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import javax.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+/**
+ * 拼团活动 Base VO,提供给添加、修改、详细的子 VO 使用
+ * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
+ */
+@Data
+public class CombinationActivityBaseVO {
+
+    @Schema(description = "拼团名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "越拼越省钱")
+    @NotNull(message = "拼团名称不能为空")
+    private String name;
+
+    @Schema(description = "商品 SPU 编号,关联 ProductSpuDO 的 id", example = "[1,2,3]")
+    @NotNull(message = "拼团商品不能为空")
+    private Long spuId;
+
+    @Schema(description = "总限购数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "16218")
+    @NotNull(message = "总限购数量不能为空")
+    private Integer totalLimitCount;
+
+    @Schema(description = "单次限购数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "28265")
+    @NotNull(message = "单次限购数量不能为空")
+    private Integer singleLimitCount;
+
+    // TODO @puhui999:是不是弄成 2 个字段会好点哈。开始、结束
+    @Schema(description = "活动时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
+    @NotNull(message = "活动时间不能为空")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] activityTime;
+
+    @Schema(description = "开团人数", requiredMode = Schema.RequiredMode.REQUIRED, example = "25222")
+    @NotNull(message = "开团人数不能为空")
+    private Integer userSize;
+
+    @Schema(description = "限制时长(小时)", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "限制时长不能为空")
+    private Integer limitDuration;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityCreateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityCreateReqVO.java
new file mode 100644
index 000000000..ea7879e4e
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityCreateReqVO.java
@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity;
+
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductCreateReqVO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import javax.validation.Valid;
+import java.util.List;
+
+@Schema(description = "管理后台 - 拼团活动创建 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class CombinationActivityCreateReqVO extends CombinationActivityBaseVO {
+
+    @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED)
+    @Valid
+    private List<CombinationProductCreateReqVO> products;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityExcelVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityExcelVO.java
new file mode 100644
index 000000000..c4a91c515
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityExcelVO.java
@@ -0,0 +1,65 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity;
+
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+// TODO @puhui999:如无必要,导出都可以删除哈
+/**
+ * 拼团活动 Excel VO
+ *
+ * @author HUIHUI
+ */
+@Data
+public class CombinationActivityExcelVO {
+
+    @ExcelProperty("活动编号")
+    private Long id;
+
+    @ExcelProperty("拼团名称")
+    private String name;
+
+    @ExcelProperty("商品 SPU 编号关联 ProductSpuDO 的 id")
+    private Long spuId;
+
+    @ExcelProperty("总限购数量")
+    private Integer totalLimitCount;
+
+    @ExcelProperty("单次限购数量")
+    private Integer singleLimitCount;
+
+    @ExcelProperty("开始时间")
+    private LocalDateTime startTime;
+
+    @ExcelProperty("结束时间")
+    private LocalDateTime endTime;
+
+    @ExcelProperty("开团人数")
+    private Integer userSize;
+
+    @ExcelProperty("开团组数")
+    private Integer totalNum;
+
+    @ExcelProperty("成团组数")
+    private Integer successNum;
+
+    @ExcelProperty("参与人数")
+    private Integer orderUserCount;
+
+    @ExcelProperty("虚拟成团")
+    private Integer virtualGroup;
+
+    @ExcelProperty(value = "活动状态:0开启 1关闭", converter = DictConvert.class)
+    @DictFormat("common_status") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中
+    private Integer status;
+
+    @ExcelProperty("限制时长(小时)")
+    private Integer limitDuration;
+
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityExportReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityExportReqVO.java
new file mode 100644
index 000000000..a5cbbd9db
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityExportReqVO.java
@@ -0,0 +1,61 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+// TODO @puhui999:如无必要,导出都可以删除哈
+@Schema(description = "管理后台 - 拼团活动 Excel 导出 Request VO,参数和 CombinationActivityPageReqVO 是一致的")
+@Data
+public class CombinationActivityExportReqVO {
+
+    @Schema(description = "拼团名称", example = "赵六")
+    private String name;
+
+    @Schema(description = "商品 SPU 编号关联 ProductSpuDO 的 id", example = "14016")
+    private Long spuId;
+
+    @Schema(description = "总限购数量", example = "16218")
+    private Integer totalLimitCount;
+
+    @Schema(description = "单次限购数量", example = "28265")
+    private Integer singleLimitCount;
+
+    @Schema(description = "开始时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] startTime;
+
+    @Schema(description = "结束时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] endTime;
+
+    @Schema(description = "开团人数")
+    private Integer userSize;
+
+    @Schema(description = "开团组数")
+    private Integer totalNum;
+
+    @Schema(description = "成团组数")
+    private Integer successNum;
+
+    @Schema(description = "参与人数", example = "25222")
+    private Integer orderUserCount;
+
+    @Schema(description = "虚拟成团")
+    private Integer virtualGroup;
+
+    @Schema(description = "活动状态:0开启 1关闭", example = "0")
+    private Integer status;
+
+    @Schema(description = "限制时长(小时)")
+    private Integer limitDuration;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityPageReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityPageReqVO.java
new file mode 100644
index 000000000..bcd06fdc8
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityPageReqVO.java
@@ -0,0 +1,65 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 拼团活动分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class CombinationActivityPageReqVO extends PageParam {
+
+    @Schema(description = "拼团名称", example = "赵六")
+    private String name;
+
+    @Schema(description = "商品 SPU 编号关联 ProductSpuDO 的 id", example = "14016")
+    private Long spuId;
+
+    @Schema(description = "总限购数量", example = "16218")
+    private Integer totalLimitCount;
+
+    @Schema(description = "单次限购数量", example = "28265")
+    private Integer singleLimitCount;
+
+    @Schema(description = "开始时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] startTime;
+
+    @Schema(description = "结束时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] endTime;
+
+    @Schema(description = "开团人数")
+    private Integer userSize;
+
+    @Schema(description = "开团组数")
+    private Integer totalNum;
+
+    @Schema(description = "成团组数")
+    private Integer successNum;
+
+    @Schema(description = "参与人数", example = "25222")
+    private Integer orderUserCount;
+
+    @Schema(description = "虚拟成团")
+    private Integer virtualGroup;
+
+    @Schema(description = "活动状态:0开启 1关闭", example = "0")
+    private Integer status;
+
+    @Schema(description = "限制时长(小时)")
+    private Integer limitDuration;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java
new file mode 100644
index 000000000..eea1f624d
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java
@@ -0,0 +1,56 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity;
+
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductRespVO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Schema(description = "管理后台 - 拼团活动 Response VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class CombinationActivityRespVO extends CombinationActivityBaseVO {
+
+    @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618大促")
+    private String spuName;
+
+    @Schema(description = "商品主图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png")
+    private String picUrl;
+
+    @Schema(description = "活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22901")
+    private Long id;
+
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    private LocalDateTime createTime;
+
+    @Schema(description = "开团人数", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "开团人数不能为空")
+    private Integer userSize;
+
+    @Schema(description = "开团组数", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "开团组数不能为空")
+    private Integer totalNum;
+
+    @Schema(description = "成团组数", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "成团组数不能为空")
+    private Integer successNum;
+
+    @Schema(description = "虚拟成团", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "虚拟成团不能为空")
+    private Integer virtualGroup;
+
+    @Schema(description = "活动状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
+    @NotNull(message = "活动状态不能为空")
+    private Integer status;
+
+    @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED)
+    @Valid
+    private List<CombinationProductRespVO> products;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityUpdateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityUpdateReqVO.java
new file mode 100644
index 000000000..c4f8cf0c3
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityUpdateReqVO.java
@@ -0,0 +1,27 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity;
+
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductUpdateReqVO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+@Schema(description = "管理后台 - 拼团活动更新 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class CombinationActivityUpdateReqVO extends CombinationActivityBaseVO {
+
+    @Schema(description = "活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22901")
+    @NotNull(message = "活动编号不能为空")
+    private Long id;
+
+    @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED)
+    @Valid
+    private List<CombinationProductUpdateReqVO> products;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductBaseVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductBaseVO.java
new file mode 100644
index 000000000..fac9cddd0
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductBaseVO.java
@@ -0,0 +1,27 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * 拼团商品 Base VO,提供给添加、修改、详细的子 VO 使用
+ * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
+ */
+@Data
+public class CombinationProductBaseVO {
+
+    @Schema(description = "商品 spuId", requiredMode = Schema.RequiredMode.REQUIRED, example = "30563")
+    @NotNull(message = "商品 spuId 不能为空")
+    private Long spuId;
+
+    @Schema(description = "商品 skuId", requiredMode = Schema.RequiredMode.REQUIRED, example = "30563")
+    @NotNull(message = "商品 skuId 不能为空")
+    private Long skuId;
+
+    @Schema(description = "拼团价格,单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "27682")
+    @NotNull(message = "拼团价格,单位分不能为空")
+    private Integer activePrice;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductCreateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductCreateReqVO.java
new file mode 100644
index 000000000..ee805bccc
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductCreateReqVO.java
@@ -0,0 +1,14 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+@Schema(description = "管理后台 - 拼团商品创建 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class CombinationProductCreateReqVO extends CombinationProductBaseVO {
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductExcelVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductExcelVO.java
new file mode 100644
index 000000000..dae0bce7e
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductExcelVO.java
@@ -0,0 +1,44 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+// TODO @puhui999:可以考虑删除 excel 导出哈
+/**
+ * 拼团商品 Excel VO
+ *
+ * @author HUIHUI
+ */
+@Data
+public class CombinationProductExcelVO {
+
+    @ExcelProperty("编号")
+    private Long id;
+
+    @ExcelProperty("拼团活动编号")
+    private Long activityId;
+
+    @ExcelProperty("商品 SPU 编号")
+    private Long spuId;
+
+    @ExcelProperty("商品 SKU 编号")
+    private Long skuId;
+
+    @ExcelProperty("拼团商品状态")
+    private Integer activityStatus;
+
+    @ExcelProperty("活动开始时间点")
+    private LocalDateTime activityStartTime;
+
+    @ExcelProperty("活动结束时间点")
+    private LocalDateTime activityEndTime;
+
+    @ExcelProperty("拼团价格,单位分")
+    private Integer activePrice;
+
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductExportReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductExportReqVO.java
new file mode 100644
index 000000000..65a1d08e8
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductExportReqVO.java
@@ -0,0 +1,43 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+// TODO @puhui999:可以考虑删除 excel 导出哈
+@Schema(description = "管理后台 - 拼团商品 Excel 导出 Request VO,参数和 CombinationProductPageReqVO 是一致的")
+@Data
+public class CombinationProductExportReqVO {
+
+    @Schema(description = "拼团活动编号", example = "6829")
+    private Long activityId;
+
+    @Schema(description = "商品 SPU 编号", example = "18731")
+    private Long spuId;
+
+    @Schema(description = "商品 SKU 编号", example = "31675")
+    private Long skuId;
+
+    @Schema(description = "拼团商品状态", example = "2")
+    private Integer activityStatus;
+
+    @Schema(description = "活动开始时间点")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] activityStartTime;
+
+    @Schema(description = "活动结束时间点")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] activityEndTime;
+
+    @Schema(description = "拼团价格,单位分", example = "27682")
+    private Integer activePrice;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductPageReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductPageReqVO.java
new file mode 100644
index 000000000..02bcc070c
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductPageReqVO.java
@@ -0,0 +1,47 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 拼团商品分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class CombinationProductPageReqVO extends PageParam {
+
+    @Schema(description = "拼团活动编号", example = "6829")
+    private Long activityId;
+
+    @Schema(description = "商品 SPU 编号", example = "18731")
+    private Long spuId;
+
+    @Schema(description = "商品 SKU 编号", example = "31675")
+    private Long skuId;
+
+    @Schema(description = "拼团商品状态", example = "2")
+    private Integer activityStatus;
+
+    @Schema(description = "活动开始时间点")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] activityStartTime;
+
+    @Schema(description = "活动结束时间点")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] activityEndTime;
+
+    @Schema(description = "拼团价格,单位分", example = "27682")
+    private Integer activePrice;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductRespVO.java
new file mode 100644
index 000000000..eeac5c3b5
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductRespVO.java
@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 拼团商品 Response VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class CombinationProductRespVO extends CombinationProductBaseVO {
+
+    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28322")
+    private Long id;
+
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductUpdateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductUpdateReqVO.java
new file mode 100644
index 000000000..5fab798da
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductUpdateReqVO.java
@@ -0,0 +1,14 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+@Schema(description = "管理后台 - 拼团商品更新 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class CombinationProductUpdateReqVO extends CombinationProductBaseVO {
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java
index ba750b296..0631bfc11 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java
@@ -2,6 +2,9 @@ package cn.iocoder.yudao.module.promotion.controller.admin.seckill;
 
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
+import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.*;
 import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
@@ -18,6 +21,7 @@ import javax.annotation.Resource;
 import javax.validation.Valid;
 import java.util.Collection;
 import java.util.List;
+import java.util.Set;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 
@@ -29,6 +33,8 @@ public class SeckillActivityController {
 
     @Resource
     private SeckillActivityService seckillActivityService;
+    @Resource
+    private ProductSpuApi spuApi;
 
     @PostMapping("/create")
     @Operation(summary = "创建秒杀活动")
@@ -69,11 +75,8 @@ public class SeckillActivityController {
     @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')")
     public CommonResult<SeckillActivityDetailRespVO> getSeckillActivity(@RequestParam("id") Long id) {
         SeckillActivityDO seckillActivity = seckillActivityService.getSeckillActivity(id);
-        if (seckillActivity == null) {
-            return success(null);
-        }
-        List<SeckillProductDO> seckillProducts =  seckillActivityService.getSeckillProductListByActivityId(id);
-        return success(SeckillActivityConvert.INSTANCE.convert(seckillActivity,seckillProducts));
+        List<SeckillProductDO> seckillProducts = seckillActivityService.getSeckillProductListByActivityId(id);
+        return success(SeckillActivityConvert.INSTANCE.convert(seckillActivity, seckillProducts));
     }
 
     @GetMapping("/list")
@@ -90,7 +93,11 @@ public class SeckillActivityController {
     @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')")
     public CommonResult<PageResult<SeckillActivityRespVO>> getSeckillActivityPage(@Valid SeckillActivityPageReqVO pageVO) {
         PageResult<SeckillActivityDO> pageResult = seckillActivityService.getSeckillActivityPage(pageVO);
-        return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult));
+        Set<Long> aIds = CollectionUtils.convertSet(pageResult.getList(), SeckillActivityDO::getId);
+        List<SeckillProductDO> seckillProducts = seckillActivityService.getSeckillProductListByActivityId(aIds);
+        Set<Long> spuIds = CollectionUtils.convertSet(pageResult.getList(), SeckillActivityDO::getSpuId);
+        List<ProductSpuRespDTO> spuList = spuApi.getSpuList(spuIds);
+        return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult, seckillProducts, spuList));
     }
 
 }
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java
index 628c6d1c2..671b1f61b 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java
@@ -19,11 +19,6 @@ import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 
-/**
- * 管理后台 - 秒杀时段相关接口
- *
- * @author HUIHUI
- */
 @Tag(name = "管理后台 - 秒杀时段")
 @RestController
 @RequestMapping("/promotion/seckill-config")
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityBaseVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityBaseVO.java
index ac1126d8c..504d4a057 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityBaseVO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityBaseVO.java
@@ -20,10 +20,9 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
 @Data
 public class SeckillActivityBaseVO {
 
-    // TODO @puhui999:对应单 spuId 哈
     @Schema(description = "秒杀活动商品id", requiredMode = Schema.RequiredMode.REQUIRED, example = "[121,1212]")
     @NotNull(message = "秒杀活动商品不能为空")
-    private List<Long> spuIds;
+    private Long spuId;
 
     @Schema(description = "秒杀活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618大促")
     @NotNull(message = "秒杀活动名称不能为空")
@@ -56,8 +55,4 @@ public class SeckillActivityBaseVO {
     @Schema(description = "单次限够数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "31683")
     private Integer singleLimitCount;
 
-    // TODO @puhui999:这个应该是计算出来的字段,只返回,create 和 update 不用哈
-    @Schema(description = "秒杀总库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
-    private Integer totalStock;
-
 }
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java
index 64f5c301a..ad78a9464 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java
@@ -6,26 +6,46 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.ToString;
 
+import java.time.LocalDateTime;
 import java.util.List;
 
-/**
- * 管理后台 - 秒杀活动 Response VO
- *
- * @author HUIHUI
- */
 @Schema(description = "管理后台 - 秒杀活动 Response VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
 public class SeckillActivityRespVO extends SeckillActivityBaseVO {
 
+    @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618大促")
+    private String spuName;
+
+    @Schema(description = "商品主图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png")
+    private String picUrl;
+
     @Schema(description = "秒杀活动id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Long id;
 
     @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED)
-    private List<SeckillProductRespVO> products; // TODO puhui: 考虑是否去除
+    private List<SeckillProductRespVO> products;
 
     @Schema(description = "活动状态 开启:0 禁用:1", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
     private Integer status;
 
+    @Schema(description = "订单实付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "22354")
+    private Integer totalPrice;
+
+    @Schema(description = "秒杀库存", example = "10")
+    private Integer stock;
+
+    @Schema(description = "秒杀总库存", example = "20")
+    private Integer totalStock;
+
+    @Schema(description = "新增订单数", example = "20")
+    private Integer orderCount;
+
+    @Schema(description = "付款人数", example = "20")
+    private Integer userCount;
+
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    private LocalDateTime createTime;
+
 }
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigBaseVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigBaseVO.java
index 27b69b2b1..78a1c51df 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigBaseVO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigBaseVO.java
@@ -1,9 +1,13 @@
 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
+import javax.validation.constraints.AssertTrue;
 import javax.validation.constraints.NotNull;
+import java.time.LocalTime;
+import java.util.List;
 
 /**
  * 秒杀时段 Base VO,提供给添加、修改、详细的子 VO 使用
@@ -26,12 +30,24 @@ public class SeckillConfigBaseVO {
     @NotNull(message = "结束时间点不能为空")
     private String endTime;
 
-    @Schema(description = "秒杀主图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn")
-    @NotNull(message = "秒杀主图不能为空")
-    private String picUrl;
+    @Schema(description = "秒杀轮播图", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/xx.png]")
+    @NotNull(message = "秒杀轮播图不能为空")
+    private List<String> sliderPicUrls;
 
     @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
     @NotNull(message = "状态不能为空")
     private Integer status;
 
+    @AssertTrue(message = "秒杀时段开始时间和结束时间不能相等")
+    @JsonIgnore
+    public boolean isValidStartTimeValid() {
+        return !LocalTime.parse(startTime).equals(LocalTime.parse(endTime));
+    }
+
+    @AssertTrue(message = "秒杀时段开始时间不能在结束时间之后")
+    @JsonIgnore
+    public boolean isValidEndTimeValid() {
+        return !LocalTime.parse(startTime).isAfter(LocalTime.parse(endTime));
+    }
+
 }
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigPageReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigPageReqVO.java
index e49a02837..92211385a 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigPageReqVO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigPageReqVO.java
@@ -6,12 +6,6 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.ToString;
 
-// TODO @puhui:VO 上不写注释,已经有注解啦。
-/**
- * 管理后台 - 秒杀时段分页 Request VO
- *
- * @author HUIHUI
- */
 @Schema(description = "管理后台 - 秒杀时段分页 Request VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductBaseVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductBaseVO.java
index 4dba74fe1..a11d78930 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductBaseVO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductBaseVO.java
@@ -14,11 +14,6 @@ import javax.validation.constraints.NotNull;
 @Data
 public class SeckillProductBaseVO {
 
-    // TODO @puhui:spuId 不用传递;因为一个秒杀活动只对应一个 SPU  哈;
-    @Schema(description = "商品spu_id", requiredMode = Schema.RequiredMode.REQUIRED, example = "30563")
-    @NotNull(message = "商品spu_id不能为空")
-    private Long spuId;
-
     @Schema(description = "商品sku_id", requiredMode = Schema.RequiredMode.REQUIRED, example = "30563")
     @NotNull(message = "商品sku_id不能为空")
     private Long skuId;
@@ -31,5 +26,4 @@ public class SeckillProductBaseVO {
     @NotNull(message = "秒杀库存不能为空")
     private Integer stock;
 
-
 }
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductCreateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductCreateReqVO.java
index 9b06f98f6..8ee4884ea 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductCreateReqVO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductCreateReqVO.java
@@ -1,16 +1,9 @@
 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product;
 
-import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO;
-import lombok.*;
-import java.util.*;
 import io.swagger.v3.oas.annotations.media.Schema;
-import javax.validation.constraints.*;
-
-/**
- * 管理后台 - 秒杀参与商品创建 Request VO
- *
- * @author HUIHUI
- */
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
 @Schema(description = "管理后台 - 秒杀参与商品创建 Request VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductRespVO.java
index bb33fab58..96b7eec4c 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductRespVO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductRespVO.java
@@ -1,14 +1,12 @@
 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product;
 
 import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
 import java.time.LocalDateTime;
 
-/**
- * 管理后台 - 秒杀参与商品 Response VO
- *
- * @author HUIHUI
- */
 @Schema(description = "管理后台 - 秒杀参与商品 Response VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductUpdateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductUpdateReqVO.java
index 3f964255a..5fdccf8d0 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductUpdateReqVO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductUpdateReqVO.java
@@ -1,22 +1,14 @@
 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product;
 
 import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.*;
-import javax.validation.constraints.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
 
-/**
- * 管理后台 - 秒杀参与商品更新 Request VO
- *
- * @author HUIHUI
- */
 @Schema(description = "管理后台 - 秒杀参与商品更新 Request VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
 public class SeckillProductUpdateReqVO extends SeckillProductBaseVO {
 
-    @Schema(description = "秒杀参与商品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "256")
-    @NotNull(message = "秒杀参与商品编号不能为空")
-    private Long id;
-
 }
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java
new file mode 100644
index 000000000..61644c9c9
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java
@@ -0,0 +1,138 @@
+package cn.iocoder.yudao.module.promotion.convert.combination;
+
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
+import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordReqDTO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityExcelVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityRespVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductRespVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationActivityDO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationProductDO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationRecordDO;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.Mappings;
+import org.mapstruct.Named;
+import org.mapstruct.factory.Mappers;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+
+/**
+ * 拼团活动 Convert
+ *
+ * @author HUIHUI
+ */
+@Mapper
+public interface CombinationActivityConvert {
+
+    CombinationActivityConvert INSTANCE = Mappers.getMapper(CombinationActivityConvert.class);
+
+    @Mappings({
+            @Mapping(target = "startTime", expression = "java(bean.getActivityTime()[0])"),
+            @Mapping(target = "endTime", expression = "java(bean.getActivityTime()[1])")
+    })
+    CombinationActivityDO convert(CombinationActivityCreateReqVO bean);
+
+    @Mappings({
+            @Mapping(target = "startTime", expression = "java(bean.getActivityTime()[0])"),
+            @Mapping(target = "endTime", expression = "java(bean.getActivityTime()[1])")
+    })
+    CombinationActivityDO convert(CombinationActivityUpdateReqVO bean);
+
+    @Named("mergeTime")
+    default LocalDateTime[] mergeTime(LocalDateTime startTime, LocalDateTime endTime) {
+        // TODO 有点怪第一次这样写 hh
+        LocalDateTime[] localDateTime = new LocalDateTime[2];
+        localDateTime[0] = startTime;
+        localDateTime[1] = endTime;
+        return localDateTime;
+    }
+
+    @Mappings({
+            @Mapping(target = "activityTime", expression = "java(mergeTime(bean.getStartTime(),bean.getEndTime()))")
+    })
+    CombinationActivityRespVO convert(CombinationActivityDO bean);
+
+    CombinationProductRespVO convert(CombinationProductDO bean);
+
+    default CombinationActivityRespVO convert(CombinationActivityDO bean, List<CombinationProductDO> productDOs) {
+        CombinationActivityRespVO respVO = convert(bean);
+        respVO.setProducts(convertList2(productDOs));
+        return respVO;
+    }
+
+    List<CombinationActivityRespVO> convertList(List<CombinationActivityDO> list);
+
+    PageResult<CombinationActivityRespVO> convertPage(PageResult<CombinationActivityDO> page);
+
+    default PageResult<CombinationActivityRespVO> convertPage(PageResult<CombinationActivityDO> page,
+                                                              List<CombinationProductDO> productList,
+                                                              List<ProductSpuRespDTO> spuList) {
+        // TODO @puhui999:c -> c 可以去掉哈
+        Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId, c -> c);
+        PageResult<CombinationActivityRespVO> pageResult = convertPage(page);
+        pageResult.getList().forEach(item -> {
+            // TODO @puhui999:最好 MapUtils.findAndThen,万一没找到呢,啊哈哈。
+            item.setSpuName(spuMap.get(item.getSpuId()).getName());
+            item.setPicUrl(spuMap.get(item.getSpuId()).getPicUrl());
+            item.setProducts(convertList2(productList));
+        });
+        return pageResult;
+    }
+
+    List<CombinationProductRespVO> convertList2(List<CombinationProductDO> productDOs);
+
+    List<CombinationActivityExcelVO> convertList02(List<CombinationActivityDO> list);
+
+    @Mappings({
+            @Mapping(target = "id", ignore = true),
+            @Mapping(target = "activityId", source = "activityDO.id"),
+            @Mapping(target = "spuId", source = "activityDO.spuId"),
+            @Mapping(target = "skuId", source = "vo.skuId"),
+            @Mapping(target = "activePrice", source = "vo.activePrice"),
+            @Mapping(target = "activityStartTime", source = "activityDO.startTime"),
+            @Mapping(target = "activityEndTime", source = "activityDO.endTime")
+    })
+    CombinationProductDO convert(CombinationActivityDO activityDO, CombinationProductBaseVO vo);
+
+    default List<CombinationProductDO> convertList(CombinationActivityDO activityDO, List<? extends CombinationProductBaseVO> products) {
+        List<CombinationProductDO> list = new ArrayList<>();
+        products.forEach(sku -> {
+            CombinationProductDO productDO = convert(activityDO, sku);
+            // TODO 状态设置
+            productDO.setActivityStatus(CommonStatusEnum.ENABLE.getStatus());
+            list.add(productDO);
+        });
+        return list;
+    }
+
+    // TODO @puhui999:这个方法的参数,调整成 productDOs、vos、activityDO;因为 productDOs 是主角;
+    // 然后,这个方法,感觉不是为了 convert,而是为了补全;
+    default List<CombinationProductDO> convertList1(CombinationActivityDO activityDO,
+                                                    List<CombinationProductUpdateReqVO> vos,
+                                                    List<CombinationProductDO> productDOs) {
+        Map<Long, Long> longMap = convertMap(productDOs, CombinationProductDO::getSkuId, CombinationProductDO::getId);
+        List<CombinationProductDO> list = new ArrayList<>();
+        vos.forEach(sku -> {
+            CombinationProductDO productDO = convert(activityDO, sku);
+            productDO.setId(longMap.get(sku.getSkuId()));
+            // TODO @puhui999:是是不是用 activityDO 的状态;
+            productDO.setActivityStatus(CommonStatusEnum.ENABLE.getStatus());
+            list.add(productDO);
+        });
+        return list;
+    }
+
+    CombinationRecordDO convert(CombinationRecordReqDTO reqDTO);
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java
index 7d62b4f2d..e8667870e 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java
@@ -1,20 +1,26 @@
 package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity;
 
-import cn.hutool.core.util.ObjectUtil;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityDetailRespVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityRespVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO;
-import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductCreateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductRespVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductUpdateReqVO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
 import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.Mappings;
 import org.mapstruct.factory.Mappers;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 /**
  * 秒杀活动 Convert
@@ -26,8 +32,6 @@ public interface SeckillActivityConvert {
 
     SeckillActivityConvert INSTANCE = Mappers.getMapper(SeckillActivityConvert.class);
 
-    SeckillProductDO convert(SeckillProductCreateReqVO product);
-
     SeckillActivityDO convert(SeckillActivityCreateReqVO bean);
 
     SeckillActivityDO convert(SeckillActivityUpdateReqVO bean);
@@ -38,53 +42,61 @@ public interface SeckillActivityConvert {
 
     PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page);
 
-    SeckillActivityDetailRespVO convert(SeckillActivityDO seckillActivity, List<SeckillProductDO> seckillProducts);
-
-
-    /**
-     * 比较两个秒杀商品对象是否相等
-     *
-     * @param productDO 数据库中的商品
-     * @param productVO 前端传入的商品
-     * @return 是否匹配
-     */
-    default boolean isEquals(SeckillProductDO productDO, SeckillProductCreateReqVO productVO) {
-        return ObjectUtil.equals(productDO.getSpuId(), 1) // TODO puhui:再看看
-                && ObjectUtil.equals(productDO.getSkuId(), productVO.getSkuId())
-                && ObjectUtil.equals(productDO.getSeckillPrice(), productVO.getSeckillPrice());
-        //&& ObjectUtil.equals(productDO.getQuota(), productVO.getQuota())
-        //&& ObjectUtil.equals(productDO.getLimitCount(), productVO.getLimitCount());
+    default PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page, List<SeckillProductDO> seckillProducts, List<ProductSpuRespDTO> spuList) {
+        Map<Long, ProductSpuRespDTO> spuMap = CollectionUtils.convertMap(spuList, ProductSpuRespDTO::getId, c -> c);
+        PageResult<SeckillActivityRespVO> pageResult = convertPage(page);
+        pageResult.getList().forEach(item -> {
+            item.setSpuName(spuMap.get(item.getSpuId()).getName());
+            item.setPicUrl(spuMap.get(item.getSpuId()).getPicUrl());
+            item.setProducts(convertList2(seckillProducts));
+        });
+        return pageResult;
     }
 
-    /**
-     * 比较两个秒杀商品对象是否相等
-     *
-     * @param productDO 商品1
-     * @param productVO 商品2
-     * @return 是否匹配
-     */
-    default boolean isEquals(SeckillProductDO productDO, SeckillProductDO productVO) {
-        return ObjectUtil.equals(productDO.getSpuId(), productVO.getSpuId())
-                && ObjectUtil.equals(productDO.getSkuId(), productVO.getSkuId())
-                && ObjectUtil.equals(productDO.getSeckillPrice(), productVO.getSeckillPrice());
-        //&& ObjectUtil.equals(productDO.getQuota(), productVO.getQuota())
-        //&& ObjectUtil.equals(productDO.getLimitCount(), productVO.getLimitCount());
+    SeckillActivityDetailRespVO convert1(SeckillActivityDO seckillActivity);
+
+    default SeckillActivityDetailRespVO convert(SeckillActivityDO seckillActivity, List<SeckillProductDO> seckillProducts) {
+        SeckillActivityDetailRespVO respVO = convert1(seckillActivity);
+        respVO.setProducts(convertList2(seckillProducts));
+        return respVO;
     }
 
-    default List<SeckillProductDO> convertList(SeckillActivityDO seckillActivity, List<SeckillProductCreateReqVO> products) {
+    @Mappings({
+            @Mapping(target = "id", ignore = true),
+            @Mapping(target = "activityId", source = "activityDO.id"),
+            @Mapping(target = "configIds", source = "activityDO.configIds"),
+            @Mapping(target = "spuId", source = "activityDO.spuId"),
+            @Mapping(target = "skuId", source = "vo.skuId"),
+            @Mapping(target = "seckillPrice", source = "vo.seckillPrice"),
+            @Mapping(target = "stock", source = "vo.stock"),
+            @Mapping(target = "activityStartTime", source = "activityDO.startTime"),
+            @Mapping(target = "activityEndTime", source = "activityDO.endTime")
+    })
+    SeckillProductDO convert(SeckillActivityDO activityDO, SeckillProductBaseVO vo);
+
+    default List<SeckillProductDO> convertList(SeckillActivityDO activityDO, List<? extends SeckillProductBaseVO> products) {
         List<SeckillProductDO> list = new ArrayList<>();
         products.forEach(sku -> {
-            SeckillProductDO productDO = new SeckillProductDO();
-            productDO.setActivityId(seckillActivity.getId());
-            productDO.setConfigIds(seckillActivity.getConfigIds());
-            productDO.setSpuId(sku.getSpuId());
-            productDO.setSkuId(sku.getSkuId());
-            productDO.setSeckillPrice(sku.getSeckillPrice());
-            productDO.setStock(sku.getStock());
+            SeckillProductDO productDO = convert(activityDO, sku);
             productDO.setActivityStatus(CommonStatusEnum.ENABLE.getStatus());
-            productDO.setActivityStartTime(seckillActivity.getStartTime());
-            productDO.setActivityEndTime(seckillActivity.getEndTime());
+            list.add(productDO);
         });
         return list;
     }
+
+    // TODO @puhui999:同拼团那个 convert 想通的情况哈。
+    default List<SeckillProductDO> convertList1(SeckillActivityDO activityDO, List<SeckillProductUpdateReqVO> vos, List<SeckillProductDO> productDOs) {
+        Map<Long, Long> longMap = CollectionUtils.convertMap(productDOs, SeckillProductDO::getSkuId, SeckillProductDO::getId);
+        List<SeckillProductDO> list = new ArrayList<>();
+        vos.forEach(sku -> {
+            SeckillProductDO productDO = convert(activityDO, sku);
+            productDO.setId(longMap.get(sku.getSkuId()));
+            productDO.setActivityStatus(CommonStatusEnum.ENABLE.getStatus());
+            list.add(productDO);
+        });
+        return list;
+    }
+
+    List<SeckillProductRespVO> convertList2(List<SeckillProductDO> productDOs);
+
 }
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationActivityDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationActivityDO.java
new file mode 100644
index 000000000..c5c08bbd9
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationActivityDO.java
@@ -0,0 +1,90 @@
+package cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity;
+
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+import java.time.LocalDateTime;
+
+// TODO @puhui999:是不是应该在 combination 哈?
+/**
+ * 拼团活动 DO
+ *
+ * @author HUIHUI
+ */
+@TableName("promotion_combination_activity")
+@KeySequence("promotion_combination_activity_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class CombinationActivityDO extends BaseDO {
+
+    /**
+     * 活动编号
+     */
+    @TableId
+    private Long id;
+    /**
+     * 拼团名称
+     */
+    private String name;
+    /**
+     * 商品 SPU 编号
+     *
+     * 关联 ProductSpuDO 的 id
+     */
+    private Long spuId;
+    /**
+     * 总限购数量
+     */
+    private Integer totalLimitCount;
+    /**
+     * 单次限购数量
+     */
+    private Integer singleLimitCount;
+    /**
+     * 开始时间
+     */
+    private LocalDateTime startTime;
+    /**
+     * 结束时间
+     */
+    private LocalDateTime endTime;
+    /**
+     * 几人团
+     */
+    private Integer userSize;
+    /**
+     * 开团组数
+     */
+    private Integer totalNum;
+    /**
+     * 成团组数
+     */
+    private Integer successNum;
+    /**
+     * 参与人数
+     */
+    private Integer orderUserCount;
+    /**
+     * 虚拟成团
+     */
+    private Integer virtualGroup;
+    /**
+     * 活动状态:0开启 1关闭
+     *
+     * 枚举 {@link CommonStatusEnum}
+     */
+    private Integer status;
+    /**
+     * 限制时长(小时)
+     */
+    private Integer limitDuration;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationProductDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationProductDO.java
new file mode 100644
index 000000000..5c4744ee9
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationProductDO.java
@@ -0,0 +1,60 @@
+package cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+import java.time.LocalDateTime;
+
+/**
+ * 拼团商品 DO
+ *
+ * @author HUIHUI
+ */
+@TableName("promotion_combination_product")
+@KeySequence("promotion_combination_product_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class CombinationProductDO extends BaseDO {
+
+    /**
+     * 编号
+     */
+    @TableId
+    private Long id;
+    /**
+     * 拼团活动编号
+     */
+    private Long activityId;
+    /**
+     * 商品 SPU 编号
+     */
+    private Long spuId;
+    /**
+     * 商品 SKU 编号
+     */
+    private Long skuId;
+    /**
+     * 拼团商品状态
+     */
+    private Integer activityStatus;
+    /**
+     * 活动开始时间点
+     */
+    private LocalDateTime activityStartTime;
+    /**
+     * 活动结束时间点
+     */
+    private LocalDateTime activityEndTime;
+    /**
+     * 拼团价格,单位分
+     */
+    private Integer activePrice;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationRecordDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationRecordDO.java
new file mode 100644
index 000000000..3ab41b9ba
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationRecordDO.java
@@ -0,0 +1,110 @@
+package cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+import java.time.LocalDateTime;
+
+/**
+ * 拼团记录 DO
+ *
+ * @author HUIHUI
+ */
+@TableName("promotion_combination_record")
+@KeySequence("promotion_combination_record_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class CombinationRecordDO extends BaseDO {
+
+    @TableId
+    private Long id;
+    /**
+     * 拼团活动编号
+     */
+    private Long activityId;
+    /**
+     * SPU 编号
+     */
+    private Long spuId;
+    /**
+     * SKU 编号
+     */
+    private Long skuId;
+    /**
+     * 用户编号
+     */
+    private Long userId;
+    /**
+     * 订单编号
+     */
+    private Long orderId;
+    /**
+     * 团长编号
+     *
+     * 关联 {@link CombinationRecordDO#getUserId()}
+     */
+    private Long headId;
+    /**
+     * 商品名字
+     */
+    private String spuName;
+    /**
+     * 商品图片
+     */
+    private String picUrl;
+    /**
+     * 拼团商品单价
+     */
+    private Integer combinationPrice;
+    /**
+     * 用户昵称
+     */
+    private String nickname;
+    /**
+     * 用户头像
+     */
+    private String avatar;
+    /**
+     * 开团状态
+     *
+     * 关联 {@link CombinationRecordStatusEnum}
+     */
+    private Integer status;
+    /**
+     * 是否虚拟成团
+     */
+    private Boolean virtualGroup;
+    /**
+     * 过期时间,单位:小时
+     *
+     * 关联 {@link CombinationActivityDO#getLimitDuration()}
+     */
+    private Integer expireTime;
+    /**
+     * 开始时间 (订单付款后开始的时间)
+     */
+    private LocalDateTime startTime;
+    /**
+     * 结束时间(成团时间/失败时间)
+     */
+    private LocalDateTime endTime;
+    /**
+     * 开团需要人数
+     *
+     * 关联 {@link CombinationActivityDO#getUserSize()}
+     */
+    private Integer userSize;
+    /**
+     * 已加入拼团人数
+     */
+    private Integer userCount;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillActivityDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillActivityDO.java
index be6663592..a8c7eb265 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillActivityDO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillActivityDO.java
@@ -34,8 +34,7 @@ public class SeckillActivityDO extends BaseDO {
     /**
      * 秒杀活动商品
      */
-    @TableField(typeHandler = LongListTypeHandler.class)
-    private List<Long> spuIds;
+    private Long spuId;
     /**
      * 秒杀活动名称
      */
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillProductDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillProductDO.java
index cdf206bd9..d3994dfd5 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillProductDO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillProductDO.java
@@ -47,11 +47,11 @@ public class SeckillProductDO extends BaseDO {
     @TableField(typeHandler = LongListTypeHandler.class)
     private List<Long> configIds;
     /**
-     * 商品 spu_id
+     * 商品 SPU 编号
      */
     private Long spuId;
     /**
-     * 商品 sku_id
+     * 商品 SKU 编号
      */
     private Long skuId;
     /**
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillconfig/SeckillConfigDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillconfig/SeckillConfigDO.java
index f8fe41a18..fdaf193a4 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillconfig/SeckillConfigDO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillconfig/SeckillConfigDO.java
@@ -3,22 +3,27 @@ package cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
+import lombok.*;
+
+import java.util.List;
 
 /**
  * 秒杀时段 DO
  *
  * @author 芋道源码
  */
-@TableName("promotion_seckill_config")
+@TableName(value = "promotion_seckill_config", autoResultMap = true)
 @KeySequence("promotion_seckill_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
 public class SeckillConfigDO extends BaseDO {
 
     /**
@@ -38,11 +43,11 @@ public class SeckillConfigDO extends BaseDO {
      * 结束时间点
      */
     private String endTime;
-    // TODO puhui999:应该是轮播图;    private List<String> sliderPicUrls;
     /**
-     * 秒杀主图
+     * 秒杀轮播图
      */
-    private String picUrl;
+    @TableField(typeHandler = JacksonTypeHandler.class)
+    private List<String> sliderPicUrls;
     /**
      * 状态
      *
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationActivityMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationActivityMapper.java
new file mode 100644
index 000000000..12c3cf28a
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationActivityMapper.java
@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityExportReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationActivityDO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+// TODO @puhui999:是不是应该在 combination 哈?
+/**
+ * 拼团活动 Mapper
+ *
+ * @author HUIHUI
+ */
+@Mapper
+public interface CombinationActivityMapper extends BaseMapperX<CombinationActivityDO> {
+
+    default PageResult<CombinationActivityDO> selectPage(CombinationActivityPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<CombinationActivityDO>()
+                .likeIfPresent(CombinationActivityDO::getName, reqVO.getName())
+                .orderByDesc(CombinationActivityDO::getId));
+    }
+
+    default List<CombinationActivityDO> selectList(CombinationActivityExportReqVO reqVO) {
+        return selectList(new LambdaQueryWrapperX<CombinationActivityDO>()
+                .likeIfPresent(CombinationActivityDO::getName, reqVO.getName())
+                .eqIfPresent(CombinationActivityDO::getStatus, reqVO.getStatus())
+                .orderByDesc(CombinationActivityDO::getId));
+    }
+
+    default List<CombinationActivityDO> selectListByStatus(Integer status) {
+        return selectList(CombinationActivityDO::getStatus, status);
+    }
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationProductMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationProductMapper.java
new file mode 100644
index 000000000..ced6de6d4
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationProductMapper.java
@@ -0,0 +1,52 @@
+package cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductExportReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductPageReqVO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationProductDO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 拼团商品 Mapper
+ *
+ * @author HUIHUI
+ */
+@Mapper
+public interface CombinationProductMapper extends BaseMapperX<CombinationProductDO> {
+
+    default PageResult<CombinationProductDO> selectPage(CombinationProductPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<CombinationProductDO>()
+                .eqIfPresent(CombinationProductDO::getActivityId, reqVO.getActivityId())
+                .eqIfPresent(CombinationProductDO::getSpuId, reqVO.getSpuId())
+                .eqIfPresent(CombinationProductDO::getSkuId, reqVO.getSkuId())
+                .eqIfPresent(CombinationProductDO::getActivityStatus, reqVO.getActivityStatus())
+                .betweenIfPresent(CombinationProductDO::getActivityStartTime, reqVO.getActivityStartTime())
+                .betweenIfPresent(CombinationProductDO::getActivityEndTime, reqVO.getActivityEndTime())
+                .eqIfPresent(CombinationProductDO::getActivePrice, reqVO.getActivePrice())
+                .betweenIfPresent(CombinationProductDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(CombinationProductDO::getId));
+    }
+
+    default List<CombinationProductDO> selectList(CombinationProductExportReqVO reqVO) {
+        return selectList(new LambdaQueryWrapperX<CombinationProductDO>()
+                .eqIfPresent(CombinationProductDO::getActivityId, reqVO.getActivityId())
+                .eqIfPresent(CombinationProductDO::getSpuId, reqVO.getSpuId())
+                .eqIfPresent(CombinationProductDO::getSkuId, reqVO.getSkuId())
+                .eqIfPresent(CombinationProductDO::getActivityStatus, reqVO.getActivityStatus())
+                .betweenIfPresent(CombinationProductDO::getActivityStartTime, reqVO.getActivityStartTime())
+                .betweenIfPresent(CombinationProductDO::getActivityEndTime, reqVO.getActivityEndTime())
+                .eqIfPresent(CombinationProductDO::getActivePrice, reqVO.getActivePrice())
+                .betweenIfPresent(CombinationProductDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(CombinationProductDO::getId));
+    }
+
+    default List<CombinationProductDO> selectListByActivityIds(Collection<Long> ids) {
+        return selectList(CombinationProductDO::getActivityId, ids);
+    }
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationRecordMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationRecordMapper.java
new file mode 100644
index 000000000..440767472
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationRecordMapper.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity;
+
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationRecordDO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * 拼团记录 Mapper
+ *
+ * @author HUIHUI
+ */
+@Mapper
+public interface CombinationRecordMapper extends BaseMapperX<CombinationRecordDO> {
+
+    default CombinationRecordDO selectRecord(Long userId, Long orderId) {
+        return selectOne(CombinationRecordDO::getUserId, userId,
+                CombinationRecordDO::getOrderId, orderId);
+    }
+
+    default List<CombinationRecordDO> selectListByHeadIdAndStatus(Long headId, Integer status) {
+        return selectList(new LambdaQueryWrapperX<CombinationRecordDO>()
+                .eq(CombinationRecordDO::getHeadId, headId)
+                .eq(CombinationRecordDO::getStatus, status));
+    }
+
+    default List<CombinationRecordDO> selectListByStatus(Integer status) {
+        return selectList(CombinationRecordDO::getStatus, status);
+    }
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java
index fd6d87bdf..625769901 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java
@@ -21,6 +21,10 @@ public interface SeckillProductMapper extends BaseMapperX<SeckillProductDO> {
         return selectList(SeckillProductDO::getActivityId, id);
     }
 
+    default List<SeckillProductDO> selectListByActivityId(Collection<Long> ids) {
+        return selectList(SeckillProductDO::getActivityId, ids);
+    }
+
     default List<SeckillProductDO> selectListBySkuIds(Collection<Long> skuIds) {
         return selectList(SeckillProductDO::getSkuId, skuIds);
     }
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillconfig/SeckillConfigMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillconfig/SeckillConfigMapper.java
index e94c61949..38bbe18da 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillconfig/SeckillConfigMapper.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillconfig/SeckillConfigMapper.java
@@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.Seck
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
 import org.apache.ibatis.annotations.Mapper;
 
+import java.util.List;
+
 @Mapper
 public interface SeckillConfigMapper extends BaseMapperX<SeckillConfigDO> {
 
@@ -17,4 +19,8 @@ public interface SeckillConfigMapper extends BaseMapperX<SeckillConfigDO> {
                 .orderByDesc(SeckillConfigDO::getId));
     }
 
+    default List<SeckillConfigDO> selectListByStatus(Integer status) {
+        return selectList(SeckillConfigDO::getStatus, status);
+    }
+
 }
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java
new file mode 100644
index 000000000..f4f0865a6
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java
@@ -0,0 +1,123 @@
+package cn.iocoder.yudao.module.promotion.service.combination;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordReqDTO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityExportReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationActivityDO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationProductDO;
+
+import javax.validation.Valid;
+import java.time.LocalDateTime;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 拼团活动 Service 接口
+ *
+ * @author HUIHUI
+ */
+public interface CombinationActivityService {
+
+    /**
+     * 创建拼团活动
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createCombinationActivity(@Valid CombinationActivityCreateReqVO createReqVO);
+
+    /**
+     * 更新拼团活动
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateCombinationActivity(@Valid CombinationActivityUpdateReqVO updateReqVO);
+
+    /**
+     * 删除拼团活动
+     *
+     * @param id 编号
+     */
+    void deleteCombinationActivity(Long id);
+
+    /**
+     * 获得拼团活动
+     *
+     * @param id 编号
+     * @return 拼团活动
+     */
+    CombinationActivityDO getCombinationActivity(Long id);
+
+    /**
+     * 获得拼团活动列表
+     *
+     * @param ids 编号
+     * @return 拼团活动列表
+     */
+    List<CombinationActivityDO> getCombinationActivityList(Collection<Long> ids);
+
+    /**
+     * 获得拼团活动分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 拼团活动分页
+     */
+    PageResult<CombinationActivityDO> getCombinationActivityPage(CombinationActivityPageReqVO pageReqVO);
+
+    /**
+     * 获得拼团活动列表, 用于 Excel 导出
+     *
+     * @param exportReqVO 查询条件
+     * @return 拼团活动列表
+     */
+    List<CombinationActivityDO> getCombinationActivityList(CombinationActivityExportReqVO exportReqVO);
+
+    /**
+     * 获得拼团活动商品列表
+     *
+     * @param ids 拼团活动 ids
+     * @return 拼团活动的商品列表
+     */
+    List<CombinationProductDO> getProductsByActivityIds(Collection<Long> ids);
+
+    // TODO @puhui999:拆一个 CombinationRecordService 里,方法名可以简洁成 updateRecordStatusByOrderId;service 方法可以稍微简单一点,如果是 update 方法
+    /**
+     * 更新拼团状态
+     *
+     * @param userId  用户编号
+     * @param orderId 订单编号
+     * @param status  状态
+     */
+    void updateRecordStatusByUserIdAndOrderId(Long userId, Long orderId, Integer status);
+
+    /**
+     * 更新拼团状态和开始时间
+     *
+     * @param userId    用户编号
+     * @param orderId   订单编号
+     * @param status    状态
+     * @param startTime 开始时间
+     */
+    void updateRecordStatusAndStartTimeByUserIdAndOrderId(Long userId, Long orderId, Integer status, LocalDateTime startTime);
+
+    // TODO @puhui999:拆一个 CombinationRecordService 里
+    /**
+     * 创建拼团记录
+     *
+     * @param reqDTO 创建信息
+     */
+    void createRecord(CombinationRecordReqDTO reqDTO);
+
+    /**
+     * 获得拼团状态
+     *
+     * @param userId  用户编号
+     * @param orderId 订单编号
+     * @return 拼团状态
+     */
+    boolean validateRecordStatusIsSuccess(Long userId, Long orderId);
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java
new file mode 100644
index 000000000..0742fd314
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java
@@ -0,0 +1,286 @@
+package cn.iocoder.yudao.module.promotion.service.combination;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
+import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
+import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
+import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
+import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordReqDTO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityExportReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductCreateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationActivityDO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationProductDO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationRecordDO;
+import cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity.CombinationActivityMapper;
+import cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity.CombinationProductMapper;
+import cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity.CombinationRecordMapper;
+import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
+import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
+import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuExistence;
+
+/**
+ * 拼团活动 Service 实现类
+ *
+ * @author HUIHUI
+ */
+@Service
+@Validated
+public class CombinationActivityServiceImpl implements CombinationActivityService {
+
+    @Resource
+    private CombinationActivityMapper combinationActivityMapper;
+    @Resource
+    private CombinationRecordMapper recordMapper;
+    @Resource
+    private CombinationProductMapper combinationProductMapper;
+    @Resource
+    private ProductSpuApi productSpuApi;
+    @Resource
+    private ProductSkuApi productSkuApi;
+
+    @Override
+    public Long createCombinationActivity(CombinationActivityCreateReqVO createReqVO) {
+        // 校验商品 SPU 是否存在是否参加的别的活动
+        validateProductCombinationConflict(createReqVO.getSpuId(), null);
+        // 获取所选 spu下的所有 sku
+        List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollectionUtil.newArrayList(createReqVO.getSpuId()));
+        // 校验商品 sku 是否存在
+        validateProductSkuExistence(skus, createReqVO.getProducts(), CombinationProductCreateReqVO::getSkuId);
+
+        // TODO 艿艿 有个小问题:现在有活动时间和限制时长,活动时间的结束时间早于设置的限制时间怎么算状态比如:
+        //  活动时间 2023-08-05 15:00:00 - 2023-08-05 15:20:00 限制时长 2小时,那么活动时间结束就结束还是加时到满两小时
+        // 插入拼团活动
+        CombinationActivityDO activityDO = CombinationActivityConvert.INSTANCE.convert(createReqVO);
+        // TODO 营销相关属性初始化
+        activityDO.setTotalNum(0);
+        activityDO.setSuccessNum(0);
+        activityDO.setOrderUserCount(0);
+        activityDO.setVirtualGroup(0);
+        activityDO.setStatus(CommonStatusEnum.ENABLE.getStatus());
+        combinationActivityMapper.insert(activityDO);
+        // 插入商品
+        List<CombinationProductDO> productDOs = CombinationActivityConvert.INSTANCE.convertList(activityDO, createReqVO.getProducts());
+        combinationProductMapper.insertBatch(productDOs);
+        // 返回
+        return activityDO.getId();
+    }
+
+    private void validateProductCombinationConflict(Long spuId, Long activityId) {
+        // 校验商品 spu 是否存在
+        List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(CollUtil.newArrayList(spuId));
+        if (CollUtil.isEmpty(spuList)) {
+            throw exception(SPU_NOT_EXISTS);
+        }
+        // 查询所有开启的拼团活动
+        List<CombinationActivityDO> activityDOs = combinationActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());
+        // 更新时排除自己
+        if (activityId != null) {
+            activityDOs.removeIf(item -> ObjectUtil.equal(item.getId(), activityId));
+        }
+        // 过滤出所有 spuIds 有交集的活动
+        List<CombinationActivityDO> doList = CollectionUtils.convertList(activityDOs, c -> c, s -> ObjectUtil.equal(s.getId(), spuId));
+        if (CollUtil.isNotEmpty(doList)) {
+            throw exception(COMBINATION_ACTIVITY_SPU_CONFLICTS);
+        }
+    }
+
+    @Override
+    public void updateCombinationActivity(CombinationActivityUpdateReqVO updateReqVO) {
+        // 校验存在
+        CombinationActivityDO activityDO = validateCombinationActivityExists(updateReqVO.getId());
+        // 校验状态
+        if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
+            throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE);
+        }
+        // 校验商品冲突
+        validateProductCombinationConflict(updateReqVO.getSpuId(), updateReqVO.getId());
+        // 获取所选 spu下的所有 sku
+        List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollectionUtil.newArrayList(updateReqVO.getSpuId()));
+        // 校验商品 sku 是否存在
+        validateProductSkuExistence(skus, updateReqVO.getProducts(), CombinationProductUpdateReqVO::getSkuId);
+
+        // 更新
+        CombinationActivityDO updateObj = CombinationActivityConvert.INSTANCE.convert(updateReqVO);
+        combinationActivityMapper.updateById(updateObj);
+        // 更新商品
+        updateCombinationProduct(updateObj, updateReqVO.getProducts());
+    }
+
+    /**
+     * 更新秒杀商品
+     *  TODO 更新商品要不要封装成通用方法
+     *
+     * @param updateObj DO
+     * @param products  商品配置
+     */
+    private void updateCombinationProduct(CombinationActivityDO updateObj, List<CombinationProductUpdateReqVO> products) {
+        List<CombinationProductDO> combinationProductDOs = combinationProductMapper.selectListByActivityIds(CollUtil.newArrayList(updateObj.getId()));
+        // 数据库中的活动商品
+        Set<Long> convertSet = CollectionUtils.convertSet(combinationProductDOs, CombinationProductDO::getSkuId);
+        // 前端传过来的活动商品
+        Set<Long> convertSet1 = CollectionUtils.convertSet(products, CombinationProductUpdateReqVO::getSkuId);
+        // 删除后台存在的前端不存在的商品
+        List<Long> d = CollectionUtils.filterList(convertSet, item -> !convertSet1.contains(item));
+        if (CollUtil.isNotEmpty(d)) {
+            combinationProductMapper.deleteBatchIds(d);
+        }
+        // 前端存在的后端不存在的商品
+        List<Long> c = CollectionUtils.filterList(convertSet1, item -> !convertSet.contains(item));
+        if (CollUtil.isNotEmpty(c)) {
+            List<CombinationProductUpdateReqVO> vos = CollectionUtils.filterList(products, item -> c.contains(item.getSkuId()));
+            List<CombinationProductDO> productDOs = CombinationActivityConvert.INSTANCE.convertList(updateObj, vos);
+            combinationProductMapper.insertBatch(productDOs);
+        }
+        // 更新已存在的商品
+        List<Long> u = CollectionUtils.filterList(convertSet1, convertSet::contains);
+        if (CollUtil.isNotEmpty(u)) {
+            List<CombinationProductUpdateReqVO> vos = CollectionUtils.filterList(products, item -> u.contains(item.getSkuId()));
+            List<CombinationProductDO> productDOs = CombinationActivityConvert.INSTANCE.convertList1(updateObj, vos, combinationProductDOs);
+            combinationProductMapper.updateBatch(productDOs);
+        }
+    }
+
+    @Override
+    public void deleteCombinationActivity(Long id) {
+        // 校验存在
+        CombinationActivityDO activityDO = validateCombinationActivityExists(id);
+        // 校验状态
+        if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
+            throw exception(COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END);
+        }
+
+        // 删除
+        combinationActivityMapper.deleteById(id);
+    }
+
+    private CombinationActivityDO validateCombinationActivityExists(Long id) {
+        CombinationActivityDO activityDO = combinationActivityMapper.selectById(id);
+        if (activityDO == null) {
+            throw exception(COMBINATION_ACTIVITY_NOT_EXISTS);
+        }
+        return activityDO;
+    }
+
+    @Override
+    public CombinationActivityDO getCombinationActivity(Long id) {
+        return validateCombinationActivityExists(id);
+    }
+
+    @Override
+    public List<CombinationActivityDO> getCombinationActivityList(Collection<Long> ids) {
+        return combinationActivityMapper.selectBatchIds(ids);
+    }
+
+    @Override
+    public PageResult<CombinationActivityDO> getCombinationActivityPage(CombinationActivityPageReqVO pageReqVO) {
+        return combinationActivityMapper.selectPage(pageReqVO);
+    }
+
+    @Override
+    public List<CombinationActivityDO> getCombinationActivityList(CombinationActivityExportReqVO exportReqVO) {
+        return combinationActivityMapper.selectList(exportReqVO);
+    }
+
+    @Override
+    public List<CombinationProductDO> getProductsByActivityIds(Collection<Long> ids) {
+        return combinationProductMapper.selectListByActivityIds(ids);
+    }
+
+    @Override
+    public void updateRecordStatusByUserIdAndOrderId(Long userId, Long orderId, Integer status) {
+        // 校验拼团是否存在
+        CombinationRecordDO recordDO = validateCombinationRecord(userId, orderId);
+
+        // 更新状态
+        recordDO.setStatus(status);
+        recordMapper.updateById(recordDO);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void updateRecordStatusAndStartTimeByUserIdAndOrderId(Long userId, Long orderId, Integer status, LocalDateTime startTime) {
+        CombinationRecordDO recordDO = validateCombinationRecord(userId, orderId);
+        // 更新状态
+        recordDO.setStatus(status);
+        // 更新开始时间
+        recordDO.setStartTime(startTime);
+        recordMapper.updateById(recordDO);
+
+        // 更新拼团参入人数
+        List<CombinationRecordDO> recordDOs = recordMapper.selectListByHeadIdAndStatus(recordDO.getHeadId(), status);
+        if (CollUtil.isNotEmpty(recordDOs)) {
+            recordDOs.forEach(item -> {
+                item.setUserCount(recordDOs.size());
+                // 校验拼团是否满足要求
+                if (recordDOs.size() >= recordDO.getUserSize()) {
+                    item.setStatus(CombinationRecordStatusEnum.SUCCESS.getStatus());
+                }
+            });
+        }
+        recordMapper.updateBatch(recordDOs);
+    }
+
+    private CombinationRecordDO validateCombinationRecord(Long userId, Long orderId) {
+        // 校验拼团是否存在
+        CombinationRecordDO recordDO = recordMapper.selectRecord(userId, orderId);
+        if (recordDO == null) {
+            throw exception(COMBINATION_RECORD_NOT_EXISTS);
+        }
+        return recordDO;
+    }
+
+    @Override
+    public void createRecord(CombinationRecordReqDTO reqDTO) {
+        // 校验拼团活动
+        CombinationActivityDO activity = validateCombinationActivityExists(reqDTO.getActivityId());
+        // TODO @puhui999:需要校验下,它当前是不是已经参加了该拼团;
+        // TODO @puhui999: 父拼团是否存在,是否已经满了
+
+        CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO);
+        record.setVirtualGroup(false);
+        // TODO @puhui999:过期时间,应该是 Date 哈;
+        record.setExpireTime(activity.getLimitDuration());
+        record.setUserSize(activity.getUserSize());
+        recordMapper.insert(record);
+    }
+
+    @Override
+    public boolean validateRecordStatusIsSuccess(Long userId, Long orderId) {
+        CombinationRecordDO record = validateCombinationRecord(userId, orderId);
+        // TODO @puhui999:可以搞个 getRecrod 方法,然后业务通过 CombinationRecordStatusEnum.isSuccess 方法校验
+        return ObjectUtil.equal(record.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus());
+    }
+
+    // TODO @puhui999:status 传入进来搞哈;
+    /**
+     * APP 端获取开团记录
+     *
+     * @return 开团记录
+     */
+    public List<CombinationRecordDO> getRecordList() {
+        return recordMapper.selectListByStatus(CombinationRecordStatusEnum.IN_PROGRESS.getStatus());
+    }
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityService.java
index 1c3ed38fe..4096f0087 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityService.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityService.java
@@ -79,4 +79,12 @@ public interface SeckillActivityService {
      */
     List<SeckillProductDO> getSeckillProductListByActivityId(Long id);
 
+    /**
+     * 通过活动编号获取活动商品
+     *
+     * @param ids 活动编号
+     * @return 活动商品列表
+     */
+    List<SeckillProductDO> getSeckillProductListByActivityId(Collection<Long> ids);
+
 }
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java
index e95449649..9538019f4 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java
@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity;
 
 import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.ArrayUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
@@ -13,29 +12,28 @@ import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO;
-import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductCreateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductUpdateReqVO;
 import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
 import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillActivityMapper;
 import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillProductMapper;
-import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum;
 import cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig.SeckillConfigService;
 import cn.iocoder.yudao.module.promotion.util.PromotionUtils;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
 import java.util.Collection;
 import java.util.List;
 import java.util.Set;
-import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS;
 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
-import static java.util.Arrays.asList;
+import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuExistence;
 
 /**
  * 秒杀活动 Service 实现类
@@ -58,155 +56,150 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
     private ProductSkuApi productSkuApi;
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public Long createSeckillActivity(SeckillActivityCreateReqVO createReqVO) {
         // 校验商品秒秒杀时段是否冲突
-        validateProductSpuSeckillConflict(createReqVO.getConfigIds(), createReqVO.getSpuIds());
+        validateProductSpuSeckillConflict(createReqVO.getConfigIds(), createReqVO.getSpuId(), null);
+        // 获取所选 spu 下的所有 sku
+        List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollUtil.newArrayList(createReqVO.getSpuId()));
         // 校验商品 sku 是否存在
-        validateProductSkuExistence(createReqVO.getSpuIds(), createReqVO.getProducts());
+        // TODO @puhui999:直接校验 sku 数量,是不是就完事啦,不需要校验的特别严谨哈;
+        validateProductSkuExistence(skus, createReqVO.getProducts(), SeckillProductCreateReqVO::getSkuId);
 
         // 插入秒杀活动
         SeckillActivityDO activity = SeckillActivityConvert.INSTANCE.convert(createReqVO)
-                .setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getEndTime()));
+                .setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getEndTime()))
+                .setTotalStock(CollectionUtils.getSumValue(createReqVO.getProducts(), SeckillProductCreateReqVO::getStock, Integer::sum));
         seckillActivityMapper.insert(activity);
         // 插入商品
+        // TODO @puhui999:products 要注意复数哈
         List<SeckillProductDO> product = SeckillActivityConvert.INSTANCE.convertList(activity, createReqVO.getProducts());
         seckillProductMapper.insertBatch(product);
         return activity.getId();
     }
 
-    private <T extends SeckillProductBaseVO> void validateProductSkuExistence(List<Long> spuIds, List<T> products) {
-        // 校验 spu 个数是否相等
-        // TODO @puhui999:不用校验 SPU 哈,只校验 sku 对应的 spuId 是否一致;
-        Set<Long> convertedSpuIds = CollectionUtils.convertSet(products, T::getSpuId);
-        if (ObjectUtil.notEqual(spuIds.size(), convertedSpuIds.size())) {
-            throw exception(SKU_NOT_EXISTS);
-        }
-        // 获取所选 spu下的所有 sku
-        // TODO @puhui999:变量可以简单一点;skus
-        List<ProductSkuRespDTO> skuRespDTOs = productSkuApi.getSkuListBySpuId(spuIds);
-        // 校验 sku 个数是否一致
-        Set<Long> skuIdsSet = CollectionUtils.convertSet(products, T::getSkuId);
-        Set<Long> skuIdsSet1 = CollectionUtils.convertSet(skuRespDTOs, ProductSkuRespDTO::getId);
-        if (ObjectUtil.notEqual(skuIdsSet.size(), skuIdsSet1.size())) {
-            throw exception(SKU_NOT_EXISTS);
-        }
-        // 校验 skuId 是否存在
-        if (!skuIdsSet1.containsAll(skuIdsSet) || !skuIdsSet.containsAll(skuIdsSet1)) {
-            throw exception(SKU_NOT_EXISTS);
-        }
-    }
-
-    private void validateProductSpuSeckillConflict(List<Long> configIds, List<Long> spuIds) {
+    private void validateProductSpuSeckillConflict(List<Long> configIds, Long spuId, Long activityId) {
         // 校验秒杀时段是否存在
         seckillConfigService.validateSeckillConfigExists(configIds);
         // 校验商品 spu 是否存在
-        List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(spuIds);
-        if (ObjectUtil.notEqual(spuIds.size(), spuList.size())) {
+        List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(CollUtil.newArrayList(spuId));
+        if (CollUtil.isEmpty(spuList)) {
             throw exception(SPU_NOT_EXISTS);
         }
         // 查询所有开启的秒杀活动
         List<SeckillActivityDO> activityDOs = seckillActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());
-        // 过滤出所有 spuIds 有交集的活动
-        List<SeckillActivityDO> doList = activityDOs.stream().filter(s -> {
-            // 判断 spu 是否有交集
-            List<Long> spuIdsClone = ArrayUtil.clone(s.getSpuIds());
-            spuIdsClone.retainAll(spuIds);
-            if (CollUtil.isEmpty(spuIdsClone)) {
-                return false;
-            }
+        if (activityId != null) {
+            // 更新时移除本活动
+            activityDOs.removeIf(item -> ObjectUtil.equal(item.getId(), activityId));
+        }
+        // 过滤出所有 spuId 有交集的活动
+        List<SeckillActivityDO> activityDOs1 = CollectionUtils.convertList(activityDOs, c -> c, s -> ObjectUtil.equal(s.getSpuId(), spuId));
+        if (CollUtil.isNotEmpty(activityDOs1)) {
+            throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS);
+        }
+        List<SeckillActivityDO> activityDOs2 = CollectionUtils.convertList(activityDOs, c -> c, s -> {
             // 判断秒杀时段是否有交集
-            List<Long> configIdsClone = ArrayUtil.clone(s.getConfigIds());
+            // TODO @puhui999:是不是 containsAny 就是有交集呀
+            List<Long> configIdsClone = CollUtil.newArrayList(s.getConfigIds());
             configIdsClone.retainAll(configIds);
             return CollUtil.isNotEmpty(configIdsClone);
-        }).collect(Collectors.toList());
-        if (CollUtil.isNotEmpty(doList)) {
-            throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS);
+        });
+        if (CollUtil.isNotEmpty(activityDOs2)) {
+            throw exception(SECKILL_TIME_CONFLICTS);
         }
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public void updateSeckillActivity(SeckillActivityUpdateReqVO updateReqVO) {
         // 校验存在
         SeckillActivityDO seckillActivity = validateSeckillActivityExists(updateReqVO.getId());
-        if (CommonStatusEnum.ENABLE.getStatus().equals(seckillActivity.getStatus())) {
+        if (CommonStatusEnum.DISABLE.getStatus().equals(seckillActivity.getStatus())) {
             throw exception(SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED);
         }
         // 校验商品是否冲突
-        validateProductSpuSeckillConflict(updateReqVO.getConfigIds(), updateReqVO.getSpuIds());
+        validateProductSpuSeckillConflict(updateReqVO.getConfigIds(), updateReqVO.getSpuId(), updateReqVO.getId());
+        // 获取所选 spu下的所有 sku
+        List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollUtil.newArrayList(updateReqVO.getSpuId()));
         // 校验商品 sku 是否存在
-        validateProductSkuExistence(updateReqVO.getSpuIds(), updateReqVO.getProducts());
+        validateProductSkuExistence(skus, updateReqVO.getProducts(), SeckillProductUpdateReqVO::getSkuId);
 
         // 更新活动
         SeckillActivityDO updateObj = SeckillActivityConvert.INSTANCE.convert(updateReqVO)
-                .setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getEndTime()));
+                .setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getEndTime()))
+                .setTotalStock(CollectionUtils.getSumValue(updateReqVO.getProducts(), SeckillProductUpdateReqVO::getStock, Integer::sum));
         seckillActivityMapper.updateById(updateObj);
         // 更新商品
-        //updateSeckillProduct(updateReqVO);
+        updateSeckillProduct(updateObj, updateReqVO.getProducts());
     }
 
 
     /**
      * 更新秒杀商品
-     * 后台查出的数据和前台查出的数据进行遍历,
-     * 1. 对前台数据进行遍历:如果不存在于后台的 sku 中需要新增
-     * 2. 对后台数据进行遍历:如果不存在于前台的 sku 中需要删除
-     * 3. 最后对当前活动商品全部更新,更新秒杀时段id列表
      *
-     * @param updateReqVO 更新的请求VO
+     * @param updateObj 更新的活动
+     * @param products  商品配置
      */
-    private void updateSeckillProduct(SeckillActivityUpdateReqVO updateReqVO) {
-        // TODO puhui999:要不这里简单一点;删除原本的,插入新增的;不做的这么细致
-        // TODO puhui999:后续完善
-        //List<SeckillProductDO> seckillProductDOs = seckillProductMapper.selectListByActivityId(updateReqVO.getId());
-        //List<SeckillProductUpdateReqVO> products = updateReqVO.getProducts();
-
-        ////计算需要删除的数据
-        //List<Long> deleteIds = CollectionUtils.convertList(seckillProductDOs, SeckillProductDO::getId,
-        //        seckillProductDO -> products.stream()
-        //                .noneMatch(product -> SeckillActivityConvert.INSTANCE.isEquals(seckillProductDO, product)));
-        //if (CollUtil.isNotEmpty(deleteIds)) {
-        //    seckillProductMapper.deleteBatchIds(deleteIds);
-        //}
-        //
-        //// 计算需要新增的数据
-        //List<SeckillProductDO> newSeckillProductDOs = CollectionUtils.convertList(products,
-        //        product -> SeckillActivityConvert.INSTANCE.convert(product).setActivityId(updateReqVO.getId()));
-        //newSeckillProductDOs.removeIf(product -> seckillProductDOs.stream()
-        //        .anyMatch(seckillProduct -> SeckillActivityConvert.INSTANCE.isEquals(seckillProduct, product)));
-        //if (CollUtil.isNotEmpty(newSeckillProductDOs)) {
-        //    seckillProductMapper.insertBatch(newSeckillProductDOs);
-        //}
-
-        //全量更新当前活动商品的秒杀时段id列表(timeIds)
-        seckillProductMapper.updateTimeIdsByActivityId(updateReqVO.getId(), updateReqVO.getConfigIds());
+    // TODO @puhui999:我在想,我们是不是可以封装一个 CollUtil 的方法,传入两个数组,判断出哪些是新增、哪些是修改、哪些是删除;
+    // 例如说,products 先转化成 SeckillProductDO;然后,基于一个 func(key1, key2) 做比对;
+    // 如果可以跑通,所有涉及到这种逻辑的,都可以服用哈。
+    private void updateSeckillProduct(SeckillActivityDO updateObj, List<SeckillProductUpdateReqVO> products) {
+        // 数据库中的活动商品
+        List<SeckillProductDO> seckillProductDOs = seckillProductMapper.selectListByActivityId(updateObj.getId());
+        Set<Long> dbSkuIds = CollectionUtils.convertSet(seckillProductDOs, SeckillProductDO::getSkuId);
+        // 1. 删除后台存在的前端不存在的商品
+        // TODO @puhui999:delete 应该是 id,不是 skuId 哈
+        Set<Long> voSkuIds = CollectionUtils.convertSet(products, SeckillProductUpdateReqVO::getSkuId);
+        List<Long> d = CollectionUtils.filterList(dbSkuIds, item -> !voSkuIds.contains(item));
+        if (CollUtil.isNotEmpty(d)) {
+            seckillProductMapper.deleteBatchIds(d);
+        }
+        // 2. 前端存在的后端不存在的商品
+        List<Long> c = CollectionUtils.filterList(voSkuIds, item -> !dbSkuIds.contains(item));
+        if (CollUtil.isNotEmpty(c)) {
+            List<SeckillProductUpdateReqVO> vos = CollectionUtils.filterList(products, item -> c.contains(item.getSkuId()));
+            List<SeckillProductDO> productDOs = SeckillActivityConvert.INSTANCE.convertList(updateObj, vos);
+            seckillProductMapper.insertBatch(productDOs);
+        }
+        // 3. 更新已存在的商品
+        List<Long> u = CollectionUtils.filterList(voSkuIds, dbSkuIds::contains);
+        if (CollUtil.isNotEmpty(u)) {
+            List<SeckillProductUpdateReqVO> vos = CollectionUtils.filterList(products, item -> u.contains(item.getSkuId()));
+            List<SeckillProductDO> productDOs = SeckillActivityConvert.INSTANCE.convertList1(updateObj, vos, seckillProductDOs);
+            seckillProductMapper.updateBatch(productDOs);
+        }
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class) // TODO @puhui999:这个不用加事务哈
     public void closeSeckillActivity(Long id) {
+        // TODO 待验证没使用过
         // 校验存在
-        SeckillActivityDO seckillActivity = this.validateSeckillActivityExists(id);
-        if (PromotionActivityStatusEnum.CLOSE.getStatus().equals(seckillActivity.getStatus())) {
+        SeckillActivityDO activity = validateSeckillActivityExists(id);
+        if (CommonStatusEnum.DISABLE.getStatus().equals(activity.getStatus())) {
             throw exception(SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED);
         }
-        if (PromotionActivityStatusEnum.END.getStatus().equals(seckillActivity.getStatus())) {
-            throw exception(SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_END);
-        }
+
         // 更新
-        SeckillActivityDO updateObj = new SeckillActivityDO().setId(id).setStatus(PromotionActivityStatusEnum.CLOSE.getStatus());
+        SeckillActivityDO updateObj = new SeckillActivityDO().setId(id).setStatus(CommonStatusEnum.DISABLE.getStatus());
         seckillActivityMapper.updateById(updateObj);
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public void deleteSeckillActivity(Long id) {
         // 校验存在
         SeckillActivityDO seckillActivity = this.validateSeckillActivityExists(id);
-        List<Integer> statuses = asList(PromotionActivityStatusEnum.CLOSE.getStatus(), PromotionActivityStatusEnum.END.getStatus());
-        if (!statuses.contains(seckillActivity.getStatus())) {
+        if (CommonStatusEnum.ENABLE.getStatus().equals(seckillActivity.getStatus())) {
             throw exception(SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END);
         }
 
-        // 删除
+        // 删除活动
         seckillActivityMapper.deleteById(id);
+        // 删除活动商品
+        List<SeckillProductDO> productDOs = seckillProductMapper.selectListByActivityId(id);
+        Set<Long> convertSet = CollectionUtils.convertSet(productDOs, SeckillProductDO::getSkuId);
+        seckillProductMapper.deleteBatchIds(convertSet);
     }
 
     private SeckillActivityDO validateSeckillActivityExists(Long id) {
@@ -219,7 +212,7 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
 
     @Override
     public SeckillActivityDO getSeckillActivity(Long id) {
-        return seckillActivityMapper.selectById(id);
+        return validateSeckillActivityExists(id);
     }
 
     @Override
@@ -237,4 +230,9 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
         return seckillProductMapper.selectListByActivityId(id);
     }
 
+    @Override
+    public List<SeckillProductDO> getSeckillProductListByActivityId(Collection<Long> ids) {
+        return seckillProductMapper.selectListByActivityId(ids);
+    }
+
 }
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigServiceImpl.java
index 599973d5b..89005501d 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigServiceImpl.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigServiceImpl.java
@@ -1,8 +1,11 @@
 package cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigCreateReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigPageReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigUpdateReqVO;
@@ -10,14 +13,13 @@ import cn.iocoder.yudao.module.promotion.convert.seckill.seckillconfig.SeckillCo
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
 import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillconfig.SeckillConfigMapper;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
 import java.time.LocalTime;
 import java.util.Collection;
 import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
@@ -35,9 +37,10 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
     private SeckillConfigMapper seckillConfigMapper;
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public Long createSeckillConfig(SeckillConfigCreateReqVO createReqVO) {
         // 校验时间段是否冲突
-        validateSeckillConfigConflict(createReqVO.getStartTime(), createReqVO.getEndTime());
+        validateSeckillConfigConflict(createReqVO.getStartTime(), createReqVO.getEndTime(), null);
 
         // 插入
         SeckillConfigDO seckillConfig = SeckillConfigConvert.INSTANCE.convert(createReqVO);
@@ -47,18 +50,30 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public void updateSeckillConfig(SeckillConfigUpdateReqVO updateReqVO) {
         // 校验存在
         validateSeckillConfigExists(updateReqVO.getId());
         // 校验时间段是否冲突
-        validateSeckillConfigConflict(updateReqVO.getStartTime(), updateReqVO.getEndTime());
+        validateSeckillConfigConflict(updateReqVO.getStartTime(), updateReqVO.getEndTime(), updateReqVO.getId());
 
         // 更新
         SeckillConfigDO updateObj = SeckillConfigConvert.INSTANCE.convert(updateReqVO);
         seckillConfigMapper.updateById(updateObj);
     }
 
+    // TODO  @puhui999: 这个要不合并到更新操作里? 不单独有个操作咧; 更新状态不用那么多必须的参数,更新的时候需要校验时间段
     @Override
+    public void updateSeckillConfigStatus(Long id, Integer status) {
+        // 校验秒杀时段是否存在
+        validateSeckillConfigExists(id);
+
+        // 更新状态
+        seckillConfigMapper.updateById(new SeckillConfigDO().setId(id).setStatus(status));
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
     public void deleteSeckillConfig(Long id) {
         // 校验存在
         validateSeckillConfigExists(id);
@@ -79,39 +94,29 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
      * @param startTime 开始时间
      * @param endTime   结束时间
      */
-    private void validateSeckillConfigConflict(String startTime, String endTime) {
+    private void validateSeckillConfigConflict(String startTime, String endTime, Long seckillConfigId) {
         LocalTime startTime1 = LocalTime.parse(startTime);
         LocalTime endTime1 = LocalTime.parse(endTime);
-        // TODO @puhui999: 这个可以用 validator 里的 assertTrue 去做哈;
-        // 检查选择的时间是否相等
-        if (startTime1.equals(endTime1)) {
-            throw exception(SECKILL_TIME_EQUAL);
-        }
-        // 检查开始时间是否在结束时间之前
-        if (startTime1.isAfter(endTime1)) {
-            throw exception(SECKILL_START_TIME_BEFORE_END_TIME);
-        }
         // 查询出所有的时段配置
         List<SeckillConfigDO> configDOs = seckillConfigMapper.selectList();
+        // 更新时排除自己
+        if (seckillConfigId != null) {
+            configDOs.removeIf(item -> ObjectUtil.equal(item.getId(), seckillConfigId));
+        }
         // 过滤出重叠的时段 ids
-        // TODO @puhui999:感觉 findOne 就可以了?
-        Set<Long> ids = configDOs.stream().filter((config) -> {
+        boolean hasConflict = configDOs.stream().anyMatch(config -> {
             LocalTime startTime2 = LocalTime.parse(config.getStartTime());
             LocalTime endTime2 = LocalTime.parse(config.getEndTime());
             // 判断时间是否重叠
-            // 开始时间在已配置时段的结束时间之前 且 结束时间在已配置时段的开始时间之后 []
-            // todo @puhui999:LocalDateUtils 可以写个工具类?是否是有重叠的时间?感觉别的场景,可能也会有需要
-            return startTime1.isBefore(endTime2) && endTime1.isAfter(startTime2)
-                    // 开始时间在已配置时段的开始时间之前 且 结束时间在已配置时段的开始时间之后 (] 或 ()
-                    || startTime1.isBefore(startTime2) && endTime1.isAfter(startTime2)
-                    // 开始时间在已配置时段的结束时间之前 且 结束时间在已配值时段的结束时间之后 [) 或 ()
-                    || startTime1.isBefore(endTime2) && endTime1.isAfter(endTime2);
-        }).map(SeckillConfigDO::getId).collect(Collectors.toSet());
-        if (CollUtil.isNotEmpty(ids)) {
+            return LocalDateTimeUtils.checkTimeOverlap(startTime1, endTime1, startTime2, endTime2);
+        });
+
+        if (hasConflict) {
             throw exception(SECKILL_TIME_CONFLICTS);
         }
     }
 
+
     @Override
     public SeckillConfigDO getSeckillConfig(Long id) {
         return seckillConfigMapper.selectById(id);
@@ -127,10 +132,18 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
         if (CollUtil.isEmpty(configIds)) {
             throw exception(SECKILL_TIME_NOT_EXISTS);
         }
-        if (seckillConfigMapper.selectBatchIds(configIds).size() != configIds.size()) {
+        List<SeckillConfigDO> configDOs = seckillConfigMapper.selectBatchIds(configIds);
+        if (CollUtil.isEmpty(configDOs)) {
+            throw exception(SECKILL_TIME_NOT_EXISTS);
+        }
+        // 过滤出关闭的时段
+        List<SeckillConfigDO> filterList = CollectionUtils.filterList(configDOs, item -> ObjectUtil.equal(item.getStatus(), CommonStatusEnum.DISABLE.getStatus()));
+        if (CollUtil.isNotEmpty(filterList)) {
+            throw exception(SECKILL_TIME_DISABLE);
+        }
+        if (configDOs.size() != configIds.size()) {
             throw exception(SECKILL_TIME_NOT_EXISTS);
         }
-        // TODO @puhui999:应该要校验个 status 哈;如果有禁用的,也不行
     }
 
     @Override
@@ -138,23 +151,10 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
         return seckillConfigMapper.selectPage(pageVO);
     }
 
-    // TODO  @puhui999:写个查询状态的; 尽可能通用哈
+    // TODO @puhui999:改成传入 enable 状态哈。一个通用的 getSeckillConfigList 方法
     @Override
     public List<SeckillConfigDO> getListAllSimple() {
-        return seckillConfigMapper.selectList(SeckillConfigDO::getStatus, CommonStatusEnum.ENABLE.getStatus());
-    }
-
-    // TODO  @puhui999: 这个要不合并到更新操作里? 不单独有个操作咧;
-    @Override
-    public void updateSeckillConfigStatus(Long id, Integer status) {
-        // 校验秒杀时段是否存在
-        validateSeckillConfigExists(id);
-
-        SeckillConfigDO seckillConfigDO = new SeckillConfigDO();
-        seckillConfigDO.setId(id);
-        seckillConfigDO.setStatus(status);
-        // 更新状态
-        seckillConfigMapper.updateById(seckillConfigDO);
+        return seckillConfigMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());
     }
 
 }
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/util/PromotionUtils.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/util/PromotionUtils.java
index 2ad362fe2..f1cd18816 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/util/PromotionUtils.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/util/PromotionUtils.java
@@ -1,9 +1,18 @@
 package cn.iocoder.yudao.module.promotion.util;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
+import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
 
 import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Function;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS;
 
 /**
  * 活动工具类
@@ -22,4 +31,16 @@ public class PromotionUtils {
         return LocalDateTimeUtils.beforeNow(endTime) ? CommonStatusEnum.DISABLE.getStatus() : CommonStatusEnum.ENABLE.getStatus();
     }
 
+    // TODO @puhui999:写个注释哈。
+    public static <T> void validateProductSkuExistence(List<ProductSkuRespDTO> skus, List<T> products, Function<T, Long> func) {
+        // 校验 sku 个数是否一致
+        Set<Long> skuIdsSet = CollectionUtils.convertSet(products, func);
+        Set<Long> skuIdsSet1 = CollectionUtils.convertSet(skus, ProductSkuRespDTO::getId);
+        // 校验 skuId 是否存在
+        List<Long> f = CollectionUtils.filterList(skuIdsSet, s -> !skuIdsSet1.contains(s));
+        if (CollUtil.isNotEmpty(f)) {
+            throw exception(SKU_NOT_EXISTS);
+        }
+    }
+
 }
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImplTest.java b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImplTest.java
new file mode 100644
index 000000000..8a1b6e345
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImplTest.java
@@ -0,0 +1,252 @@
+package cn.iocoder.yudao.module.promotion.service.combination;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityExportReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationActivityDO;
+import cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity.CombinationActivityMapper;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.annotation.Import;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
+import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
+import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COMBINATION_ACTIVITY_NOT_EXISTS;
+import static org.junit.jupiter.api.Assertions.*;
+
+// TODO 芋艿:等完成后,在补全单测
+/**
+ * {@link CombinationActivityServiceImpl} 的单元测试类
+ *
+ * @author HUIHUI
+ */
+@Import(CombinationActivityServiceImpl.class)
+public class CombinationActivityServiceImplTest extends BaseDbUnitTest {
+
+    @Resource
+    private CombinationActivityServiceImpl combinationActivityService;
+
+    @Resource
+    private CombinationActivityMapper combinationActivityMapper;
+
+    @Test
+    public void testCreateCombinationActivity_success() {
+        // 准备参数
+        CombinationActivityCreateReqVO reqVO = randomPojo(CombinationActivityCreateReqVO.class);
+
+        // 调用
+        Long combinationActivityId = combinationActivityService.createCombinationActivity(reqVO);
+        // 断言
+        assertNotNull(combinationActivityId);
+        // 校验记录的属性是否正确
+        CombinationActivityDO combinationActivity = combinationActivityMapper.selectById(combinationActivityId);
+        assertPojoEquals(reqVO, combinationActivity);
+    }
+
+    @Test
+    public void testUpdateCombinationActivity_success() {
+        // mock 数据
+        CombinationActivityDO dbCombinationActivity = randomPojo(CombinationActivityDO.class);
+        combinationActivityMapper.insert(dbCombinationActivity);// @Sql: 先插入出一条存在的数据
+        // 准备参数
+        CombinationActivityUpdateReqVO reqVO = randomPojo(CombinationActivityUpdateReqVO.class, o -> {
+            o.setId(dbCombinationActivity.getId()); // 设置更新的 ID
+        });
+
+        // 调用
+        combinationActivityService.updateCombinationActivity(reqVO);
+        // 校验是否更新正确
+        CombinationActivityDO combinationActivity = combinationActivityMapper.selectById(reqVO.getId()); // 获取最新的
+        assertPojoEquals(reqVO, combinationActivity);
+    }
+
+    @Test
+    public void testUpdateCombinationActivity_notExists() {
+        // 准备参数
+        CombinationActivityUpdateReqVO reqVO = randomPojo(CombinationActivityUpdateReqVO.class);
+
+        // 调用, 并断言异常
+        assertServiceException(() -> combinationActivityService.updateCombinationActivity(reqVO), COMBINATION_ACTIVITY_NOT_EXISTS);
+    }
+
+    @Test
+    public void testDeleteCombinationActivity_success() {
+        // mock 数据
+        CombinationActivityDO dbCombinationActivity = randomPojo(CombinationActivityDO.class);
+        combinationActivityMapper.insert(dbCombinationActivity);// @Sql: 先插入出一条存在的数据
+        // 准备参数
+        Long id = dbCombinationActivity.getId();
+
+        // 调用
+        combinationActivityService.deleteCombinationActivity(id);
+        // 校验数据不存在了
+        assertNull(combinationActivityMapper.selectById(id));
+    }
+
+    @Test
+    public void testDeleteCombinationActivity_notExists() {
+        // 准备参数
+        Long id = randomLongId();
+
+        // 调用, 并断言异常
+        assertServiceException(() -> combinationActivityService.deleteCombinationActivity(id), COMBINATION_ACTIVITY_NOT_EXISTS);
+    }
+
+    @Test
+    @Disabled  // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
+    public void testGetCombinationActivityPage() {
+        // mock 数据
+        CombinationActivityDO dbCombinationActivity = randomPojo(CombinationActivityDO.class, o -> { // 等会查询到
+            o.setName(null);
+            //o.setSpuId(null);
+            o.setTotalLimitCount(null);
+            o.setSingleLimitCount(null);
+            o.setStartTime(null);
+            o.setEndTime(null);
+            o.setUserSize(null);
+            o.setTotalNum(null);
+            o.setSuccessNum(null);
+            o.setOrderUserCount(null);
+            o.setVirtualGroup(null);
+            o.setStatus(null);
+            o.setLimitDuration(null);
+            o.setCreateTime(null);
+        });
+        combinationActivityMapper.insert(dbCombinationActivity);
+        // 测试 name 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setName(null)));
+        // 测试 spuId 不匹配
+        //combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setSpuId(null)));
+        // 测试 totalLimitCount 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setTotalLimitCount(null)));
+        // 测试 singleLimitCount 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setSingleLimitCount(null)));
+        // 测试 startTime 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setStartTime(null)));
+        // 测试 endTime 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setEndTime(null)));
+        // 测试 userSize 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setUserSize(null)));
+        // 测试 totalNum 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setTotalNum(null)));
+        // 测试 successNum 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setSuccessNum(null)));
+        // 测试 orderUserCount 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setOrderUserCount(null)));
+        // 测试 virtualGroup 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setVirtualGroup(null)));
+        // 测试 status 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setStatus(null)));
+        // 测试 limitDuration 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setLimitDuration(null)));
+        // 测试 createTime 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setCreateTime(null)));
+        // 准备参数
+        CombinationActivityPageReqVO reqVO = new CombinationActivityPageReqVO();
+        reqVO.setName(null);
+        reqVO.setSpuId(null);
+        reqVO.setTotalLimitCount(null);
+        reqVO.setSingleLimitCount(null);
+        reqVO.setStartTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
+        reqVO.setEndTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
+        reqVO.setUserSize(null);
+        reqVO.setTotalNum(null);
+        reqVO.setSuccessNum(null);
+        reqVO.setOrderUserCount(null);
+        reqVO.setVirtualGroup(null);
+        reqVO.setStatus(null);
+        reqVO.setLimitDuration(null);
+        reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
+
+        // 调用
+        PageResult<CombinationActivityDO> pageResult = combinationActivityService.getCombinationActivityPage(reqVO);
+        // 断言
+        assertEquals(1, pageResult.getTotal());
+        assertEquals(1, pageResult.getList().size());
+        assertPojoEquals(dbCombinationActivity, pageResult.getList().get(0));
+    }
+
+    @Test
+    @Disabled  // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
+    public void testGetCombinationActivityList() {
+        // mock 数据
+        CombinationActivityDO dbCombinationActivity = randomPojo(CombinationActivityDO.class, o -> { // 等会查询到
+            o.setName(null);
+            //o.setSpuId(null);
+            o.setTotalLimitCount(null);
+            o.setSingleLimitCount(null);
+            o.setStartTime(null);
+            o.setEndTime(null);
+            o.setUserSize(null);
+            o.setTotalNum(null);
+            o.setSuccessNum(null);
+            o.setOrderUserCount(null);
+            o.setVirtualGroup(null);
+            o.setStatus(null);
+            o.setLimitDuration(null);
+            o.setCreateTime(null);
+        });
+        combinationActivityMapper.insert(dbCombinationActivity);
+        // 测试 name 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setName(null)));
+        // 测试 spuId 不匹配
+        //combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setSpuId(null)));
+        // 测试 totalLimitCount 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setTotalLimitCount(null)));
+        // 测试 singleLimitCount 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setSingleLimitCount(null)));
+        // 测试 startTime 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setStartTime(null)));
+        // 测试 endTime 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setEndTime(null)));
+        // 测试 userSize 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setUserSize(null)));
+        // 测试 totalNum 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setTotalNum(null)));
+        // 测试 successNum 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setSuccessNum(null)));
+        // 测试 orderUserCount 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setOrderUserCount(null)));
+        // 测试 virtualGroup 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setVirtualGroup(null)));
+        // 测试 status 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setStatus(null)));
+        // 测试 limitDuration 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setLimitDuration(null)));
+        // 测试 createTime 不匹配
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setCreateTime(null)));
+        // 准备参数
+        CombinationActivityExportReqVO reqVO = new CombinationActivityExportReqVO();
+        reqVO.setName(null);
+        reqVO.setSpuId(null);
+        reqVO.setTotalLimitCount(null);
+        reqVO.setSingleLimitCount(null);
+        reqVO.setStartTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
+        reqVO.setEndTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
+        reqVO.setUserSize(null);
+        reqVO.setTotalNum(null);
+        reqVO.setSuccessNum(null);
+        reqVO.setOrderUserCount(null);
+        reqVO.setVirtualGroup(null);
+        reqVO.setStatus(null);
+        reqVO.setLimitDuration(null);
+        reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
+
+        // 调用
+        List<CombinationActivityDO> list = combinationActivityService.getCombinationActivityList(reqVO);
+        // 断言
+        assertEquals(1, list.size());
+        assertPojoEquals(dbCombinationActivity, list.get(0));
+    }
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/test/resources/sql/clean.sql b/yudao-module-mall/yudao-module-promotion-biz/src/test/resources/sql/clean.sql
index d848bf556..7f3ace7b6 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/test/resources/sql/clean.sql
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/test/resources/sql/clean.sql
@@ -5,3 +5,4 @@ DELETE FROM "promotion_reward_activity";
 DELETE FROM "promotion_discount_activity";
 DELETE FROM "promotion_discount_product";
 DELETE FROM "promotion_seckill_config";
+DELETE FROM "promotion_combination_activity";
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/test/resources/sql/create_tables.sql b/yudao-module-mall/yudao-module-promotion-biz/src/test/resources/sql/create_tables.sql
index 33b6edc48..c7a3b56da 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/test/resources/sql/create_tables.sql
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/test/resources/sql/create_tables.sql
@@ -1,151 +1,183 @@
-CREATE TABLE IF NOT EXISTS "market_activity" (
-    "id" bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY,
-    "title" varchar(50) NOT NULL,
-    "activity_type" tinyint(4) NOT NULL,
-    "status" tinyint(4) NOT NULL,
-    "start_time" datetime NOT NULL,
-    "end_time" datetime NOT NULL,
-    "invalid_time" datetime,
-    "delete_time" datetime,
+CREATE TABLE IF NOT EXISTS "market_activity"
+(
+    "id"                    bigint(20)  NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+    "title"                 varchar(50) NOT NULL,
+    "activity_type"         tinyint(4)  NOT NULL,
+    "status"                tinyint(4)  NOT NULL,
+    "start_time"            datetime    NOT NULL,
+    "end_time"              datetime    NOT NULL,
+    "invalid_time"          datetime,
+    "delete_time"           datetime,
     "time_limited_discount" varchar(2000),
-    "full_privilege" varchar(2000),
-    "creator" varchar(64) DEFAULT '',
-    "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
-    "updater" varchar(64) DEFAULT '',
-    "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-    "deleted" bit NOT NULL DEFAULT FALSE,
-    "tenant_id" bigint(20) NOT NULL,
+    "full_privilege"        varchar(2000),
+    "creator"               varchar(64)          DEFAULT '',
+    "create_time"           datetime    NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updater"               varchar(64)          DEFAULT '',
+    "update_time"           datetime    NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+    "deleted"               bit         NOT NULL DEFAULT FALSE,
+    "tenant_id"             bigint(20)  NOT NULL,
     PRIMARY KEY ("id")
-    ) COMMENT '促销活动';
+) COMMENT '促销活动';
 
-CREATE TABLE IF NOT EXISTS "promotion_coupon_template" (
-   "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
-   "name" varchar NOT NULL,
-   "status" int NOT NULL,
-   "total_count" int NOT NULL,
-   "take_limit_count" int NOT NULL,
-   "take_type" int NOT NULL,
-   "use_price" int NOT NULL,
-   "product_scope" int NOT NULL,
-   "product_spu_ids" varchar,
-   "validity_type" int NOT NULL,
-   "valid_start_time" datetime,
-   "valid_end_time" datetime,
-   "fixed_start_term" int,
-   "fixed_end_term" int,
-   "discount_type" int NOT NULL,
-   "discount_percent" int,
-   "discount_price" int,
-   "discount_limit_price" int,
-   "take_count" int NOT NULL DEFAULT 0,
-   "use_count" int NOT NULL DEFAULT 0,
-   "creator" varchar DEFAULT '',
-   "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
-   "updater" varchar DEFAULT '',
-   "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-   "deleted" bit NOT NULL DEFAULT FALSE,
-   PRIMARY KEY ("id")
+CREATE TABLE IF NOT EXISTS "promotion_coupon_template"
+(
+    "id"                   bigint   NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+    "name"                 varchar  NOT NULL,
+    "status"               int      NOT NULL,
+    "total_count"          int      NOT NULL,
+    "take_limit_count"     int      NOT NULL,
+    "take_type"            int      NOT NULL,
+    "use_price"            int      NOT NULL,
+    "product_scope"        int      NOT NULL,
+    "product_spu_ids"      varchar,
+    "validity_type"        int      NOT NULL,
+    "valid_start_time"     datetime,
+    "valid_end_time"       datetime,
+    "fixed_start_term"     int,
+    "fixed_end_term"       int,
+    "discount_type"        int      NOT NULL,
+    "discount_percent"     int,
+    "discount_price"       int,
+    "discount_limit_price" int,
+    "take_count"           int      NOT NULL DEFAULT 0,
+    "use_count"            int      NOT NULL DEFAULT 0,
+    "creator"              varchar           DEFAULT '',
+    "create_time"          datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updater"              varchar           DEFAULT '',
+    "update_time"          datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+    "deleted"              bit      NOT NULL DEFAULT FALSE,
+    PRIMARY KEY ("id")
 ) COMMENT '优惠劵模板';
 
-CREATE TABLE IF NOT EXISTS "promotion_coupon" (
-    "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
-    "template_id" bigint NOT NULL,
-    "name" varchar NOT NULL,
-    "status" int NOT NULL,
-    "user_id" bigint NOT NULL,
-    "take_type" int NOT NULL,
-    "useprice" int NOT NULL,
-    "valid_start_time" datetime NOT NULL,
-    "valid_end_time" datetime NOT NULL,
-    "product_scope" int NOT NULL,
-    "product_spu_ids" varchar,
-    "discount_type" int NOT NULL,
-    "discount_percent" int,
-    "discount_price" int,
+CREATE TABLE IF NOT EXISTS "promotion_coupon"
+(
+    "id"                   bigint   NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+    "template_id"          bigint   NOT NULL,
+    "name"                 varchar  NOT NULL,
+    "status"               int      NOT NULL,
+    "user_id"              bigint   NOT NULL,
+    "take_type"            int      NOT NULL,
+    "useprice"             int      NOT NULL,
+    "valid_start_time"     datetime NOT NULL,
+    "valid_end_time"       datetime NOT NULL,
+    "product_scope"        int      NOT NULL,
+    "product_spu_ids"      varchar,
+    "discount_type"        int      NOT NULL,
+    "discount_percent"     int,
+    "discount_price"       int,
     "discount_limit_price" int,
-    "use_order_id" bigint,
-    "use_time" datetime,
-    "creator" varchar DEFAULT '',
-    "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
-    "updater" varchar DEFAULT '',
-    "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-    "deleted" bit NOT NULL DEFAULT FALSE,
+    "use_order_id"         bigint,
+    "use_time"             datetime,
+    "creator"              varchar           DEFAULT '',
+    "create_time"          datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updater"              varchar           DEFAULT '',
+    "update_time"          datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+    "deleted"              bit      NOT NULL DEFAULT FALSE,
     PRIMARY KEY ("id")
 ) COMMENT '优惠劵';
 
-CREATE TABLE IF NOT EXISTS "promotion_reward_activity" (
-   "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
-   "name" varchar NOT NULL,
-   "status" int NOT NULL,
-   "start_time" datetime NOT NULL,
-   "end_time" datetime NOT NULL,
-   "remark" varchar,
-   "condition_type" int NOT NULL,
-   "product_scope" int NOT NULL,
-   "product_spu_ids" varchar,
-   "rules" varchar,
-   "creator" varchar DEFAULT '',
-   "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
-   "updater" varchar DEFAULT '',
-   "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-   "deleted" bit NOT NULL DEFAULT FALSE,
-   PRIMARY KEY ("id")
+CREATE TABLE IF NOT EXISTS "promotion_reward_activity"
+(
+    "id"              bigint   NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+    "name"            varchar  NOT NULL,
+    "status"          int      NOT NULL,
+    "start_time"      datetime NOT NULL,
+    "end_time"        datetime NOT NULL,
+    "remark"          varchar,
+    "condition_type"  int      NOT NULL,
+    "product_scope"   int      NOT NULL,
+    "product_spu_ids" varchar,
+    "rules"           varchar,
+    "creator"         varchar           DEFAULT '',
+    "create_time"     datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updater"         varchar           DEFAULT '',
+    "update_time"     datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+    "deleted"         bit      NOT NULL DEFAULT FALSE,
+    PRIMARY KEY ("id")
 ) COMMENT '满减送活动';
 
-CREATE TABLE IF NOT EXISTS "promotion_discount_activity" (
-     "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
-     "name" varchar NOT NULL,
-     "status" int NOT NULL,
-     "start_time" datetime NOT NULL,
-     "end_time" datetime NOT NULL,
-     "remark" varchar,
-     "creator" varchar DEFAULT '',
-     "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
-     "updater" varchar DEFAULT '',
-     "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-     "deleted" bit NOT NULL DEFAULT FALSE,
-     PRIMARY KEY ("id")
+CREATE TABLE IF NOT EXISTS "promotion_discount_activity"
+(
+    "id"          bigint   NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+    "name"        varchar  NOT NULL,
+    "status"      int      NOT NULL,
+    "start_time"  datetime NOT NULL,
+    "end_time"    datetime NOT NULL,
+    "remark"      varchar,
+    "creator"     varchar           DEFAULT '',
+    "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updater"     varchar           DEFAULT '',
+    "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+    "deleted"     bit      NOT NULL DEFAULT FALSE,
+    PRIMARY KEY ("id")
 ) COMMENT '限时折扣活动';
 
 -- 将该建表 SQL 语句,添加到 yudao-module-promotion-biz 模块的 test/resources/sql/create_tables.sql 文件里
-CREATE TABLE IF NOT EXISTS "promotion_seckill_activity" (
-    "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
-    "spu_id" bigint NOT NULL,
-    "name" varchar NOT NULL,
-    "status" int NOT NULL,
-    "remark" varchar,
-    "start_time" varchar NOT NULL,
-    "end_time" varchar NOT NULL,
-    "sort" int NOT NULL,
-    "config_ids" varchar NOT NULL,
-    "order_count" int NOT NULL,
-    "user_count" int NOT NULL,
-    "total_price" int NOT NULL,
-    "total_limit_count" int,
+CREATE TABLE IF NOT EXISTS "promotion_seckill_activity"
+(
+    "id"                 bigint   NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+    "spu_id"             bigint   NOT NULL,
+    "name"               varchar  NOT NULL,
+    "status"             int      NOT NULL,
+    "remark"             varchar,
+    "start_time"         varchar  NOT NULL,
+    "end_time"           varchar  NOT NULL,
+    "sort"               int      NOT NULL,
+    "config_ids"         varchar  NOT NULL,
+    "order_count"        int      NOT NULL,
+    "user_count"         int      NOT NULL,
+    "total_price"        int      NOT NULL,
+    "total_limit_count"  int,
     "single_limit_count" int,
-    "stock" int,
-    "total_stock" int,
-    "creator" varchar DEFAULT '',
-    "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
-    "updater" varchar DEFAULT '',
-    "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-    "deleted" bit NOT NULL DEFAULT FALSE,
-    "tenant_id" bigint NOT NULL,
+    "stock"              int,
+    "total_stock"        int,
+    "creator"            varchar           DEFAULT '',
+    "create_time"        datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updater"            varchar           DEFAULT '',
+    "update_time"        datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+    "deleted"            bit      NOT NULL DEFAULT FALSE,
+    "tenant_id"          bigint   NOT NULL,
     PRIMARY KEY ("id")
 ) COMMENT '秒杀活动';
 
-CREATE TABLE IF NOT EXISTS "promotion_seckill_config" (
-    "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
-    "name" varchar NOT NULL,
-    "start_time" varchar NOT NULL,
-    "end_time" varchar NOT NULL,
-    "pic_url" varchar NOT NULL,
-    "status" int NOT NULL,
-    "creator" varchar DEFAULT '',
+CREATE TABLE IF NOT EXISTS "promotion_seckill_config"
+(
+    "id"          bigint   NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+    "name"        varchar  NOT NULL,
+    "start_time"  varchar  NOT NULL,
+    "end_time"    varchar  NOT NULL,
+    "pic_url"     varchar  NOT NULL,
+    "status"      int      NOT NULL,
+    "creator"     varchar           DEFAULT '',
     "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
-    "updater" varchar DEFAULT '',
+    "updater"     varchar           DEFAULT '',
     "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-    "deleted" bit NOT NULL DEFAULT FALSE,
-    "tenant_id" bigint NOT NULL,
+    "deleted"     bit      NOT NULL DEFAULT FALSE,
+    "tenant_id"   bigint   NOT NULL,
     PRIMARY KEY ("id")
 ) COMMENT '秒杀时段配置';
+
+CREATE TABLE IF NOT EXISTS "promotion_combination_activity"
+(
+    "id"                 bigint   NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+    "name"               varchar  NOT NULL,
+    "spu_id"             bigint,
+    "total_limit_count"  int      NOT NULL,
+    "single_limit_count" int      NOT NULL,
+    "start_time"         varchar  NOT NULL,
+    "end_time"           varchar  NOT NULL,
+    "user_size"          int      NOT NULL,
+    "total_num"          int      NOT NULL,
+    "success_num"        int      NOT NULL,
+    "order_user_count"   int      NOT NULL,
+    "virtual_group"      int      NOT NULL,
+    "status"             int      NOT NULL,
+    "limit_duration"     int      NOT NULL,
+    "creator"            varchar           DEFAULT '',
+    "create_time"        datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updater"            varchar           DEFAULT '',
+    "update_time"        datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+    "deleted"            bit      NOT NULL DEFAULT FALSE,
+    "tenant_id"          bigint   NOT NULL,
+    PRIMARY KEY ("id")
+) COMMENT '拼团活动';
\ No newline at end of file
diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
index 1b3c73c30..6571e65ff 100644
--- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
+++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
@@ -27,6 +27,10 @@ public interface ErrorCodeConstants {
     ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH = new ErrorCode(1011000016, "交易订单更新支付状态失败,支付单金额不匹配");
     ErrorCode ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED = new ErrorCode(1011000017, "交易订单发货失败,订单不是【待发货】状态");
     ErrorCode ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED = new ErrorCode(1011000018, "交易订单收货失败,订单不是【待收货】状态");
+    ErrorCode ORDER_COMMENT_FAIL_STATUS_NOT_COMPLETED = new ErrorCode(1011000019, "创建交易订单项的评价失败,订单不是【已完成】状态");
+    ErrorCode ORDER_COMMENT_STATUS_NOT_FALSE = new ErrorCode(1011000020, "创建交易订单项的评价失败,订单已评价");
+    ErrorCode ORDER_DELIVERY_FAIL_REFUND_STATUS_NOT_NONE = new ErrorCode(1011000021, "交易订单发货失败,订单已退款或部分退款");
+    ErrorCode ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS = new ErrorCode(1011000022, "交易订单发货失败,拼团未成功");
 
     // ==========  After Sale 模块 1011000100 ==========
     ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1011000100, "售后单不存在");
@@ -63,8 +67,12 @@ public interface ErrorCodeConstants {
     ErrorCode EXPRESS_TEMPLATE_NOT_EXISTS = new ErrorCode(1011005001, "运费模板不存在");
 
     // ==========  物流 PICK_UP 模块 1011006000 ==========
-
     ErrorCode PICK_UP_STORE_NOT_EXISTS = new ErrorCode(1011006000, "自提门店不存在");
 
+    // ==========  物流 PICK_UP 模块 1011007000 ==========
+    // TODO @puhui999:这几个错误码,应该属于订单哈
+    ErrorCode ORDER_DELIVERY_FAILED_ITEMS_NOT_EMPTY = new ErrorCode(1011007000, "订单发货失败,请选择发货商品");
+    ErrorCode ORDER_DELIVERY_FAILED_ITEM_NOT_EXISTS = new ErrorCode(1011007001, "订单发货失败,所选发货商品不存在");
+    ErrorCode ORDER_DELIVERY_FAILED_ITEM_ALREADY_DELIVERY = new ErrorCode(1011007002, "订单发货失败,所选商品已发货");
 
 }
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderDeliveryReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderDeliveryReqVO.java
index 039fb2f09..7564d304b 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderDeliveryReqVO.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderDeliveryReqVO.java
@@ -1,10 +1,12 @@
 package cn.iocoder.yudao.module.trade.controller.admin.order.vo;
 
+import cn.iocoder.yudao.framework.common.validation.InEnum;
+import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
-import javax.validation.constraints.NotEmpty;
 import javax.validation.constraints.NotNull;
+import java.util.List;
 
 @Schema(description = "管理后台 - 订单发货 Request VO")
 @Data
@@ -14,12 +16,26 @@ public class TradeOrderDeliveryReqVO {
     @NotNull(message = "订单编号不能为空")
     private Long id;
 
-    @Schema(description = "发货物流公司编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @NotNull(message = "发货物流公司编号不能为空")
+    @Schema(description = "发货类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
+    @InEnum(DeliveryTypeEnum.class)
+    @NotNull(message = "发货类型不能为空")
+    private Integer type;
+
+    // TODO @puhui999:还是要校验下
+
+    @Schema(description = "发货物流公司编号", example = "1")
     private Long logisticsId;
 
-    @Schema(description = "发货物流单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "SF123456789")
-    @NotEmpty(message = "发货物流单号不能为空")
+    @Schema(description = "发货物流单号", example = "SF123456789")
     private String logisticsNo;
 
+    // TODO 订单项商品单独发货;不做单独发
+
+    @Schema(description = "发货订单项", example = "[1,2,3]")
+    @NotNull(message = "发货订单项不能为空")
+    private List<Long> orderItemIds;
+
+    // =============== 同城配送  ================
+    // TODO
+
 }
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
index 6567e3169..765ed58c4 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
@@ -4,8 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
 import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO;
-import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi;
-import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
 import cn.iocoder.yudao.module.product.api.property.ProductPropertyValueApi;
 import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
 import cn.iocoder.yudao.module.trade.controller.app.order.vo.*;
@@ -30,13 +28,10 @@ import javax.validation.Valid;
 import java.util.List;
 import java.util.Map;
 
-import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
-import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_ITEM_NOT_FOUND;
-import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_NOT_FOUND;
 
 @Tag(name = "用户 App - 交易订单")
 @RestController
@@ -47,12 +42,8 @@ public class AppTradeOrderController {
 
     @Resource
     private TradeOrderService tradeOrderService;
-
     @Resource
     private ProductPropertyValueApi productPropertyValueApi;
-    @Resource
-    private ProductCommentApi productCommentApi;
-
     @Resource
     private TradeOrderProperties tradeOrderProperties;
 
@@ -117,13 +108,17 @@ public class AppTradeOrderController {
         // 全部
         orderCount.put("allCount", tradeOrderService.getOrderCount(getLoginUserId(), null, null));
         // 待付款(未支付)
-        orderCount.put("unpaidCount", tradeOrderService.getOrderCount(getLoginUserId(), TradeOrderStatusEnum.UNPAID.getStatus(), null));
+        orderCount.put("unpaidCount", tradeOrderService.getOrderCount(getLoginUserId(),
+                TradeOrderStatusEnum.UNPAID.getStatus(), null));
         // 待发货
-        orderCount.put("undeliveredCount", tradeOrderService.getOrderCount(getLoginUserId(), TradeOrderStatusEnum.UNDELIVERED.getStatus(), null));
+        orderCount.put("undeliveredCount", tradeOrderService.getOrderCount(getLoginUserId(),
+                TradeOrderStatusEnum.UNDELIVERED.getStatus(), null));
         // 待收货
-        orderCount.put("deliveredCount", tradeOrderService.getOrderCount(getLoginUserId(),  TradeOrderStatusEnum.DELIVERED.getStatus(), null));
+        orderCount.put("deliveredCount", tradeOrderService.getOrderCount(getLoginUserId(),
+                TradeOrderStatusEnum.DELIVERED.getStatus(), null));
         // 待评价
-        orderCount.put("uncommentedCount", tradeOrderService.getOrderCount(getLoginUserId(), TradeOrderStatusEnum.COMPLETED.getStatus(), false));
+        orderCount.put("uncommentedCount", tradeOrderService.getOrderCount(getLoginUserId(),
+                TradeOrderStatusEnum.COMPLETED.getStatus(), false));
         return success(orderCount);
     }
 
@@ -164,22 +159,7 @@ public class AppTradeOrderController {
     @PostMapping("/item/create-comment")
     @Operation(summary = "创建交易订单项的评价")
     public CommonResult<Long> createOrderItemComment(@RequestBody AppTradeOrderItemCommentCreateReqVO createReqVO) {
-        // TODO @puhui999:这个逻辑,最好写到 service 哈;
-        Long loginUserId = getLoginUserId();
-        // 先通过订单项 ID 查询订单项是否存在
-        TradeOrderItemDO orderItemDO = tradeOrderService.getOrderItemByIdAndUserId(createReqVO.getOrderItemId(), loginUserId);
-        if (orderItemDO == null) {
-            throw exception(ORDER_ITEM_NOT_FOUND);
-        }
-        // 校验订单
-        TradeOrderDO orderDO = tradeOrderService.getOrderByIdAndUserId(orderItemDO.getOrderId(), loginUserId);
-        if (orderDO == null) {
-            throw exception(ORDER_NOT_FOUND);
-        }
-        // TODO @puhui999:要校验订单已完成,但是未评价;
-
-        ProductCommentCreateReqDTO productCommentCreateReqDTO = TradeOrderConvert.INSTANCE.convert04(createReqVO, orderItemDO);
-        return success(productCommentApi.createComment(productCommentCreateReqDTO));
+        return success(tradeOrderService.createOrderItemComment(createReqVO));
     }
 
 }
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java
index f3a7d9120..3e322c786 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java
@@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.trade.controller.app.order.vo;
 import cn.iocoder.yudao.framework.common.validation.InEnum;
 import cn.iocoder.yudao.framework.common.validation.Mobile;
 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
-import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
@@ -19,11 +18,6 @@ import java.util.List;
 @Data
 public class AppTradeOrderSettlementReqVO {
 
-    @NotNull(message = "交易类型不能为空")
-    @InEnum(value = TradeOrderTypeEnum.class, message = "交易类型必须是 {value}")
-    @Deprecated // TODO 芋艿:后续干掉这个字段,对于前端不需要关注这个
-    private Integer type = 1;
-
     @Schema(description = "商品项数组", requiredMode = Schema.RequiredMode.REQUIRED)
     @NotEmpty(message = "商品不能为空")
     private List<Item> items;
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/item/AppTradeOrderItemCommentCreateReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/item/AppTradeOrderItemCommentCreateReqVO.java
index 349b071d5..69ffef241 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/item/AppTradeOrderItemCommentCreateReqVO.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/item/AppTradeOrderItemCommentCreateReqVO.java
@@ -19,11 +19,6 @@ public class AppTradeOrderItemCommentCreateReqVO {
     @NotNull(message = "交易订单项编号不能为空")
     private Long orderItemId;
 
-    // TODO @puhui999:貌似不用这个字段哈;
-    @Schema(description = "评分星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
-    @NotNull(message = "评分星级 1-5 分不能为空")
-    private Integer scores;
-
     @Schema(description = "描述星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
     @NotNull(message = "描述星级 1-5 分不能为空")
     private Integer descriptionScores;
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
index 21534f47a..da9269d8d 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
@@ -13,10 +13,12 @@ import cn.iocoder.yudao.module.pay.enums.DictTypeConstants;
 import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
 import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
+import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordReqDTO;
 import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;
 import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO;
 import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO;
 import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO;
+import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDetailRespVO;
 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageItemRespVO;
 import cn.iocoder.yudao.module.trade.controller.app.base.property.AppProductPropertyValueDetailRespVO;
@@ -25,6 +27,7 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderI
 import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO;
 import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO;
 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
+import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDeliveryDO;
 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum;
 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
@@ -52,7 +55,6 @@ public interface TradeOrderConvert {
             @Mapping(source = "createReqVO.couponId", target = "couponId"),
             @Mapping(target = "remark", ignore = true),
             @Mapping(source = "createReqVO.remark", target = "userRemark"),
-            @Mapping(source = "createReqVO.type", target = "type"),
             @Mapping(source = "calculateRespBO.price.totalPrice", target = "totalPrice"),
             @Mapping(source = "calculateRespBO.price.discountPrice", target = "discountPrice"),
             @Mapping(source = "calculateRespBO.price.deliveryPrice", target = "deliveryPrice"),
@@ -123,7 +125,7 @@ public interface TradeOrderConvert {
     // TODO 芋艿:可简化
     default PageResult<TradeOrderPageItemRespVO> convertPage(PageResult<TradeOrderDO> pageResult, List<TradeOrderItemDO> orderItems,
                                                              List<ProductPropertyValueDetailRespDTO> propertyValueDetails,
-                                                             Map<Long,MemberUserRespDTO> memberUserRespDTOMap) {
+                                                             Map<Long, MemberUserRespDTO> memberUserRespDTOMap) {
         Map<Long, List<TradeOrderItemDO>> orderItemMap = convertMultiMap(orderItems, TradeOrderItemDO::getOrderId);
         Map<Long, ProductPropertyValueDetailRespDTO> propertyValueDetailMap = convertMap(propertyValueDetails, ProductPropertyValueDetailRespDTO::getValueId);
         // 转化 List
@@ -267,23 +269,23 @@ public interface TradeOrderConvert {
 
     AppTradeOrderItemRespVO convert03(TradeOrderItemDO bean);
 
-    @Mapping(target = "skuId", source = "tradeOrderItemDO.skuId")
-    @Mapping(target = "orderId", source = "tradeOrderItemDO.orderId")
-    @Mapping(target = "orderItemId", source = "tradeOrderItemDO.id")
-    @Mapping(target = "scores", source = "createReqVO.scores")
-    @Mapping(target = "descriptionScores", source = "createReqVO.descriptionScores")
-    @Mapping(target = "benefitScores", source = "createReqVO.benefitScores")
-    @Mapping(target = "content", source = "createReqVO.content")
-    @Mapping(target = "picUrls", source = "createReqVO.picUrls")
-    @Mapping(target = "anonymous", source = "createReqVO.anonymous")
-    @Mapping(target = "userId", source = "tradeOrderItemDO.userId")
+    @Mappings({
+            @Mapping(target = "skuId", source = "tradeOrderItemDO.skuId"),
+            @Mapping(target = "orderId", source = "tradeOrderItemDO.orderId"),
+            @Mapping(target = "orderItemId", source = "tradeOrderItemDO.id"),
+            @Mapping(target = "descriptionScores", source = "createReqVO.descriptionScores"),
+            @Mapping(target = "benefitScores", source = "createReqVO.benefitScores"),
+            @Mapping(target = "content", source = "createReqVO.content"),
+            @Mapping(target = "picUrls", source = "createReqVO.picUrls"),
+            @Mapping(target = "anonymous", source = "createReqVO.anonymous"),
+            @Mapping(target = "userId", source = "tradeOrderItemDO.userId")
+    })
     ProductCommentCreateReqDTO convert04(AppTradeOrderItemCommentCreateReqVO createReqVO, TradeOrderItemDO tradeOrderItemDO);
 
     default TradePriceCalculateReqBO convert(Long userId, AppTradeOrderSettlementReqVO settlementReqVO,
                                              List<TradeCartDO> cartList) {
         TradePriceCalculateReqBO reqBO = new TradePriceCalculateReqBO();
-        reqBO.setUserId(userId).setType(settlementReqVO.getType())
-                .setCouponId(settlementReqVO.getCouponId()).setAddressId(settlementReqVO.getAddressId())
+        reqBO.setUserId(userId).setCouponId(settlementReqVO.getCouponId()).setAddressId(settlementReqVO.getAddressId())
                 .setItems(new ArrayList<>(settlementReqVO.getItems().size()));
         // 商品项的构建
         Map<Long, TradeCartDO> cartMap = convertMap(cartList, TradeCartDO::getId);
@@ -318,4 +320,31 @@ public interface TradeOrderConvert {
 
     AppTradeOrderSettlementRespVO convert0(TradePriceCalculateRespBO calculate, AddressRespDTO address);
 
+    @Mappings({
+            @Mapping(target = "activityId", source = "createReqVO.combinationActivityId"),
+            @Mapping(target = "spuId", source = "orderItem.spuId"),
+            @Mapping(target = "skuId", source = "orderItem.skuId"),
+            @Mapping(target = "userId", source = "order.userId"),
+            @Mapping(target = "orderId", source = "order.id"),
+            @Mapping(target = "headId", source = "createReqVO.combinationHeadId"),
+            @Mapping(target = "spuName", source = "orderItem.spuName"),
+            @Mapping(target = "picUrl", source = "orderItem.picUrl"),
+            @Mapping(target = "combinationPrice", source = "orderItem.payPrice"),
+            @Mapping(target = "nickname", source = "user.nickname"),
+            @Mapping(target = "avatar", source = "user.avatar"),
+            @Mapping(target = "status", ignore = true)
+    })
+    CombinationRecordReqDTO convert(TradeOrderDO order, TradeOrderItemDO orderItem, AppTradeOrderCreateReqVO createReqVO, MemberUserRespDTO user);
+
+    TradeOrderDeliveryDO covert(Long orderId, Long orderItemId, Long userId, Integer deliveryType, Long logisticsId, String logisticsNo);
+
+    default List<TradeOrderDeliveryDO> covert(TradeOrderDO order, TradeOrderDeliveryReqVO deliveryReqVO) {
+        ArrayList<TradeOrderDeliveryDO> arrayList = new ArrayList<>();
+        deliveryReqVO.getOrderItemIds().forEach(item -> {
+            arrayList.add(covert(order.getId(), item, order.getUserId(), deliveryReqVO.getType(),
+                    deliveryReqVO.getLogisticsId(), deliveryReqVO.getLogisticsNo()));
+        });
+        return arrayList;
+    }
+
 }
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDeliveryDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDeliveryDO.java
new file mode 100644
index 000000000..4e1416afd
--- /dev/null
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDeliveryDO.java
@@ -0,0 +1,60 @@
+package cn.iocoder.yudao.module.trade.dal.dataobject.order;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+// TODO @puhui999:
+/**
+ * 交易订单发货记录 DO
+ *
+ * @author HUIHUI
+ */
+@TableName("trade_order_delivery")
+@KeySequence("trade_order_delivery_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class TradeOrderDeliveryDO extends BaseDO {
+
+    /**
+     * 订单发货记录 id
+     */
+    private Long id;
+    /**
+     * 订单 id
+     */
+    private Long orderId;
+    /**
+     * 订单项 id TODO 要不要一个发货记录可对应多个订单项?
+     */
+    private Long orderItemId;
+    /**
+     * 用户编号
+     *
+     * 关联 MemberUserDO 的 id 编号
+     */
+    private Long userId;
+    /**
+     * 配送方式
+     *
+     * 枚举 {@link DeliveryTypeEnum}
+     */
+    private Integer deliveryType;
+    /**
+     * 发货物流公司编号
+     */
+    private Long logisticsId;
+    /**
+     * 发货物流单号
+     */
+    private String logisticsNo;
+
+    // TODO 同城配送
+
+}
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderDeliveryMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderDeliveryMapper.java
new file mode 100644
index 000000000..f40bb07ce
--- /dev/null
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderDeliveryMapper.java
@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.module.trade.dal.mysql.order;
+
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDeliveryDO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+// TODO @puhui999:应该去掉啦
+/**
+ * 交易订单发货记录 Mapper
+ *
+ * @author HUIHUI
+ */
+@Mapper
+public interface TradeOrderDeliveryMapper extends BaseMapperX<TradeOrderDeliveryDO> {
+
+    default List<TradeOrderDeliveryDO> selsectListByOrderIdAndItemIds(Long orderId, List<Long> orderItemIds) {
+        return selectList(new LambdaQueryWrapperX<TradeOrderDeliveryDO>()
+                .eq(TradeOrderDeliveryDO::getOrderId, orderId).in(TradeOrderDeliveryDO::getOrderItemId, orderItemIds));
+    }
+
+}
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderService.java
index d49baf49c..bb234ab85 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderService.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderService.java
@@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreate
 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO;
 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementReqVO;
 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO;
+import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO;
 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
 
@@ -177,4 +178,13 @@ public interface TradeOrderService {
      * @return 得到订单
      */
     TradeOrderDO getOrderByIdAndUserId(Long orderId, Long loginUserId);
+
+    /**
+     * 创建订单项的评论
+     *
+     * @param createReqVO 创建请求
+     * @return 得到评价 id
+     */
+    Long createOrderItemComment(AppTradeOrderItemCommentCreateReqVO createReqVO);
+
 }
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java
index 48c709962..d67b336ec 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java
@@ -17,24 +17,30 @@ import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
+import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi;
+import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
+import cn.iocoder.yudao.module.promotion.api.combination.CombinationApi;
 import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi;
 import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO;
+import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
 import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
 import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO;
-import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO;
 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;
 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO;
 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementReqVO;
 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO;
+import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO;
 import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
 import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO;
 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
+import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDeliveryDO;
 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
+import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderDeliveryMapper;
 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper;
 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
 import cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants;
@@ -57,6 +63,7 @@ import java.util.*;
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue;
+import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.ORDER_NOT_FOUND;
 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
 
@@ -93,13 +100,17 @@ public class TradeOrderServiceImpl implements TradeOrderService {
     @Resource
     private MemberUserApi memberUserApi;
     @Resource
-    private AdminUserApi adminUserApi;
+    private ProductCommentApi productCommentApi;
     @Resource
     private NotifyMessageSendApi notifyMessageSendApi;
 
     @Resource
     private TradeOrderProperties tradeOrderProperties;
 
+    @Resource
+    private CombinationApi combinationApi;
+    @Resource
+    private TradeOrderDeliveryMapper orderDeliveryMapper;
     // =================== Order ===================
 
     @Override
@@ -153,19 +164,27 @@ public class TradeOrderServiceImpl implements TradeOrderService {
     @Override
     @Transactional(rollbackFor = Exception.class)
     public TradeOrderDO createOrder(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO) {
-        // 1. 用户收件地址的校验
-        AddressRespDTO address = validateAddress(userId, createReqVO.getAddressId());
-
         // 2. 价格计算
         TradePriceCalculateRespBO calculateRespBO = calculatePrice(userId, createReqVO);
-
         // 3.1 插入 TradeOrderDO 订单
-        TradeOrderDO order = createTradeOrder(userId, userIp, createReqVO, calculateRespBO, address);
+        TradeOrderDO order = createTradeOrder(userId, userIp, createReqVO, calculateRespBO);
         // 3.2 插入 TradeOrderItemDO 订单项
         List<TradeOrderItemDO> orderItems = createTradeOrderItems(order, calculateRespBO);
-
         // 订单创建完后的逻辑
         afterCreateTradeOrder(userId, createReqVO, order, orderItems, calculateRespBO);
+        // 3.3 校验订单类型
+        // 拼团
+        if (ObjectUtil.equal(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) {
+            MemberUserRespDTO user = memberUserApi.getUser(userId);
+            // TODO 拼团一次应该只能选择一种规格的商品
+            combinationApi.createRecord(TradeOrderConvert.INSTANCE.convert(order, orderItems.get(0), createReqVO, user)
+                    .setStatus(CombinationRecordStatusEnum.WAITING.getStatus()));
+        }
+        // TODO 秒杀扣减库存是下单就扣除还是等待订单支付成功再扣除
+        if (ObjectUtil.equal(TradeOrderTypeEnum.SECKILL.getType(), order.getType())) {
+
+        }
+
         // TODO @LeeYan9: 是可以思考下, 订单的营销优惠记录, 应该记录在哪里, 微信讨论起来!
         return order;
     }
@@ -186,24 +205,47 @@ public class TradeOrderServiceImpl implements TradeOrderService {
     }
 
     private TradeOrderDO createTradeOrder(Long userId, String clientIp, AppTradeOrderCreateReqVO createReqVO,
-                                          TradePriceCalculateRespBO calculateRespBO, AddressRespDTO address) {
+                                          TradePriceCalculateRespBO calculateRespBO) {
+        // 用户选择物流配送的时候才需要填写收货地址
+        AddressRespDTO address = new AddressRespDTO();
+        if (ObjectUtil.equal(createReqVO.getDeliveryType(), DeliveryTypeEnum.EXPRESS.getMode())) {
+            // 用户收件地址的校验
+            address = validateAddress(userId, createReqVO.getAddressId());
+        }
         TradeOrderDO order = TradeOrderConvert.INSTANCE.convert(userId, clientIp, createReqVO, calculateRespBO, address);
+        order.setType(validateActivity(createReqVO));
         order.setNo(IdUtil.getSnowflakeNextId() + ""); // TODO @LeeYan9: 思考下, 怎么生成好点哈; 这个是会展示给用户的;
         order.setStatus(TradeOrderStatusEnum.UNPAID.getStatus());
-        order.setType(TradeOrderTypeEnum.NORMAL.getType());
         order.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus());
         order.setProductCount(getSumValue(calculateRespBO.getItems(), TradePriceCalculateRespBO.OrderItem::getCount, Integer::sum));
         order.setTerminal(TerminalEnum.H5.getTerminal()); // todo 数据来源?
         // 支付信息
         order.setAdjustPrice(0).setPayStatus(false);
         // 物流信息 TODO 芋艿:暂时写死物流方式;应该是前端选择的
-        order.setDeliveryType(DeliveryTypeEnum.EXPRESS.getMode()).setDeliveryStatus(TradeOrderDeliveryStatusEnum.UNDELIVERED.getStatus());
+        order.setDeliveryType(createReqVO.getDeliveryType()).setDeliveryStatus(TradeOrderDeliveryStatusEnum.UNDELIVERED.getStatus());
         // 退款信息
         order.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()).setRefundPrice(0);
         tradeOrderMapper.insert(order);
         return order;
     }
 
+    /**
+     * 校验活动,并返回订单类型
+     *
+     * @param createReqVO 请求参数
+     * @return 订单类型
+     */
+    private Integer validateActivity(AppTradeOrderCreateReqVO createReqVO) {
+        if (createReqVO.getSeckillActivityId() != null) {
+            return TradeOrderTypeEnum.SECKILL.getType();
+        }
+        if (createReqVO.getCombinationActivityId() != null) {
+            return TradeOrderTypeEnum.COMBINATION.getType();
+        }
+        // TODO 砍价敬请期待
+        return TradeOrderTypeEnum.NORMAL.getType();
+    }
+
     private List<TradeOrderItemDO> createTradeOrderItems(TradeOrderDO tradeOrderDO, TradePriceCalculateRespBO calculateRespBO) {
         List<TradeOrderItemDO> orderItems = TradeOrderConvert.INSTANCE.convertList(tradeOrderDO, calculateRespBO);
         tradeOrderItemMapper.insertBatch(orderItems);
@@ -212,7 +254,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
 
     /**
      * 执行创建完创建完订单后的逻辑
-     * <p>
+     *
      * 例如说:优惠劵的扣减、积分的扣减、支付单的创建等等
      *
      * @param userId          用户编号
@@ -254,6 +296,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public void updateOrderPaid(Long id, Long payOrderId) {
         // 校验并获得交易订单(可支付)
         KeyValue<TradeOrderDO, PayOrderRespDTO> orderResult = validateOrderPayable(id, payOrderId);
@@ -267,7 +310,12 @@ public class TradeOrderServiceImpl implements TradeOrderService {
         if (updateCount == 0) {
             throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID);
         }
-
+        // 校验活动
+        // 1、拼团活动
+        if (ObjectUtil.equal(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) {
+            // 更新拼团状态 TODO puhui999:订单支付失败或订单支付过期删除这条拼团记录
+            combinationApi.updateRecordStatusAndStartTime(order.getUserId(), order.getId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus());
+        }
         // TODO 芋艿:发送订单变化的消息
 
         // TODO 芋艿:发送站内信
@@ -277,7 +325,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
 
     /**
      * 校验交易订单满足被支付的条件
-     * <p>
+     *
      * 1. 交易订单未支付
      * 2. 支付单已支付
      *
@@ -308,7 +356,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
         PayOrderRespDTO payOrder = payOrderApi.getOrder(payOrderId);
         if (payOrder == null) {
             log.error("[validateOrderPaid][order({}) payOrder({}) 不存在,请进行处理!]", id, payOrderId);
-            throw exception(cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.ORDER_NOT_FOUND);
+            throw exception(ORDER_NOT_FOUND);
         }
         // 校验支付单已支付
         if (!PayOrderStatusEnum.isSuccess(payOrder.getStatus())) {
@@ -331,29 +379,51 @@ public class TradeOrderServiceImpl implements TradeOrderService {
         return new KeyValue<>(order, payOrder);
     }
 
-    // TODO 芋艿:如果无需发货,需要怎么存储?
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public void deliveryOrder(Long userId, TradeOrderDeliveryReqVO deliveryReqVO) {
         // 校验并获得交易订单(可发货)
         TradeOrderDO order = validateOrderDeliverable(deliveryReqVO.getId());
-        // TODO 芋艿:logisticsId 校验存在 发货物流公司 fix
-        DeliveryExpressDO deliveryExpress = deliveryExpressService.getDeliveryExpress(deliveryReqVO.getLogisticsId());
-        if (deliveryExpress == null) {
-            throw exception(EXPRESS_NOT_EXISTS);
+
+        TradeOrderDO tradeOrderDO = new TradeOrderDO();
+        List<TradeOrderDeliveryDO> deliveryDOs = new ArrayList<>();
+        /* TODO
+         * fix: 首先需要店铺设置配送方式如: 自提 、配送、物流-配送、物流-配送-自提、商家配送
+         * 1.如果店铺有设置配送方式用户只填写收货地址的情况下店家后台自己选择配送方式
+         * 2.如果店铺只支持到店自提那么下单后默认发货不需要物流
+         * 3.如果店铺支持 物流-配送-自提 的情况下后台不需要选择配送方式按前端用户选择的配送方式发货即可
+         */
+        // 判断发货类型
+        // 快递发货
+        if (ObjectUtil.equal(deliveryReqVO.getType(), DeliveryTypeEnum.EXPRESS.getMode())) {
+            deliveryDOs = express(order, deliveryReqVO);
+            tradeOrderDO.setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo());
+        }
+        // 用户自提
+        if (ObjectUtil.equal(deliveryReqVO.getType(), DeliveryTypeEnum.PICK_UP.getMode())) {
+            deliveryDOs = pickUp(order, deliveryReqVO);
+            // 重置一下确保快递公司和快递单号为空
+            tradeOrderDO.setLogisticsId(null).setLogisticsNo("");
+        }
+        // TODO 芋艿:如果无需发货,需要怎么存储?
+        if (ObjectUtil.equal(deliveryReqVO.getType(), DeliveryTypeEnum.NULL.getMode())) {
+            // TODO 情况一:正常走发货逻辑和用户自提有点像 不同点:不需要自提门店只需要用户确认收货
+            // TODO 情况二:用户下单付款后直接确认收货或等待用户确认收货
         }
 
         // 更新 TradeOrderDO 状态为已发货,等待收货
-        int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(),
-                new TradeOrderDO().setStatus(TradeOrderStatusEnum.DELIVERED.getStatus())
-                        .setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo())
-                        .setDeliveryStatus(TradeOrderDeliveryStatusEnum.DELIVERED.getStatus()).setDeliveryTime(LocalDateTime.now()));
+        tradeOrderDO.setStatus(TradeOrderStatusEnum.DELIVERED.getStatus())
+                .setDeliveryStatus(TradeOrderDeliveryStatusEnum.DELIVERED.getStatus()).setDeliveryTime(LocalDateTime.now());
+        int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), tradeOrderDO);
         if (updateCount == 0) {
             throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED);
         }
-
+        // 发货成功记录发货表
+        orderDeliveryMapper.insertBatch(deliveryDOs);
         // TODO 芋艿:发送订单变化的消息
 
-        // TODO 芋艿:发送站内信 fix
+        // TODO @puhui999:可以抽个 message 包,里面是 Order 所有的 message;类似工作流的
+        // 发送站内信
         // 1、构造消息
         Map<String, Object> msgMap = new HashMap<>();
         msgMap.put("orderId", deliveryReqVO.getId());
@@ -364,16 +434,59 @@ public class TradeOrderServiceImpl implements TradeOrderService {
                         .setUserId(userId)
                         .setTemplateCode("order_delivery")
                         .setTemplateParams(msgMap));
-        // TODO 芋艿:OrderLog
 
-        // TODO 设计:like:是否要单独一个 delivery 发货单表???
-        // TODO 设计:niu:要不要支持一个订单下,多个 order item 单独发货,类似有赞
+        // TODO 芋艿:OrderLog
         // TODO 设计:lili:是不是发货后,才支持售后?
     }
 
+    private List<TradeOrderDeliveryDO> express(TradeOrderDO order, TradeOrderDeliveryReqVO deliveryReqVO) {
+        // 校验快递公司
+        DeliveryExpressDO deliveryExpress = deliveryExpressService.getDeliveryExpress(deliveryReqVO.getLogisticsId());
+        if (deliveryExpress == null) {
+            throw exception(EXPRESS_NOT_EXISTS);
+        }
+        // 校验发货商品
+        validateDeliveryOrderItem(order, deliveryReqVO);
+        // 创建发货记录
+        return TradeOrderConvert.INSTANCE.covert(order, deliveryReqVO);
+    }
+
+    private List<TradeOrderDeliveryDO> pickUp(TradeOrderDO order, TradeOrderDeliveryReqVO deliveryReqVO) {
+        // TODO 校验自提门店是否存在
+        // 重置一下确保快递公司和快递单号为空
+        deliveryReqVO.setLogisticsId(null);
+        deliveryReqVO.setLogisticsNo("");
+        // 校验发货商品
+        validateDeliveryOrderItem(order, deliveryReqVO);
+        // 创建发货记录
+        return TradeOrderConvert.INSTANCE.covert(order, deliveryReqVO);
+    }
+
+    private void validateDeliveryOrderItem(TradeOrderDO order, TradeOrderDeliveryReqVO deliveryReqVO) {
+        // TODO 设计:like:是否要单独一个 delivery 发货单表??? fix: 多商品可分开单独发货,添加 trade_order_delivery 交易订单发货日志表关联发货所选订单项设置物流单号
+        // TODO 设计:niu:要不要支持一个订单下,多个 order item 单独发货,类似有赞 fix
+        // 校验发货商品
+        if (CollUtil.isEmpty(deliveryReqVO.getOrderItemIds())) {
+            throw exception(ORDER_DELIVERY_FAILED_ITEMS_NOT_EMPTY);
+        }
+        // 校验发货商品是否存在
+        List<TradeOrderItemDO> orderItemDOs = tradeOrderItemMapper.selectListByOrderId(order.getId());
+        Set<Long> itemIds = convertSet(orderItemDOs, TradeOrderItemDO::getId);
+        if (!itemIds.containsAll(deliveryReqVO.getOrderItemIds())) {
+            throw exception(ORDER_DELIVERY_FAILED_ITEM_NOT_EXISTS);
+        }
+        // 校验所选订单项是否存在有已发货的
+        List<TradeOrderDeliveryDO> deliveryDOList = orderDeliveryMapper.selsectListByOrderIdAndItemIds(order.getId(), deliveryReqVO.getOrderItemIds());
+        if (CollUtil.isNotEmpty(deliveryDOList)) {
+            HashSet<Long> hashSet = CollUtil.newHashSet(deliveryReqVO.getOrderItemIds());
+            hashSet.retainAll(convertSet(deliveryDOList, TradeOrderDeliveryDO::getOrderItemId));
+            throw exception(ORDER_DELIVERY_FAILED_ITEM_ALREADY_DELIVERY);
+        }
+    }
+
     /**
      * 校验交易订单满足被发货的条件
-     * <p>
+     *
      * 1. 交易订单未发货
      *
      * @param id 交易订单编号
@@ -390,6 +503,19 @@ public class TradeOrderServiceImpl implements TradeOrderService {
                 || ObjectUtil.notEqual(order.getDeliveryStatus(), TradeOrderDeliveryStatusEnum.UNDELIVERED.getStatus())) {
             throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED);
         }
+        // 校验订单是否退款
+        if (ObjectUtil.notEqual(TradeOrderRefundStatusEnum.NONE.getStatus(), order.getRefundStatus())) {
+            throw exception(ORDER_DELIVERY_FAIL_REFUND_STATUS_NOT_NONE);
+        }
+        // 订单类型:拼团
+        if (ObjectUtil.equal(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) {
+            // 校验订单拼团是否成功
+            // TODO 用户 ID 使用当前登录用户的还是订单保存的?
+            if (combinationApi.validateRecordStatusIsSuccess(order.getUserId(), order.getId())) {
+                throw exception(ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS);
+            }
+        }
+        // TODO puhui999: 校验订单砍价是否成功
         return order;
     }
 
@@ -421,7 +547,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
 
     /**
      * 校验交易订单满足可售货的条件
-     * <p>
+     *
      * 1. 交易订单待收货
      *
      * @param userId 用户编号
@@ -556,6 +682,32 @@ public class TradeOrderServiceImpl implements TradeOrderService {
         return tradeOrderMapper.selectOrderByIdAndUserId(orderId, loginUserId);
     }
 
+    @Override
+    public Long createOrderItemComment(AppTradeOrderItemCommentCreateReqVO createReqVO) {
+        Long loginUserId = getLoginUserId();
+        // 先通过订单项 ID,查询订单项是否存在
+        TradeOrderItemDO orderItem = getOrderItemByIdAndUserId(createReqVO.getOrderItemId(), loginUserId);
+        if (orderItem == null) {
+            throw exception(ORDER_ITEM_NOT_FOUND);
+        }
+        // 校验订单
+        TradeOrderDO order = getOrderByIdAndUserId(orderItem.getOrderId(), loginUserId);
+        if (order == null) {
+            throw exception(ORDER_NOT_FOUND);
+        }
+        if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.COMPLETED.getStatus())) {
+            throw exception(ORDER_COMMENT_FAIL_STATUS_NOT_COMPLETED);
+        }
+        if (ObjectUtil.notEqual(order.getCommentStatus(), Boolean.FALSE)) {
+            throw exception(ORDER_COMMENT_STATUS_NOT_FALSE);
+        }
+        // TODO @puhui999:是不是评论完,要更新 status、commentStatus;另外,是不是上面 order 可以不校验,直接只判断 orderItem 就够;
+        // 对于 order 来说,就是评论完,把 order 更新完合理的 status 等字段。
+
+        ProductCommentCreateReqDTO productCommentCreateReqDTO = TradeOrderConvert.INSTANCE.convert04(createReqVO, orderItem);
+        return productCommentApi.createComment(productCommentCreateReqDTO);
+    }
+
     /**
      * 判断指定订单的所有订单项,是不是都售后成功
      *
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceServiceImpl.java
index 0e9dc32c2..a6982c177 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceServiceImpl.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceServiceImpl.java
@@ -21,7 +21,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*;
-import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.PRICE_CALCULATE_PAY_PRICE_ILLEGAL;
+import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_PAY_PRICE_ILLEGAL;
 
 /**
  * 价格计算 Service 实现类
diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginReqVO.java
index fa5d77956..41762da67 100644
--- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginReqVO.java
+++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginReqVO.java
@@ -33,7 +33,7 @@ public class AppAuthLoginReqVO {
 
     // ========== 绑定社交登录时,需要传递如下参数 ==========
 
-    @Schema(description = "社交平台的类型,参见 SysUserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
+    @Schema(description = "社交平台的类型,参见 SysUserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
     @InEnum(SocialTypeEnum.class)
     private Integer socialType;
 
diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSmsLoginReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSmsLoginReqVO.java
index fb0f8a2ee..3a3f33155 100644
--- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSmsLoginReqVO.java
+++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSmsLoginReqVO.java
@@ -35,7 +35,7 @@ public class AppAuthSmsLoginReqVO {
 
     // ========== 绑定社交登录时,需要传递如下参数 ==========
 
-    @Schema(description = "社交平台的类型,参见 SysUserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
+    @Schema(description = "社交平台的类型,参见 SysUserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
     @InEnum(SocialTypeEnum.class)
     private Integer socialType;
 
diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialLoginReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialLoginReqVO.java
index c05fcb4f8..70bd0eacb 100644
--- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialLoginReqVO.java
+++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialLoginReqVO.java
@@ -18,7 +18,7 @@ import javax.validation.constraints.NotNull;
 @Builder
 public class AppAuthSocialLoginReqVO {
 
-    @Schema(description = "社交平台的类型,参见 SysUserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
+    @Schema(description = "社交平台的类型,参见 SysUserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
     @InEnum(SocialTypeEnum.class)
     @NotNull(message = "社交平台的类型不能为空")
     private Integer type;
diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserBindReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserBindReqVO.java
index a5f43fcb8..2e7c9cb38 100644
--- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserBindReqVO.java
+++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserBindReqVO.java
@@ -18,7 +18,7 @@ import javax.validation.constraints.NotNull;
 @Builder
 public class AppSocialUserBindReqVO {
 
-    @Schema(description = "社交平台的类型,参见 SysUserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
+    @Schema(description = "社交平台的类型,参见 SysUserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
     @InEnum(SocialTypeEnum.class)
     @NotNull(message = "社交平台的类型不能为空")
     private Integer type;
diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserUnbindReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserUnbindReqVO.java
index c5337f984..e2ff2a71b 100644
--- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserUnbindReqVO.java
+++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserUnbindReqVO.java
@@ -18,7 +18,7 @@ import javax.validation.constraints.NotNull;
 @Builder
 public class AppSocialUserUnbindReqVO {
 
-    @Schema(description = "社交平台的类型,参见 SysUserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
+    @Schema(description = "社交平台的类型,参见 SysUserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
     @InEnum(SocialTypeEnum.class)
     @NotNull(message = "社交平台的类型不能为空")
     private Integer type;
diff --git a/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImplTest.java b/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImplTest.java
index 77b40705e..c25b76ca6 100644
--- a/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImplTest.java
+++ b/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImplTest.java
@@ -19,10 +19,10 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
 
 /**
-* {@link AddressServiceImpl} 的单元测试类
-*
-* @author 芋道源码
-*/
+ * {@link AddressServiceImpl} 的单元测试类
+ *
+ * @author 芋道源码
+ */
 @Import(AddressServiceImpl.class)
 public class AddressServiceImplTest extends BaseDbUnitTest {
 
@@ -82,8 +82,8 @@ public class AddressServiceImplTest extends BaseDbUnitTest {
 
         // 调用
         addressService.deleteAddress(dbAddress.getUserId(), id);
-       // 校验数据不存在了
-       assertNull(addressMapper.selectById(id));
+        // 校验数据不存在了
+        assertNull(addressMapper.selectById(id));
     }
 
     @Test
diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/tag/vo/MpTagPageReqVO.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/tag/vo/MpTagPageReqVO.java
index 08cc0531b..0666b340a 100644
--- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/tag/vo/MpTagPageReqVO.java
+++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/tag/vo/MpTagPageReqVO.java
@@ -18,7 +18,7 @@ public class MpTagPageReqVO extends PageParam {
     @NotEmpty(message = "公众号账号的编号不能为空")
     private Long accountId;
 
-    @Schema(description = "标签名 模糊匹配", example = "哈哈")
+    @Schema(description = "标签名,模糊匹配", example = "哈哈")
     private String name;
 
 }
diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/user/vo/MpUserPageReqVO.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/user/vo/MpUserPageReqVO.java
index 814a4dbb8..84f7187dd 100644
--- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/user/vo/MpUserPageReqVO.java
+++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/user/vo/MpUserPageReqVO.java
@@ -18,10 +18,10 @@ public class MpUserPageReqVO extends PageParam {
     @NotNull(message = "公众号账号的编号不能为空")
     private Long accountId;
 
-    @Schema(description = "公众号粉丝标识 模糊匹配", example = "o6_bmjrPTlm6_2sgVt7hMZOPfL2M")
+    @Schema(description = "公众号粉丝标识,模糊匹配", example = "o6_bmjrPTlm6_2sgVt7hMZOPfL2M")
     private String openid;
 
-    @Schema(description = "公众号粉丝昵称 模糊匹配", example = "芋艿")
+    @Schema(description = "公众号粉丝昵称,模糊匹配", example = "芋艿")
     private String nickname;
 
 }
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java
index 7ef7012cc..59aab4f04 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java
@@ -55,6 +55,7 @@ public class AuthController {
     private PermissionService permissionService;
     @Resource
     private SocialUserService socialUserService;
+
     @Resource
     private SecurityProperties securityProperties;
 
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthSocialLoginReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthSocialLoginReqVO.java
index f98a4c894..1bbb67eda 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthSocialLoginReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthSocialLoginReqVO.java
@@ -18,7 +18,7 @@ import javax.validation.constraints.NotNull;
 @Builder
 public class AuthSocialLoginReqVO {
 
-    @Schema(description = "社交平台的类型,参见 UserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
+    @Schema(description = "社交平台的类型,参见 UserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
     @InEnum(SocialTypeEnum.class)
     @NotNull(message = "社交平台的类型不能为空")
     private Integer type;
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptListReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptListReqVO.java
index 469dc6ac6..131686f2d 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptListReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptListReqVO.java
@@ -7,10 +7,10 @@ import lombok.Data;
 @Data
 public class DeptListReqVO {
 
-    @Schema(description = "部门名称,模糊匹配", example = "芋道")
+    @Schema(description = "部门名称,模糊匹配", example = "芋道")
     private String name;
 
-    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
+    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
     private Integer status;
 
 }
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptRespVO.java
index aa062ec7b..d8d6a229b 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptRespVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptRespVO.java
@@ -14,7 +14,7 @@ public class DeptRespVO extends DeptBaseVO {
     @Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Long id;
 
-    @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer status;
 
     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostBaseVO.java
index c447cbc45..974f5202d 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostBaseVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostBaseVO.java
@@ -27,7 +27,7 @@ public class PostBaseVO {
     @NotNull(message = "显示顺序不能为空")
     private Integer sort;
 
-    @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer status;
 
     @Schema(description = "备注", example = "快乐的备注")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostExportReqVO.java
index 8b7cc79a3..48043969a 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostExportReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostExportReqVO.java
@@ -3,17 +3,17 @@ package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
-@Schema(description = "管理后台 - 岗位导出 Request VO,参数和 PostExcelVO 是一致的")
+@Schema(description = "管理后台 - 岗位导出 Request VO,参数和 PostExcelVO 是一致的")
 @Data
 public class PostExportReqVO {
 
-    @Schema(description = "岗位编码,模糊匹配", example = "yudao")
+    @Schema(description = "岗位编码,模糊匹配", example = "yudao")
     private String code;
 
-    @Schema(description = "岗位名称,模糊匹配", example = "芋道")
+    @Schema(description = "岗位名称,模糊匹配", example = "芋道")
     private String name;
 
-    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
+    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
     private Integer status;
 
 }
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostListReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostListReqVO.java
index abb166132..57993c4e7 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostListReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostListReqVO.java
@@ -9,10 +9,10 @@ import lombok.EqualsAndHashCode;
 @EqualsAndHashCode(callSuper = true)
 public class PostListReqVO extends PostBaseVO {
 
-    @Schema(description = "岗位名称,模糊匹配", example = "芋道")
+    @Schema(description = "岗位名称,模糊匹配", example = "芋道")
     private String name;
 
-    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
+    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
     private Integer status;
 
 }
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostPageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostPageReqVO.java
index 0806725f5..78f306edb 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostPageReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostPageReqVO.java
@@ -10,13 +10,13 @@ import lombok.EqualsAndHashCode;
 @EqualsAndHashCode(callSuper = true)
 public class PostPageReqVO extends PageParam {
 
-    @Schema(description = "岗位编码,模糊匹配", example = "yudao")
+    @Schema(description = "岗位编码,模糊匹配", example = "yudao")
     private String code;
 
-    @Schema(description = "岗位名称,模糊匹配", example = "芋道")
+    @Schema(description = "岗位名称,模糊匹配", example = "芋道")
     private String name;
 
-    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
+    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
     private Integer status;
 
 }
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataExportReqVO.java
index 60e91db19..0d7fc748a 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataExportReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataExportReqVO.java
@@ -13,11 +13,11 @@ public class DictDataExportReqVO {
     @Size(max = 100, message = "字典标签长度不能超过100个字符")
     private String label;
 
-    @Schema(description = "字典类型,模糊匹配", example = "sys_common_sex")
+    @Schema(description = "字典类型,模糊匹配", example = "sys_common_sex")
     @Size(max = 100, message = "字典类型类型长度不能超过100个字符")
     private String dictType;
 
-    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
+    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
     private Integer status;
 
 }
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataPageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataPageReqVO.java
index bceec1600..7fcc2c96a 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataPageReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataPageReqVO.java
@@ -16,11 +16,11 @@ public class DictDataPageReqVO extends PageParam {
     @Size(max = 100, message = "字典标签长度不能超过100个字符")
     private String label;
 
-    @Schema(description = "字典类型,模糊匹配", example = "sys_common_sex")
+    @Schema(description = "字典类型,模糊匹配", example = "sys_common_sex")
     @Size(max = 100, message = "字典类型类型长度不能超过100个字符")
     private String dictType;
 
-    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
+    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
     private Integer status;
 
 }
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataSimpleRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataSimpleRespVO.java
index 1debf7ece..d1497c345 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataSimpleRespVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataSimpleRespVO.java
@@ -16,8 +16,9 @@ public class DictDataSimpleRespVO {
     @Schema(description = "字典标签", requiredMode = Schema.RequiredMode.REQUIRED, example = "男")
     private String label;
 
-    @Schema(description = "颜色类型,default、primary、success、info、warning、danger", example = "default")
+    @Schema(description = "颜色类型,default、primary、success、info、warning、danger", example = "default")
     private String colorType;
+
     @Schema(description = "css 样式", example = "btn-visible")
     private String cssClass;
 
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeBaseVO.java
index 9270ab834..996a32364 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeBaseVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeBaseVO.java
@@ -19,7 +19,7 @@ public class DictTypeBaseVO {
     @Size(max = 100, message = "字典类型名称长度不能超过100个字符")
     private String name;
 
-    @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "状态不能为空")
     private Integer status;
 
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeExportReqVO.java
index b7d227ea3..5a5147b69 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeExportReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeExportReqVO.java
@@ -12,13 +12,13 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
 @Data
 public class DictTypeExportReqVO {
 
-    @Schema(description = "字典类型名称,模糊匹配", example = "芋道")
+    @Schema(description = "字典类型名称,模糊匹配", example = "芋道")
     private String name;
 
-    @Schema(description = "字典类型,模糊匹配", example = "sys_common_sex")
+    @Schema(description = "字典类型,模糊匹配", example = "sys_common_sex")
     private String type;
 
-    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
+    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
     private Integer status;
 
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypePageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypePageReqVO.java
index 336836f89..80fde2e9c 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypePageReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypePageReqVO.java
@@ -16,14 +16,14 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
 @EqualsAndHashCode(callSuper = true)
 public class DictTypePageReqVO extends PageParam {
 
-    @Schema(description = "字典类型名称,模糊匹配", example = "芋道")
+    @Schema(description = "字典类型名称,模糊匹配", example = "芋道")
     private String name;
 
-    @Schema(description = "字典类型,模糊匹配", example = "sys_common_sex")
+    @Schema(description = "字典类型,模糊匹配", example = "sys_common_sex")
     @Size(max = 100, message = "字典类型类型长度不能超过100个字符")
     private String type;
 
-    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
+    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
     private Integer status;
 
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeExportReqVO.java
index cb2488ee8..a89d7190c 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeExportReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeExportReqVO.java
@@ -8,7 +8,7 @@ import java.time.LocalDateTime;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
-@Schema(description = "管理后台 - 错误码 Excel 导出 Request VO,参数和 InfErrorCodePageReqVO 是一致的")
+@Schema(description = "管理后台 - 错误码 Excel 导出 Request VO,参数和 InfErrorCodePageReqVO 是一致的")
 @Data
 public class ErrorCodeExportReqVO {
 
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodePageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodePageReqVO.java
index 8e5bbdb07..ba565d94c 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodePageReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodePageReqVO.java
@@ -17,7 +17,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
 @ToString(callSuper = true)
 public class ErrorCodePageReqVO extends PageParam {
 
-    @Schema(description = "错误码类型,参见 ErrorCodeTypeEnum 枚举类", example = "1")
+    @Schema(description = "错误码类型,参见 ErrorCodeTypeEnum 枚举类", example = "1")
     private Integer type;
 
     @Schema(description = "应用名", example = "dashboard")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeRespVO.java
index de616a3e4..bd8e35fef 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeRespVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeRespVO.java
@@ -16,7 +16,7 @@ public class ErrorCodeRespVO extends ErrorCodeBaseVO {
     @Schema(description = "错误码编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Long id;
 
-    @Schema(description = "错误码类型,参见 ErrorCodeTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "错误码类型,参见 ErrorCodeTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer type;
 
     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogBaseVO.java
index 477315946..0a8736a80 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogBaseVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogBaseVO.java
@@ -15,7 +15,7 @@ import javax.validation.constraints.Size;
 @Data
 public class LoginLogBaseVO {
 
-    @Schema(description = "日志类型,参见 LoginLogTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "日志类型,参见 LoginLogTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "日志类型不能为空")
     private Integer logType;
 
@@ -28,7 +28,7 @@ public class LoginLogBaseVO {
     @Size(max = 30, message = "用户账号长度不能超过30个字符")
     private String username;
 
-    @Schema(description = "登录结果,参见 LoginResultEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "登录结果,参见 LoginResultEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "登录结果不能为空")
     private Integer result;
 
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogExportReqVO.java
index a62d9da23..d957771e0 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogExportReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogExportReqVO.java
@@ -12,10 +12,10 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
 @Data
 public class LoginLogExportReqVO {
 
-    @Schema(description = "用户 IP,模拟匹配", example = "127.0.0.1")
+    @Schema(description = "用户 IP,模拟匹配", example = "127.0.0.1")
     private String userIp;
 
-    @Schema(description = "用户账号,模拟匹配", example = "芋道")
+    @Schema(description = "用户账号,模拟匹配", example = "芋道")
     private String username;
 
     @Schema(description = "操作状态", example = "true")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogPageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogPageReqVO.java
index 73f6d38a7..40e12a843 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogPageReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogPageReqVO.java
@@ -15,10 +15,10 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
 @EqualsAndHashCode(callSuper = true)
 public class LoginLogPageReqVO extends PageParam {
 
-    @Schema(description = "用户 IP,模拟匹配", example = "127.0.0.1")
+    @Schema(description = "用户 IP,模拟匹配", example = "127.0.0.1")
     private String userIp;
 
-    @Schema(description = "用户账号,模拟匹配", example = "芋道")
+    @Schema(description = "用户账号,模拟匹配", example = "芋道")
     private String username;
 
     @Schema(description = "操作状态", example = "true")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogRespVO.java
index a9f4f2acb..0d69e7d3c 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogRespVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogRespVO.java
@@ -20,7 +20,7 @@ public class LoginLogRespVO extends LoginLogBaseVO {
     @Schema(description = "用户编号", example = "666")
     private Long userId;
 
-    @Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    @Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
     @NotNull(message = "用户类型不能为空")
     private Integer userType;
 
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogBaseVO.java
index dde84ee58..c07cc8e1f 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogBaseVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogBaseVO.java
@@ -31,7 +31,7 @@ public class OperateLogBaseVO {
     @NotEmpty(message = "操作名")
     private String name;
 
-    @Schema(description = "操作分类,参见 OperateLogTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "操作分类,参见 OperateLogTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "操作分类不能为空")
     private Integer type;
 
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogExportReqVO.java
index c12aca80e..b25953027 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogExportReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogExportReqVO.java
@@ -12,13 +12,13 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
 @Data
 public class OperateLogExportReqVO {
 
-    @Schema(description = "操作模块,模拟匹配", example = "订单")
+    @Schema(description = "操作模块,模拟匹配", example = "订单")
     private String module;
 
-    @Schema(description = "用户昵称,模拟匹配", example = "芋道")
+    @Schema(description = "用户昵称,模拟匹配", example = "芋道")
     private String userNickname;
 
-    @Schema(description = "操作分类,参见 OperateLogTypeEnum 枚举类", example = "1")
+    @Schema(description = "操作分类,参见 OperateLogTypeEnum 枚举类", example = "1")
     private Integer type;
 
     @Schema(description = "操作状态", example = "true")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogPageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogPageReqVO.java
index 13a23ac02..5c1742e58 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogPageReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogPageReqVO.java
@@ -13,13 +13,13 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
 @Data
 public class OperateLogPageReqVO extends PageParam {
 
-    @Schema(description = "操作模块,模拟匹配", example = "订单")
+    @Schema(description = "操作模块,模拟匹配", example = "订单")
     private String module;
 
-    @Schema(description = "用户昵称,模拟匹配", example = "芋道")
+    @Schema(description = "用户昵称,模拟匹配", example = "芋道")
     private String userNickname;
 
-    @Schema(description = "操作分类,参见 OperateLogTypeEnum 枚举类", example = "1")
+    @Schema(description = "操作分类,参见 OperateLogTypeEnum 枚举类", example = "1")
     private Integer type;
 
     @Schema(description = "操作状态", example = "true")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountRespVO.java
index c8065d5b8..dcc42f408 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountRespVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountRespVO.java
@@ -8,7 +8,7 @@ import lombok.ToString;
 import javax.validation.constraints.NotNull;
 import java.time.LocalDateTime;
 
-@Schema(description ="管理后台 - 邮箱账号 Response VO")
+@Schema(description = "管理后台 - 邮箱账号 Response VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/log/MailLogBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/log/MailLogBaseVO.java
index a07958817..63d4224e6 100755
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/log/MailLogBaseVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/log/MailLogBaseVO.java
@@ -20,7 +20,7 @@ public class MailLogBaseVO {
     @Schema(description = "用户编号", example = "30883")
     private Long userId;
 
-    @Schema(description = "用户类型 - 参见 UserTypeEnum 枚举", example = "2")
+    @Schema(description = "用户类型,参见 UserTypeEnum 枚举", example = "2")
     private Byte userType;
 
     @Schema(description = "接收邮箱地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "76854@qq.com")
@@ -58,7 +58,7 @@ public class MailLogBaseVO {
     @NotNull(message = "邮件参数不能为空")
     private Map<String, Object> templateParams;
 
-    @Schema(description = "发送状态 - 参见 MailSendStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "发送状态,参见 MailSendStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "发送状态不能为空")
     private Byte sendStatus;
 
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/log/MailLogPageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/log/MailLogPageReqVO.java
index 6fe0244ef..5b3ad72ee 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/log/MailLogPageReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/log/MailLogPageReqVO.java
@@ -20,10 +20,10 @@ public class MailLogPageReqVO extends PageParam {
     @Schema(description = "用户编号", example = "30883")
     private Long userId;
 
-    @Schema(description = "用户类型 - 参见 UserTypeEnum 枚举", example = "2")
+    @Schema(description = "用户类型,参见 UserTypeEnum 枚举", example = "2")
     private Integer userType;
 
-    @Schema(description = "接收邮箱地址 模糊匹配", example = "76854@qq.com")
+    @Schema(description = "接收邮箱地址,模糊匹配", example = "76854@qq.com")
     private String toMail;
 
     @Schema(description = "邮箱账号编号", example = "18107")
@@ -32,7 +32,7 @@ public class MailLogPageReqVO extends PageParam {
     @Schema(description = "模板编号", example = "5678")
     private Long templateId;
 
-    @Schema(description = "发送状态 - 参见 MailSendStatusEnum 枚举", example = "1")
+    @Schema(description = "发送状态,参见 MailSendStatusEnum 枚举", example = "1")
     private Integer sendStatus;
 
     @Schema(description = "发送时间")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateBaseVO.java
index 73eeb8ac8..eae1640aa 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateBaseVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateBaseVO.java
@@ -36,7 +36,7 @@ public class MailTemplateBaseVO {
     @NotEmpty(message = "内容不能为空")
     private String content;
 
-    @Schema(description = "状态 - 参见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "状态,参见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "状态不能为空")
     private Integer status;
 
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplatePageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplatePageReqVO.java
index 4044b7244..2a9afd706 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplatePageReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplatePageReqVO.java
@@ -17,13 +17,13 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
 @ToString(callSuper = true)
 public class MailTemplatePageReqVO extends PageParam {
 
-    @Schema(description = "状态 - 参见 CommonStatusEnum 枚举", example = "1")
+    @Schema(description = "状态,参见 CommonStatusEnum 枚举", example = "1")
     private Integer status;
 
-    @Schema(description = "标识 - 模糊匹配", example = "code_1024")
+    @Schema(description = "标识,模糊匹配", example = "code_1024")
     private String code;
 
-    @Schema(description = "名称 - 模糊匹配", example = "芋头")
+    @Schema(description = "名称,模糊匹配", example = "芋头")
     private String name;
 
     @Schema(description = "账号编号", example = "2048")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeBaseVO.java
index 359c3c5b2..efac4df73 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeBaseVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeBaseVO.java
@@ -26,7 +26,7 @@ public class NoticeBaseVO {
     @Schema(description = "公告内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "半生编码")
     private String content;
 
-    @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer status;
 
 }
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticePageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticePageReqVO.java
index 53ad45f56..e39804234 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticePageReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticePageReqVO.java
@@ -10,10 +10,10 @@ import lombok.EqualsAndHashCode;
 @EqualsAndHashCode(callSuper = true)
 public class NoticePageReqVO extends PageParam {
 
-    @Schema(description = "通知公告名称,模糊匹配", example = "芋道")
+    @Schema(description = "通知公告名称,模糊匹配", example = "芋道")
     private String title;
 
-    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
+    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
     private Integer status;
 
 }
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/message/NotifyMessageBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/message/NotifyMessageBaseVO.java
index 8e4b3fd03..95fa77cc5 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/message/NotifyMessageBaseVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/message/NotifyMessageBaseVO.java
@@ -21,7 +21,7 @@ public class NotifyMessageBaseVO {
     @NotNull(message = "用户编号不能为空")
     private Long userId;
 
-    @Schema(description = "用户类型 - 参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "用户类型不能为空")
     private Byte userType;
 
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateBaseVO.java
index 1af2ec128..72b995ad1 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateBaseVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateBaseVO.java
@@ -9,9 +9,9 @@ import javax.validation.constraints.NotEmpty;
 import javax.validation.constraints.NotNull;
 
 /**
-* 站内信模版 Base VO,提供给添加、修改、详细的子 VO 使用
-* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
-*/
+ * 站内信模版 Base VO,提供给添加、修改、详细的子 VO 使用
+ * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
+ */
 @Data
 public class NotifyTemplateBaseVO {
 
@@ -23,7 +23,7 @@ public class NotifyTemplateBaseVO {
     @NotNull(message = "模版编码不能为空")
     private String code;
 
-    @Schema(description = "模版类型 - 对应 system_notify_template_type 字典", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "模版类型,对应 system_notify_template_type 字典", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "模版类型不能为空")
     private Integer type;
 
@@ -35,7 +35,7 @@ public class NotifyTemplateBaseVO {
     @NotEmpty(message = "模版内容不能为空")
     private String content;
 
-    @Schema(description = "状态 - 参见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "状态,参见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "状态不能为空")
     @InEnum(value = CommonStatusEnum.class, message = "状态必须是 {value}")
     private Integer status;
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplatePageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplatePageReqVO.java
index 6c3a36bb1..055729716 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplatePageReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplatePageReqVO.java
@@ -1,11 +1,13 @@
 package cn.iocoder.yudao.module.system.controller.admin.notify.vo.template;
 
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
 
 import java.time.LocalDateTime;
-import cn.iocoder.yudao.framework.common.pojo.PageParam;
-import org.springframework.format.annotation.DateTimeFormat;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
@@ -21,7 +23,7 @@ public class NotifyTemplatePageReqVO extends PageParam {
     @Schema(description = "模版名称", example = "我是名称")
     private String name;
 
-    @Schema(description = "状态 - 参见 CommonStatusEnum 枚举类", example = "1")
+    @Schema(description = "状态,参见 CommonStatusEnum 枚举类", example = "1")
     private Integer status;
 
     @Schema(description = "创建时间")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientBaseVO.java
index cd38f8b17..d9f661d5e 100755
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientBaseVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientBaseVO.java
@@ -38,7 +38,7 @@ public class OAuth2ClientBaseVO {
     @Schema(description = "应用描述", example = "我是一个应用")
     private String description;
 
-    @Schema(description = "状态,参见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "状态,参见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "状态不能为空")
     private Integer status;
 
@@ -55,7 +55,7 @@ public class OAuth2ClientBaseVO {
     private List<@NotEmpty(message = "重定向的 URI 不能为空")
         @URL(message = "重定向的 URI 格式不正确") String> redirectUris;
 
-    @Schema(description = "授权类型,参见 OAuth2GrantTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "password")
+    @Schema(description = "授权类型,参见 OAuth2GrantTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "password")
     @NotNull(message = "授权类型不能为空")
     private List<String> authorizedGrantTypes;
 
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientPageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientPageReqVO.java
index 66fd1f41b..f10f15aa4 100755
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientPageReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientPageReqVO.java
@@ -10,10 +10,10 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam;
 @ToString(callSuper = true)
 public class OAuth2ClientPageReqVO extends PageParam {
 
-    @Schema(description = "应用名,模糊匹配", example = "土豆")
+    @Schema(description = "应用名,模糊匹配", example = "土豆")
     private String name;
 
-    @Schema(description = "状态,参见 CommonStatusEnum 枚举", example = "1")
+    @Schema(description = "状态,参见 CommonStatusEnum 枚举", example = "1")
     private Integer status;
 
 }
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/open/OAuth2OpenCheckTokenRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/open/OAuth2OpenCheckTokenRespVO.java
index fd74f336c..cbee61342 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/open/OAuth2OpenCheckTokenRespVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/open/OAuth2OpenCheckTokenRespVO.java
@@ -17,7 +17,7 @@ public class OAuth2OpenCheckTokenRespVO {
     @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
     @JsonProperty("user_id")
     private Long userId;
-    @Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    @Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
     @JsonProperty("user_type")
     private Integer userType;
     @Schema(description = "租户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@@ -34,7 +34,7 @@ public class OAuth2OpenCheckTokenRespVO {
     @JsonProperty("access_token")
     private String accessToken;
 
-    @Schema(description = "过期时间,时间戳 / 1000,即单位:秒", requiredMode = Schema.RequiredMode.REQUIRED, example = "1593092157")
+    @Schema(description = "过期时间,时间戳 / 1000,即单位:秒", requiredMode = Schema.RequiredMode.REQUIRED, example = "1593092157")
     private Long exp;
 
 }
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/token/OAuth2AccessTokenPageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/token/OAuth2AccessTokenPageReqVO.java
index 4e4a6af7a..0f932ee56 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/token/OAuth2AccessTokenPageReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/token/OAuth2AccessTokenPageReqVO.java
@@ -13,7 +13,7 @@ public class OAuth2AccessTokenPageReqVO extends PageParam {
     @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
     private Long userId;
 
-    @Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    @Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
     private Integer userType;
 
     @Schema(description = "客户端编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/token/OAuth2AccessTokenRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/token/OAuth2AccessTokenRespVO.java
index e0f93d954..362a460ab 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/token/OAuth2AccessTokenRespVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/token/OAuth2AccessTokenRespVO.java
@@ -25,7 +25,7 @@ public class OAuth2AccessTokenRespVO {
     @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
     private Long userId;
 
-    @Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    @Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
     private Integer userType;
 
     @Schema(description = "客户端编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/user/OAuth2UserInfoRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/user/OAuth2UserInfoRespVO.java
index ff19b2b65..69a905d2c 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/user/OAuth2UserInfoRespVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/user/OAuth2UserInfoRespVO.java
@@ -27,7 +27,7 @@ public class OAuth2UserInfoRespVO {
     @Schema(description = "手机号码", example = "15601691300")
     private String mobile;
 
-    @Schema(description = "用户性别,参见 SexEnum 枚举类", example = "1")
+    @Schema(description = "用户性别,参见 SexEnum 枚举类", example = "1")
     private Integer sex;
 
     @Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/user/OAuth2UserUpdateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/user/OAuth2UserUpdateReqVO.java
index b9970741a..bb2ff4bf4 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/user/OAuth2UserUpdateReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/user/OAuth2UserUpdateReqVO.java
@@ -28,7 +28,7 @@ public class OAuth2UserUpdateReqVO {
     @Length(min = 11, max = 11, message = "手机号长度必须 11 位")
     private String mobile;
 
-    @Schema(description = "用户性别,参见 SexEnum 枚举类", example = "1")
+    @Schema(description = "用户性别,参见 SexEnum 枚举类", example = "1")
     private Integer sex;
 
 }
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuBaseVO.java
index a1d2e022e..29e6c36ea 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuBaseVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuBaseVO.java
@@ -23,7 +23,7 @@ public class MenuBaseVO {
     @Size(max = 100)
     private String permission;
 
-    @Schema(description = "类型,参见 MenuTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "类型,参见 MenuTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "菜单类型不能为空")
     private Integer type;
 
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuListReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuListReqVO.java
index ce6cf5dbd..b3b7f2d07 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuListReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuListReqVO.java
@@ -7,10 +7,10 @@ import lombok.Data;
 @Data
 public class MenuListReqVO {
 
-    @Schema(description = "菜单名称,模糊匹配", example = "芋道")
+    @Schema(description = "菜单名称,模糊匹配", example = "芋道")
     private String name;
 
-    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
+    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
     private Integer status;
 
 }
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuRespVO.java
index 5d149feb6..6cd9bd174 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuRespVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuRespVO.java
@@ -18,7 +18,7 @@ public class MenuRespVO extends MenuBaseVO {
     @Schema(description = "菜单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Long id;
 
-    @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer status;
 
     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuSimpleRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuSimpleRespVO.java
index 9e27dc925..19770dd80 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuSimpleRespVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuSimpleRespVO.java
@@ -22,7 +22,7 @@ public class MenuSimpleRespVO {
     @Schema(description = "父菜单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Long parentId;
 
-    @Schema(description = "类型,参见 MenuTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "类型,参见 MenuTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer type;
 
 }
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/permission/PermissionAssignRoleDataScopeReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/permission/PermissionAssignRoleDataScopeReqVO.java
index 1311faf7a..8e457c32e 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/permission/PermissionAssignRoleDataScopeReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/permission/PermissionAssignRoleDataScopeReqVO.java
@@ -15,7 +15,7 @@ public class PermissionAssignRoleDataScopeReqVO {
     @NotNull(message = "角色编号不能为空")
     private Long roleId;
 
-    @Schema(description = "数据范围,参见 DataScopeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "数据范围,参见 DataScopeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "数据范围不能为空")
 //    TODO 这里要多一个枚举校验
     private Integer dataScope;
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleExportReqVO.java
index f13e91f33..40ff75197 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleExportReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleExportReqVO.java
@@ -12,13 +12,13 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
 @Data
 public class RoleExportReqVO {
 
-    @Schema(description = "角色名称,模糊匹配", example = "芋道")
+    @Schema(description = "角色名称,模糊匹配", example = "芋道")
     private String name;
 
-    @Schema(description = "角色标识,模糊匹配", example = "yudao")
+    @Schema(description = "角色标识,模糊匹配", example = "yudao")
     private String code;
 
-    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
+    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
     private Integer status;
 
     @Schema(description = "开始时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RolePageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RolePageReqVO.java
index cc0f0040d..c87127446 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RolePageReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RolePageReqVO.java
@@ -15,13 +15,13 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
 @EqualsAndHashCode(callSuper = true)
 public class RolePageReqVO extends PageParam {
 
-    @Schema(description = "角色名称,模糊匹配", example = "芋道")
+    @Schema(description = "角色名称,模糊匹配", example = "芋道")
     private String name;
 
-    @Schema(description = "角色标识,模糊匹配", example = "yudao")
+    @Schema(description = "角色标识,模糊匹配", example = "yudao")
     private String code;
 
-    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
+    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
     private Integer status;
 
     @Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleRespVO.java
index d6b4dcf44..7eeb1493c 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleRespVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleRespVO.java
@@ -19,16 +19,16 @@ public class RoleRespVO extends RoleBaseVO {
     @Schema(description = "角色编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Long id;
 
-    @Schema(description = "数据范围,参见 DataScopeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "数据范围,参见 DataScopeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer dataScope;
 
     @Schema(description = "数据范围(指定部门数组)", example = "1")
     private Set<Long> dataScopeDeptIds;
 
-    @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer status;
 
-    @Schema(description = "角色类型,参见 RoleTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "角色类型,参见 RoleTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer type;
 
     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordBaseVO.java
index 906c168ac..e940bf55b 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordBaseVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordBaseVO.java
@@ -21,7 +21,7 @@ public class SensitiveWordBaseVO {
     @NotNull(message = "标签不能为空")
     private List<String> tags;
 
-    @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "状态不能为空")
     private Integer status;
 
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordExportReqVO.java
index f5f3c4442..6ea8614ab 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordExportReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordExportReqVO.java
@@ -8,7 +8,7 @@ import java.time.LocalDateTime;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
-@Schema(description = "管理后台 - 敏感词 Excel 导出 Request VO,参数和 SensitiveWordPageReqVO 是一致的")
+@Schema(description = "管理后台 - 敏感词 Excel 导出 Request VO,参数和 SensitiveWordPageReqVO 是一致的")
 @Data
 public class SensitiveWordExportReqVO {
 
@@ -18,7 +18,7 @@ public class SensitiveWordExportReqVO {
     @Schema(description = "标签", example = "短信,评论")
     private String tag;
 
-    @Schema(description = "状态,参见 CommonStatusEnum 枚举类", example = "1")
+    @Schema(description = "状态,参见 CommonStatusEnum 枚举类", example = "1")
     private Integer status;
 
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordPageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordPageReqVO.java
index 173162194..642773a55 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordPageReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordPageReqVO.java
@@ -23,7 +23,7 @@ public class SensitiveWordPageReqVO extends PageParam {
     @Schema(description = "标签", example = "短信,评论")
     private String tag;
 
-    @Schema(description = "状态,参见 CommonStatusEnum 枚举类", example = "1")
+    @Schema(description = "状态,参见 CommonStatusEnum 枚举类", example = "1")
     private Integer status;
 
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelCreateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelCreateReqVO.java
index d1dde92fd..7e052de57 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelCreateReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelCreateReqVO.java
@@ -13,7 +13,7 @@ import javax.validation.constraints.NotNull;
 @ToString(callSuper = true)
 public class SmsChannelCreateReqVO extends SmsChannelBaseVO {
 
-    @Schema(description = "渠道编码,参见 SmsChannelEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "YUN_PIAN")
+    @Schema(description = "渠道编码,参见 SmsChannelEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "YUN_PIAN")
     @NotNull(message = "渠道编码不能为空")
     private String code;
 
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelPageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelPageReqVO.java
index a0c5baaf6..2ec9b2f25 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelPageReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelPageReqVO.java
@@ -20,7 +20,7 @@ public class SmsChannelPageReqVO extends PageParam {
     @Schema(description = "任务状态", example = "1")
     private Integer status;
 
-    @Schema(description = "短信签名,模糊匹配", example = "芋道源码")
+    @Schema(description = "短信签名,模糊匹配", example = "芋道源码")
     private String signature;
 
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelRespVO.java
index 8623c085d..040f5bc24 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelRespVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelRespVO.java
@@ -16,7 +16,7 @@ public class SmsChannelRespVO extends SmsChannelBaseVO {
     @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Long id;
 
-    @Schema(description = "渠道编码,参见 SmsChannelEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "YUN_PIAN")
+    @Schema(description = "渠道编码,参见 SmsChannelEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "YUN_PIAN")
     private String code;
 
     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelSimpleRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelSimpleRespVO.java
index 9d3cffda9..560a39e91 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelSimpleRespVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelSimpleRespVO.java
@@ -17,7 +17,7 @@ public class SmsChannelSimpleRespVO {
     @NotNull(message = "短信签名不能为空")
     private String signature;
 
-    @Schema(description = "渠道编码,参见 SmsChannelEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "YUN_PIAN")
+    @Schema(description = "渠道编码,参见 SmsChannelEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "YUN_PIAN")
     private String code;
 
 }
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogExportReqVO.java
index 739e630eb..a96aeb8ef 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogExportReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogExportReqVO.java
@@ -8,7 +8,7 @@ import java.time.LocalDateTime;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
-@Schema(description = "管理后台 - 短信日志 Excel 导出 Request VO,参数和 SmsLogPageReqVO 是一致的")
+@Schema(description = "管理后台 - 短信日志 Excel 导出 Request VO,参数和 SmsLogPageReqVO 是一致的")
 @Data
 public class SmsLogExportReqVO {
 
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogPageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogPageReqVO.java
index 0da70bd12..fbf9dcfae 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogPageReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogPageReqVO.java
@@ -26,14 +26,14 @@ public class SmsLogPageReqVO extends PageParam {
     @Schema(description = "手机号", example = "15601691300")
     private String mobile;
 
-    @Schema(description = "发送状态,参见 SmsSendStatusEnum 枚举类", example = "1")
+    @Schema(description = "发送状态,参见 SmsSendStatusEnum 枚举类", example = "1")
     private Integer sendStatus;
 
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     @Schema(description = "发送时间")
     private LocalDateTime[] sendTime;
 
-    @Schema(description = "接收状态,参见 SmsReceiveStatusEnum 枚举类", example = "0")
+    @Schema(description = "接收状态,参见 SmsReceiveStatusEnum 枚举类", example = "0")
     private Integer receiveStatus;
 
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateBaseVO.java
index 6ea78bbc6..d5bc304e5 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateBaseVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateBaseVO.java
@@ -11,11 +11,11 @@ import javax.validation.constraints.NotNull;
 @Data
 public class SmsTemplateBaseVO {
 
-    @Schema(description = "短信类型,参见 SmsTemplateTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "短信类型,参见 SmsTemplateTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "短信类型不能为空")
     private Integer type;
 
-    @Schema(description = "开启状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "开启状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "开启状态不能为空")
     private Integer status;
 
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateExportReqVO.java
index 93d157340..973a9a4e8 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateExportReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateExportReqVO.java
@@ -8,7 +8,7 @@ import java.time.LocalDateTime;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
-@Schema(description = "管理后台 - 短信模板 Excel 导出 Request VO,参数和 SmsTemplatePageReqVO 是一致的")
+@Schema(description = "管理后台 - 短信模板 Excel 导出 Request VO,参数和 SmsTemplatePageReqVO 是一致的")
 @Data
 public class SmsTemplateExportReqVO {
 
@@ -18,13 +18,13 @@ public class SmsTemplateExportReqVO {
     @Schema(description = "开启状态", example = "1")
     private Integer status;
 
-    @Schema(description = "模板编码,模糊匹配", example = "test_01")
+    @Schema(description = "模板编码,模糊匹配", example = "test_01")
     private String code;
 
-    @Schema(description = "模板内容,模糊匹配", example = "你好,{name}。你长的太{like}啦!")
+    @Schema(description = "模板内容,模糊匹配", example = "你好,{name}。你长的太{like}啦!")
     private String content;
 
-    @Schema(description = "短信 API 的模板编号,模糊匹配", example = "4383920")
+    @Schema(description = "短信 API 的模板编号,模糊匹配", example = "4383920")
     private String apiTemplateId;
 
     @Schema(description = "短信渠道编号", example = "10")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplatePageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplatePageReqVO.java
index 89ae459f5..acf99e380 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplatePageReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplatePageReqVO.java
@@ -23,13 +23,13 @@ public class SmsTemplatePageReqVO extends PageParam {
     @Schema(description = "开启状态", example = "1")
     private Integer status;
 
-    @Schema(description = "模板编码,模糊匹配", example = "test_01")
+    @Schema(description = "模板编码,模糊匹配", example = "test_01")
     private String code;
 
-    @Schema(description = "模板内容,模糊匹配", example = "你好,{name}。你长的太{like}啦!")
+    @Schema(description = "模板内容,模糊匹配", example = "你好,{name}。你长的太{like}啦!")
     private String content;
 
-    @Schema(description = "短信 API 的模板编号,模糊匹配", example = "4383920")
+    @Schema(description = "短信 API 的模板编号,模糊匹配", example = "4383920")
     private String apiTemplateId;
 
     @Schema(description = "短信渠道编号", example = "10")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/SocialUserBindReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/SocialUserBindReqVO.java
index d91173958..9958d6441 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/SocialUserBindReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/SocialUserBindReqVO.java
@@ -18,7 +18,7 @@ import javax.validation.constraints.NotNull;
 @Builder
 public class SocialUserBindReqVO {
 
-    @Schema(description = "社交平台的类型,参见 UserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
+    @Schema(description = "社交平台的类型,参见 UserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
     @InEnum(SocialTypeEnum.class)
     @NotNull(message = "社交平台的类型不能为空")
     private Integer type;
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/SocialUserUnbindReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/SocialUserUnbindReqVO.java
index 9a1e841fb..10f6244cd 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/SocialUserUnbindReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/SocialUserUnbindReqVO.java
@@ -18,7 +18,7 @@ import javax.validation.constraints.NotNull;
 @Builder
 public class SocialUserUnbindReqVO {
 
-    @Schema(description = "社交平台的类型,参见 UserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
+    @Schema(description = "社交平台的类型,参见 UserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
     @InEnum(SocialTypeEnum.class)
     @NotNull(message = "社交平台的类型不能为空")
     private Integer type;
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageBaseVO.java
index d8f14f6f0..fdf316a9b 100755
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageBaseVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageBaseVO.java
@@ -7,9 +7,9 @@ import javax.validation.constraints.NotNull;
 import java.util.Set;
 
 /**
-* 租户套餐 Base VO,提供给添加、修改、详细的子 VO 使用
-* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
-*/
+ * 租户套餐 Base VO,提供给添加、修改、详细的子 VO 使用
+ * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
+ */
 @Data
 public class TenantPackageBaseVO {
 
@@ -17,7 +17,7 @@ public class TenantPackageBaseVO {
     @NotNull(message = "套餐名不能为空")
     private String name;
 
-    @Schema(description = "状态,参见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "状态,参见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "状态不能为空")
     private Integer status;
 
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantExportReqVO.java
index 706337276..c5c5a0660 100755
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantExportReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantExportReqVO.java
@@ -8,7 +8,7 @@ import java.time.LocalDateTime;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
-@Schema(description = "管理后台 - 租户 Excel 导出 Request VO,参数和 TenantPageReqVO 是一致的")
+@Schema(description = "管理后台 - 租户 Excel 导出 Request VO,参数和 TenantPageReqVO 是一致的")
 @Data
 public class TenantExportReqVO {
 
@@ -24,8 +24,8 @@ public class TenantExportReqVO {
     @Schema(description = "租户状态(0正常 1停用)", example = "1")
     private Integer status;
 
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime[] createTime;
 
 }
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileRespVO.java
index fd1c26eac..6abf1fb65 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileRespVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileRespVO.java
@@ -21,7 +21,7 @@ public class UserProfileRespVO extends UserBaseVO {
     @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Long id;
 
-    @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer status;
 
     @Schema(description = "最后登录 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "192.168.1.1")
@@ -92,7 +92,7 @@ public class UserProfileRespVO extends UserBaseVO {
     @Data
     public static class SocialUser {
 
-        @Schema(description = "社交平台的类型,参见 SocialTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
+        @Schema(description = "社交平台的类型,参见 SocialTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
         private Integer type;
 
         @Schema(description = "社交用户的 openid", requiredMode = Schema.RequiredMode.REQUIRED, example = "IPRmJ0wvBptiPIlGEZiPewGwiEiE")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileUpdateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileUpdateReqVO.java
index 8abc07af6..562c9ae34 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileUpdateReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileUpdateReqVO.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.controller.admin.user.vo.profile;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
+import org.hibernate.validator.constraints.Length;
 
 import javax.validation.constraints.Email;
 import javax.validation.constraints.Size;
@@ -21,6 +22,7 @@ public class UserProfileUpdateReqVO {
     private String email;
 
     @Schema(description = "手机号码", example = "15601691300")
+    @Length(min = 11, max = 11, message = "手机号长度必须 11 位")
     private String mobile;
 
     @Schema(description = "用户性别-参见 SexEnum 枚举类", example = "1")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserBaseVO.java
index ce3af1302..5008cb2d0 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserBaseVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserBaseVO.java
@@ -45,7 +45,7 @@ public class UserBaseVO {
     @Mobile
     private String mobile;
 
-    @Schema(description = "用户性别,参见 SexEnum 枚举类", example = "1")
+    @Schema(description = "用户性别,参见 SexEnum 枚举类", example = "1")
     private Integer sex;
 
     @Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserExportReqVO.java
index 5d9464b79..a3203ed3d 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserExportReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserExportReqVO.java
@@ -10,19 +10,19 @@ import java.time.LocalDateTime;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
-@Schema(description = "管理后台 - 用户导出 Request VO,参数和 UserPageReqVO 是一致的")
+@Schema(description = "管理后台 - 用户导出 Request VO,参数和 UserPageReqVO 是一致的")
 @Data
 @NoArgsConstructor
 @AllArgsConstructor
 public class UserExportReqVO {
 
-    @Schema(description = "用户账号,模糊匹配", example = "yudao")
+    @Schema(description = "用户账号,模糊匹配", example = "yudao")
     private String username;
 
-    @Schema(description = "手机号码,模糊匹配", example = "yudao")
+    @Schema(description = "手机号码,模糊匹配", example = "yudao")
     private String mobile;
 
-    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
+    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
     private Integer status;
 
     @Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserImportRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserImportRespVO.java
index 6843ef5c3..746c5afc0 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserImportRespVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserImportRespVO.java
@@ -18,7 +18,7 @@ public class UserImportRespVO {
     @Schema(description = "更新成功的用户名数组", requiredMode = Schema.RequiredMode.REQUIRED)
     private List<String> updateUsernames;
 
-    @Schema(description = "导入失败的用户集合,key 为用户名,value 为失败原因", requiredMode = Schema.RequiredMode.REQUIRED)
+    @Schema(description = "导入失败的用户集合,key 为用户名,value 为失败原因", requiredMode = Schema.RequiredMode.REQUIRED)
     private Map<String, String> failureUsernames;
 
 }
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserPageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserPageReqVO.java
index 4e6a42541..525cb11c4 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserPageReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserPageReqVO.java
@@ -19,20 +19,20 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
 @EqualsAndHashCode(callSuper = true)
 public class UserPageReqVO extends PageParam {
 
-    @Schema(description = "用户账号,模糊匹配", example = "yudao")
+    @Schema(description = "用户账号,模糊匹配", example = "yudao")
     private String username;
 
-    @Schema(description = "手机号码,模糊匹配", example = "yudao")
+    @Schema(description = "手机号码,模糊匹配", example = "yudao")
     private String mobile;
 
-    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
+    @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
     private Integer status;
 
-    @Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
+    @Schema(description = "创建时间", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]")
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime[] createTime;
 
-    @Schema(description = "部门编号,同时筛选子部门", example = "1024")
+    @Schema(description = "部门编号,同时筛选子部门", example = "1024")
     private Long deptId;
 
 }
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java
index 4859b520d..f07b5679f 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java
@@ -16,7 +16,7 @@ public class UserRespVO extends UserBaseVO {
     @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Long id;
 
-    @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer status;
 
     @Schema(description = "最后登录 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "192.168.1.1")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java
index 12fd35b1c..a35fa8231 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java
@@ -1,6 +1,5 @@
 package cn.iocoder.yudao.module.system.convert.auth;
 
-import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
 import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
@@ -15,6 +14,7 @@ import org.slf4j.LoggerFactory;
 
 import java.util.*;
 
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
 import static cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO.ID_ROOT;
 
@@ -28,8 +28,8 @@ public interface AuthConvert {
     default AuthPermissionInfoRespVO convert(AdminUserDO user, List<RoleDO> roleList, List<MenuDO> menuList) {
         return AuthPermissionInfoRespVO.builder()
             .user(AuthPermissionInfoRespVO.UserVO.builder().id(user.getId()).nickname(user.getNickname()).avatar(user.getAvatar()).build())
-            .roles(CollectionUtils.convertSet(roleList, RoleDO::getCode))
-            .permissions(CollectionUtils.convertSet(menuList, MenuDO::getPermission))
+            .roles(convertSet(roleList, RoleDO::getCode))
+            .permissions(convertSet(menuList, MenuDO::getPermission))
             .build();
     }