liu 10 месяцев назад
Родитель
Сommit
7847cb59d3
47 измененных файлов с 1898 добавлено и 165 удалено
  1. 114 0
      db/update_250824.sql
  2. 23 0
      db/update_250825.sql
  3. 5 0
      src/main/java/com/sqx/common/constant/RedisKey.java
  4. 6 0
      src/main/java/com/sqx/common/utils/RedisUtils.java
  5. 51 9
      src/main/java/com/sqx/modules/lovers/controller/LoversSetController.java
  6. 48 22
      src/main/java/com/sqx/modules/lovers/controller/LoversSetRuleController.java
  7. 39 0
      src/main/java/com/sqx/modules/lovers/controller/app/AppLoversSetController.java
  8. 50 0
      src/main/java/com/sqx/modules/lovers/controller/app/AppLoversSetOrderController.java
  9. 11 0
      src/main/java/com/sqx/modules/lovers/dao/LoversSetDao.java
  10. 96 0
      src/main/java/com/sqx/modules/lovers/dto/LoversSetAddDTO.java
  11. 37 0
      src/main/java/com/sqx/modules/lovers/dto/LoversSetContentDTO.java
  12. 58 0
      src/main/java/com/sqx/modules/lovers/dto/LoversSetContentDetailDTO.java
  13. 42 0
      src/main/java/com/sqx/modules/lovers/dto/LoversSetMenstrualPeriodSettingDTO.java
  14. 79 0
      src/main/java/com/sqx/modules/lovers/dto/LoversSetOrderSubmitDTO.java
  15. 22 0
      src/main/java/com/sqx/modules/lovers/dto/LoversSetQueryDTO.java
  16. 27 0
      src/main/java/com/sqx/modules/lovers/dto/LoversSetRuleDTO.java
  17. 17 0
      src/main/java/com/sqx/modules/lovers/dto/LoversSetRuleQueryDTO.java
  18. 11 8
      src/main/java/com/sqx/modules/lovers/entity/LoversSet.java
  19. 7 3
      src/main/java/com/sqx/modules/lovers/entity/LoversSetContent.java
  20. 6 2
      src/main/java/com/sqx/modules/lovers/entity/LoversSetContentDetail.java
  21. 16 8
      src/main/java/com/sqx/modules/lovers/entity/LoversSetMenstrualPeriodSetting.java
  22. 4 3
      src/main/java/com/sqx/modules/lovers/entity/LoversSetOrderDeliveryInfo.java
  23. 1 1
      src/main/java/com/sqx/modules/lovers/entity/LoversSetOrderDetail.java
  24. 14 4
      src/main/java/com/sqx/modules/lovers/entity/LoversSetOrderInfo.java
  25. 12 4
      src/main/java/com/sqx/modules/lovers/entity/LoversSetRule.java
  26. 12 0
      src/main/java/com/sqx/modules/lovers/service/LoversSetContentDetailService.java
  27. 13 0
      src/main/java/com/sqx/modules/lovers/service/LoversSetContentService.java
  28. 13 0
      src/main/java/com/sqx/modules/lovers/service/LoversSetMenstrualPeriodSettingService.java
  29. 10 0
      src/main/java/com/sqx/modules/lovers/service/LoversSetOrderDetailService.java
  30. 35 0
      src/main/java/com/sqx/modules/lovers/service/LoversSetOrderInfoService.java
  31. 6 5
      src/main/java/com/sqx/modules/lovers/service/LoversSetRuleService.java
  32. 34 2
      src/main/java/com/sqx/modules/lovers/service/LoversSetService.java
  33. 60 0
      src/main/java/com/sqx/modules/lovers/service/impl/LoversSetContentDetailServiceImpl.java
  34. 131 0
      src/main/java/com/sqx/modules/lovers/service/impl/LoversSetContentServiceImpl.java
  35. 11 0
      src/main/java/com/sqx/modules/lovers/service/impl/LoversSetMenstrualPeriodSettingServiceImpl.java
  36. 10 0
      src/main/java/com/sqx/modules/lovers/service/impl/LoversSetOrderDetailServiceImpl.java
  37. 239 0
      src/main/java/com/sqx/modules/lovers/service/impl/LoversSetOrderInfoServiceImpl.java
  38. 47 41
      src/main/java/com/sqx/modules/lovers/service/impl/LoversSetRuleServiceImpl.java
  39. 76 6
      src/main/java/com/sqx/modules/lovers/service/impl/LoversSetServiceImpl.java
  40. 58 0
      src/main/java/com/sqx/modules/lovers/vo/AppLoversSetShortVO.java
  41. 38 0
      src/main/java/com/sqx/modules/lovers/vo/LoversSetContentDetailVO.java
  42. 26 0
      src/main/java/com/sqx/modules/lovers/vo/LoversSetContentVO.java
  43. 22 0
      src/main/java/com/sqx/modules/lovers/vo/LoversSetRuleVO.java
  44. 76 0
      src/main/java/com/sqx/modules/lovers/vo/LoversSetVO.java
  45. 2 1
      src/main/java/com/sqx/modules/pay/enums/PaySceneEnum.java
  46. 11 45
      src/main/java/com/sqx/modules/pay/service/impl/NewPayServiceImpl.java
  47. 172 1
      src/main/resources/mapper/lovers/LoversSetDao.xml

+ 114 - 0
db/update_250824.sql

@@ -0,0 +1,114 @@
+DROP TABLE IF EXISTS lovers_set;
+CREATE TABLE lovers_set(
+                           `id` bigint NOT NULL AUTO_INCREMENT  COMMENT 'id' ,
+                           `del_flag` VARCHAR(1) NOT NULL   COMMENT '删除标识;0未删除、1已删除' ,
+                           `name` VARCHAR(32) NOT NULL   COMMENT '套餐名称' ,
+                           `sub_name` VARCHAR(32)    COMMENT '套餐子名称' ,
+                           `set_tag` VARCHAR(90) NOT NULL   COMMENT '套餐标签;多个标签之间使用,分割' ,
+                           `service_tag` VARCHAR(90) NOT NULL   COMMENT '服务标签;多个标签之间使用,分割' ,
+                           `price` DECIMAL(24,6) NOT NULL   COMMENT '价格' ,
+                           `original_price` DECIMAL(24,6) NOT NULL   COMMENT '原价' ,
+                           `imgs` VARCHAR(900) NOT NULL   COMMENT '图片;多张图片使用,分割,第一张为主图' ,
+                           `set_type` VARCHAR(1) NOT NULL   COMMENT '套餐类型;1月度套餐,2季度套餐,3年度套餐,4自定义' ,
+                           `suit_sex` VARCHAR(1) NOT NULL   COMMENT '适用性别;1男、2女' ,
+                           `rule_id` bigint NOT NULL   COMMENT '规则id' ,
+                           `set_status` VARCHAR(1) NOT NULL   COMMENT '状态;1可用、2不可用' ,
+                           `sub_order_generate_time` INT NOT NULL   COMMENT '子订单生成时机;单位:小时' ,
+                           `start_time` DATETIME NOT NULL   COMMENT '套餐开始时间' ,
+                           `end_time` DATETIME NOT NULL   COMMENT '套餐结束时间' ,
+                           `self_start_time` DATETIME    COMMENT '自定义时间段开始时间;type为4自定义时必填' ,
+                           `self_end_time` DATETIME    COMMENT '自定义时间段结束时间;type为4自定义时必填' ,
+                           PRIMARY KEY (id)
+)  COMMENT = '情侣套餐';
+DROP TABLE IF EXISTS lovers_set_rule;
+CREATE TABLE lovers_set_rule(
+                                `id` bigint NOT NULL AUTO_INCREMENT  COMMENT 'id' ,
+                                `del_flag` VARCHAR(1) NOT NULL   COMMENT '删除标识;0未删除、1已删除' ,
+                                `name` VARCHAR(32) NOT NULL   COMMENT '规则名称' ,
+                                `sort` INT NOT NULL  DEFAULT 0 COMMENT '排序' ,
+                                `content` VARCHAR(900) NOT NULL   COMMENT '规则内容' ,
+                                PRIMARY KEY (id)
+)  COMMENT = '情侣套餐规则';
+DROP TABLE IF EXISTS lovers_set_content;
+CREATE TABLE lovers_set_content(
+                                   `id` bigint NOT NULL AUTO_INCREMENT  COMMENT 'id' ,
+                                   `del_flag` VARCHAR(1) NOT NULL   COMMENT '删除标识;0未删除、1已删除' ,
+                                   `lovers_set_id` VARCHAR(32) NOT NULL   COMMENT '套餐id' ,
+                                   `sort` INT NOT NULL  DEFAULT 0 COMMENT '排序' ,
+                                   `content_name` VARCHAR(32) NOT NULL   COMMENT '内容名称' ,
+                                   PRIMARY KEY (id)
+)  COMMENT = '情侣套餐内容';
+DROP TABLE IF EXISTS lovers_set_content_detail;
+CREATE TABLE lovers_set_content_detail(
+                                          `id` bigint NOT NULL AUTO_INCREMENT  COMMENT 'id' ,
+                                          `del_flag` VARCHAR(1) NOT NULL   COMMENT '删除标识;0未删除、1已删除' ,
+                                          `lovers_set_content_id` bigint NOT NULL   COMMENT '情侣套餐内容id' ,
+                                          `goods_id` bigint NOT NULL   COMMENT '商品id' ,
+                                          `goods_name` VARCHAR(32) NOT NULL   COMMENT '商品名称' ,
+                                          `shop_id` bigint NOT NULL   COMMENT '店铺id' ,
+                                          `shop_name` VARCHAR(32) NOT NULL   COMMENT '店铺名称' ,
+                                          `num` INT NOT NULL   COMMENT '数量' ,
+                                          `price` DECIMAL(24,6) NOT NULL   COMMENT '价格' ,
+                                          `original_price` DECIMAL(24,6) NOT NULL   COMMENT '原价' ,
+                                          PRIMARY KEY (id)
+)  COMMENT = '情侣套餐内容详情';
+DROP TABLE IF EXISTS lovers_set_order_detail;
+CREATE TABLE lovers_set_order_detail(
+                                        `id` bigint NOT NULL AUTO_INCREMENT  COMMENT 'id' ,
+                                        `lovers_set_order_info_id` bigint NOT NULL   COMMENT '情侣套餐订单id' ,
+                                        `goods_id` bigint NOT NULL   COMMENT '商品id' ,
+                                        `goods_name` VARCHAR(32) NOT NULL   COMMENT '商品名称' ,
+                                        `shop_id` bigint NOT NULL   COMMENT '店铺id' ,
+                                        `shop_name` VARCHAR(32) NOT NULL   COMMENT '店铺名称' ,
+                                        `num` INT NOT NULL   COMMENT '数量' ,
+                                        `price` DECIMAL(24,6) NOT NULL   COMMENT '价格' ,
+                                        `original_price` DECIMAL(24,6) NOT NULL   COMMENT '原价' ,
+                                        PRIMARY KEY (id)
+)  COMMENT = '情侣套餐订单详情';
+DROP TABLE IF EXISTS lovers_set_menstrual_period_setting;
+CREATE TABLE lovers_set_menstrual_period_setting(
+                                                    `id` bigint NOT NULL AUTO_INCREMENT  COMMENT 'id' ,
+                                                    `del_flag` VARCHAR(1) NOT NULL   COMMENT '删除标识;0未删除、1已删除' ,
+                                                    `user_id` bigint NOT NULL   COMMENT '用户id' ,
+                                                    `duration_days` INT NOT NULL   COMMENT '持续天数' ,
+                                                    `interval_days` INT NOT NULL   COMMENT '间隔天数' ,
+                                                    `last_start_date` DATE NOT NULL   COMMENT '上一次月经开始时间' ,
+                                                    `last_end_date` DATE NOT NULL   COMMENT '上一次月经结束时间' ,
+                                                    `next_start_date_of_expect` DATE NOT NULL   COMMENT '预计下一次月经开始时间' ,
+                                                    `next_end_date_of_expect` DATE NOT NULL   COMMENT '预计下一次月经结束时间' ,
+                                                    `create_date` DATE NOT NULL   COMMENT '创建时间' ,
+                                                    PRIMARY KEY (id)
+)  COMMENT = '情侣套餐月经期设置';
+DROP TABLE IF EXISTS lovers_set_order_info;
+CREATE TABLE lovers_set_order_info(
+                                      `id` bigint NOT NULL AUTO_INCREMENT  COMMENT 'id' ,
+                                      `del_flag` VARCHAR(1) NOT NULL   COMMENT '删除标识;0未删除、1已删除' ,
+                                      `order_number` VARCHAR(32) NOT NULL   COMMENT '订单编号' ,
+                                      `user_id` bigint NOT NULL   COMMENT '用户id' ,
+                                      `lovers_set_id` bigint NOT NULL   COMMENT '套餐id' ,
+                                      `lovers_set_name` VARCHAR(32) NOT NULL   COMMENT '套餐名称' ,
+                                      `lovers_set_master_img` VARCHAR(900) NOT NULL   COMMENT '套餐主图' ,
+                                      `lovers_set_amount` DECIMAL(24,6) NOT NULL   COMMENT '套餐金额' ,
+                                      `pay_amount` DECIMAL(24,6) NOT NULL   COMMENT '实付金额' ,
+                                      `refund_amount` DECIMAL(24,6) NOT NULL  DEFAULT 0.0 COMMENT '退款金额' ,
+                                      `receiver_name` VARCHAR(32) NOT NULL   COMMENT '收货人姓名' ,
+                                      `receiver_phone` VARCHAR(32) NOT NULL   COMMENT '收货人电话' ,
+                                      `receive_start_date` DATE NOT NULL   COMMENT '接货开始时间' ,
+                                      `receive_end_date` DATE NOT NULL   COMMENT '接货结束时间' ,
+                                      `expect_receive_time` VARCHAR(32) NOT NULL   COMMENT '期待接货时间;HH:mm:ss' ,
+                                      `active_status` VARCHAR(1) NOT NULL   COMMENT '订单激活状态;0待支付、1待使用、2使用中、3已使用' ,
+                                      `pay_status` VARCHAR(1) NOT NULL   COMMENT '订单支付状态;0待支付、1已支付' ,
+                                      `refund_status` VARCHAR(1) NOT NULL   COMMENT '订单退款状态;0未退款、1部分退款、2整单退款' ,
+                                      PRIMARY KEY (id)
+)  COMMENT = '情侣套餐订单信息';
+DROP TABLE IF EXISTS lovers_set_order_delivery_info;
+CREATE TABLE lovers_set_order_delivery_info(
+                                               `id` bigint NOT NULL AUTO_INCREMENT  COMMENT 'id' ,
+                                               `lovers_set_order_id` bigint NOT NULL   COMMENT '情侣套餐订单id' ,
+                                               `lovers_set_order_detail_id` bigint NOT NULL   COMMENT '情侣套餐订单详情id' ,
+                                               `delivery_time_of_expect` DATETIME NOT NULL   COMMENT '预计配送时间' ,
+                                               `delivery_order_id` bigint    COMMENT '配送单id(跑腿订单id)' ,
+                                               `delivery_status` VARCHAR(1) NOT NULL   COMMENT '状态;1等待生成配送单、2已生成配送单、3已取消' ,
+                                               PRIMARY KEY (id)
+)  COMMENT = '情侣套餐订单配送信息';
+

+ 23 - 0
db/update_250825.sql

@@ -0,0 +1,23 @@
+/* --------------- 修改表 --------------- */
+-- 修改表:lovers_set_rule[情侣套餐规则]
+-- 添加字段:
+ALTER TABLE lovers_set_rule
+    ADD COLUMN `create_time` DATETIME NOT NULL COMMENT '创建时间;' AFTER content,
+ADD COLUMN `update_time` DATETIME NOT NULL COMMENT '更新时间;' AFTER create_time;
+/* --------------- 修改表 --------------- */
+-- 修改表:lovers_set_content[情侣套餐内容]
+-- 修改字段:
+ALTER TABLE lovers_set_content  MODIFY COLUMN `lovers_set_id` bigint NOT NULL COMMENT '套餐id';
+/* --------------- 修改表 --------------- */
+-- 修改表:lovers_set_menstrual_period_setting[情侣套餐月经期设置]
+-- 修改字段:
+ALTER TABLE lovers_set_menstrual_period_setting  CHANGE COLUMN `create_date` `create_time` DATETIME NOT NULL COMMENT '创建时间';
+-- 添加字段:
+ALTER TABLE lovers_set_menstrual_period_setting
+    ADD COLUMN `update_time` DATETIME NOT NULL COMMENT '更新时间;' AFTER create_time;
+/* --------------- 修改表 --------------- */
+-- 修改表:lovers_set_order_info[情侣套餐订单信息]
+-- 添加字段:
+ALTER TABLE lovers_set_order_info
+    ADD COLUMN `create_time` DATETIME NOT NULL COMMENT '创建时间;' AFTER refund_status,
+ADD COLUMN `update_time` VARCHAR(32) NOT NULL COMMENT '更新时间;' AFTER create_time;

+ 5 - 0
src/main/java/com/sqx/common/constant/RedisKey.java

@@ -102,4 +102,9 @@ public interface RedisKey {
      * 平台账单锁
      */
     String PLATFORM_BILL_LOCK = "wm:lock:platform-bill";
+
+    /**
+     * 情侣订单提交token
+     */
+    String LOVERS_SET_ORDER_SUBMIT_TOKEN = "wm:data:lovers-set-order:submit:token:%s";
 }

+ 6 - 0
src/main/java/com/sqx/common/utils/RedisUtils.java

@@ -2,9 +2,11 @@ package com.sqx.common.utils;
 
 import org.springframework.data.redis.core.HashOperations;
 import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.script.DefaultRedisScript;
 import org.springframework.stereotype.Component;
 
 import javax.annotation.Resource;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Date;
 import java.util.Map;
@@ -155,4 +157,8 @@ public class RedisUtils {
     public Object rightPop(String key) {
         return redisTemplate.opsForList().rightPop(key);
     }
+
+    public Long execute(String key, String script, Object... args) {
+        return redisTemplate.execute(new DefaultRedisScript<>(script, Long.class), Arrays.asList(key), args);
+    }
 }

+ 51 - 9
src/main/java/com/sqx/modules/lovers/controller/LoversSetController.java

@@ -1,27 +1,69 @@
 package com.sqx.modules.lovers.controller;
 
+import com.sqx.common.utils.PageUtils;
 import com.sqx.common.utils.Result;
-import com.sqx.modules.lovers.entity.LoversSet;
+import com.sqx.modules.lovers.dto.LoversSetAddDTO;
+import com.sqx.modules.lovers.dto.LoversSetQueryDTO;
 import com.sqx.modules.lovers.service.LoversSetService;
 import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.validation.Valid;
+import javax.validation.constraints.Pattern;
+import java.util.List;
 
 @Slf4j
 @Api(tags = {"管理端-情侣套餐"})
 @RestController
-@RequestMapping("/admin/loverSet")
+@RequestMapping("lover-set")
+@RequiredArgsConstructor
 public class LoversSetController {
 
-    @Autowired
-    LoversSetService loversSetService;
+    private final LoversSetService loversSetService;
+
+    @ApiOperation("套餐分页查询")
+    @GetMapping("page")
+    public Result page(@Valid LoversSetQueryDTO queryDTO){
+        PageUtils pages = loversSetService.pages(queryDTO);
+        return Result.success().put("data", pages);
+    }
 
-    @PostMapping("/save")
-    public Result saveLoverSet(@RequestBody LoversSet loversSet){
-        return loversSetService.saveLoverSet(loversSet);
+    @ApiOperation("新增")
+    @PostMapping
+    public Result add(@RequestBody @Valid LoversSetAddDTO loversSetDTO){
+        loversSetService.add(loversSetDTO);
+        return Result.success();
     }
 
+    @ApiOperation("修改")
+    @PutMapping
+    public Result update(@RequestBody @Valid LoversSetAddDTO loversSetDTO){
+        loversSetService.update(loversSetDTO);
+        return Result.success();
+    }
 
+    @ApiOperation("修改套餐状态")
+    @PutMapping("update-status/{id}/status")
+    public Result updateStatus(@PathVariable Long id,
+                               @PathVariable @Pattern(regexp = "^[1-2]$", message = "状态格式只能为1-2") String status){
+        loversSetService.updateStatus(id, status);
+        return Result.success();
+    }
 
+    @ApiOperation("删除")
+    @DeleteMapping
+    public Result delete(@RequestBody List<Long> ids){
+        loversSetService.deleteByIds(ids);
+        return Result.success();
+    }
 }

+ 48 - 22
src/main/java/com/sqx/modules/lovers/controller/LoversSetRuleController.java

@@ -1,42 +1,68 @@
 package com.sqx.modules.lovers.controller;
 
+import cn.hutool.core.util.ObjectUtil;
+import com.sqx.common.exception.SqxException;
+import com.sqx.common.utils.PageUtils;
 import com.sqx.common.utils.Result;
-import com.sqx.modules.lovers.entity.LoversSet;
-import com.sqx.modules.lovers.entity.LoversSetRule;
+import com.sqx.modules.lovers.dto.LoversSetRuleDTO;
+import com.sqx.modules.lovers.dto.LoversSetRuleQueryDTO;
 import com.sqx.modules.lovers.service.LoversSetRuleService;
 import io.swagger.annotations.Api;
-import lombok.extern.slf4j.Slf4j;
-import org.checkerframework.checker.units.qual.A;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
 
+import javax.validation.Valid;
 
-@Slf4j
+/**
+ * 情侣套餐-规则
+ *
+ * @author codingliang
+ * @date 2025-08-22
+ */
 @Api(tags = {"管理端-情侣套餐规则"})
 @RestController
-@RequestMapping("/admin/loverSetRule")
+@RequestMapping("lovers-set-rule")
+@RequiredArgsConstructor
 public class LoversSetRuleController {
 
-    @Autowired
-    LoversSetRuleService loversSetRuleService;
+    private final LoversSetRuleService loversSetRuleService;
 
-    @PostMapping("/saveLoverSetRule")
-    public Result saveLoverSetRule(@RequestBody LoversSetRule loversSetRule){
-        return loversSetRuleService.saveLoverSetRule(loversSetRule);
+    @GetMapping("page")
+    @ApiOperation("情侣套餐规则分页")
+    public Result page(LoversSetRuleQueryDTO queryDTO) {
+        PageUtils page = loversSetRuleService.page(queryDTO);
+        return Result.success().put("data", page);
     }
 
-    @GetMapping("/list")
-    public Result pageLoverSetRule(Integer page, Integer limit, String name){
-        return loversSetRuleService.pageLoverSetRule(page,limit,name);
+    @PostMapping
+    @ApiOperation("新增情侣套餐规则")
+    public Result add(@Valid LoversSetRuleDTO loversSetRule) {
+        loversSetRuleService.add(loversSetRule);
+        return Result.success();
     }
 
-    @PostMapping("/update")
-    public Result updateLoverSetRule(@RequestBody LoversSetRule loversSetRule){
-        return loversSetRuleService.updateLoverSetRule(loversSetRule);
+    @PutMapping
+    @ApiOperation("修改情侣套餐规则")
+    public Result update(@Valid LoversSetRuleDTO loversSetRule) {
+        if (ObjectUtil.isNull(loversSetRule.getId())) {
+            throw new SqxException("规则ID不能为空");
+        }
+
+        loversSetRuleService.update(loversSetRule);
+        return Result.success();
     }
 
-    @GetMapping("/delete")
-    public Result deleteLoverSetRule(Integer id){
-        return loversSetRuleService.deleteLoverSetRule(id);
+    @DeleteMapping("{id}")
+    @ApiOperation("删除情侣套餐规则")
+    public Result delete(@PathVariable String id) {
+        loversSetRuleService.removeById(id);
+        return Result.success();
     }
 }

+ 39 - 0
src/main/java/com/sqx/modules/lovers/controller/app/AppLoversSetController.java

@@ -0,0 +1,39 @@
+package com.sqx.modules.lovers.controller.app;
+
+import com.sqx.common.utils.PageUtils;
+import com.sqx.common.utils.Result;
+import com.sqx.modules.lovers.dto.LoversSetQueryDTO;
+import com.sqx.modules.lovers.service.LoversSetService;
+import com.sqx.modules.lovers.vo.LoversSetVO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.validation.Valid;
+
+@Api(tags = {"用户端-情侣套餐"})
+@RestController
+@RequestMapping("app/lover-set")
+@RequiredArgsConstructor
+public class AppLoversSetController {
+
+    private final LoversSetService loversSetService;
+
+    @ApiOperation("套餐列表")
+    @GetMapping("page")
+    public Result page(@Valid LoversSetQueryDTO queryDTO){
+        PageUtils pages = loversSetService.listForApp(queryDTO);
+        return Result.success().put("data", pages);
+    }
+
+    @ApiOperation(value = "套餐列表", notes = "根据套餐id查询详情")
+    @GetMapping("{id}")
+    public Result detail(@PathVariable Long id){
+        LoversSetVO vo = loversSetService.getDetailById(id);
+        return Result.success().put("data", vo);
+    }
+}

+ 50 - 0
src/main/java/com/sqx/modules/lovers/controller/app/AppLoversSetOrderController.java

@@ -0,0 +1,50 @@
+package com.sqx.modules.lovers.controller.app;
+
+import com.sqx.common.utils.Result;
+import com.sqx.modules.app.annotation.Login;
+import com.sqx.modules.lovers.dto.LoversSetOrderSubmitDTO;
+import com.sqx.modules.lovers.service.LoversSetOrderInfoService;
+import com.sqx.modules.pay.vo.WechatTransactionsParamVO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestAttribute;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.validation.Valid;
+
+@Api(tags = {"移动端-情侣套餐订单"})
+@RestController
+@RequestMapping("app/lovers-set-order")
+@RequiredArgsConstructor
+public class AppLoversSetOrderController {
+
+    private final LoversSetOrderInfoService loversSetOrderInfoService;
+
+    @Login
+    @ApiOperation("创建订单")
+    @GetMapping
+    public Result createOrder(@RequestAttribute Long userId, @Valid LoversSetOrderSubmitDTO submitDTO){
+        Long orderId = loversSetOrderInfoService.createOrder(userId, submitDTO);
+        return Result.success().put("data", orderId);
+    }
+
+    @Login
+    @ApiOperation("获取支付参数")
+    @GetMapping("pay-params/{orderId}")
+    public Result getPayParams(@RequestAttribute Long userId, @PathVariable Long orderId){
+        WechatTransactionsParamVO transactionsParamVO = loversSetOrderInfoService.getPayParams(userId, orderId);
+        return Result.success().put("data", transactionsParamVO);
+    }
+
+    @Login
+    @ApiOperation("获取提交订单token")
+    @GetMapping("submit-token")
+    public Result getSubmitToken(@RequestAttribute Long userId){
+        String token = loversSetOrderInfoService.getSubmitToken(userId);
+        return Result.success().put("data", token);
+    }
+}

+ 11 - 0
src/main/java/com/sqx/modules/lovers/dao/LoversSetDao.java

@@ -1,9 +1,20 @@
 package com.sqx.modules.lovers.dao;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.sqx.modules.lovers.dto.LoversSetQueryDTO;
 import com.sqx.modules.lovers.entity.LoversSet;
+import com.sqx.modules.lovers.vo.AppLoversSetShortVO;
+import com.sqx.modules.lovers.vo.LoversSetVO;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 
 @Mapper
 public interface LoversSetDao extends BaseMapper<LoversSet> {
+    IPage<LoversSetVO> pages(@Param("pages") Page<LoversSetVO> pages, @Param("queryDTO") LoversSetQueryDTO queryDTO);
+
+    IPage<AppLoversSetShortVO> listForApp(@Param("pages") Page<AppLoversSetShortVO> pages, @Param("queryDTO") LoversSetQueryDTO queryDTO);
+
+    LoversSetVO getDetailById(Long id);
 }

+ 96 - 0
src/main/java/com/sqx/modules/lovers/dto/LoversSetAddDTO.java

@@ -0,0 +1,96 @@
+package com.sqx.modules.lovers.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import javax.validation.constraints.Size;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * 情侣套餐新增DTO
+ * @author codingliang
+ * @date 2025-08-24
+ */
+@Data
+public class LoversSetAddDTO {
+
+    @ApiModelProperty("主键id")
+    private Long id;
+
+    @ApiModelProperty("套餐名称")
+    @NotBlank(message = "套餐名称不能为空")
+    private String name;
+
+    @ApiModelProperty("套餐子名称")
+    @NotBlank(message = "套餐子名称不能为空")
+    private String subName;
+
+    @ApiModelProperty("套餐标签;多个标签之间使用,分割")
+    private String setTag;
+
+    @ApiModelProperty("服务标签;多个标签之间使用,分割")
+    private String serviceTag;
+
+    @ApiModelProperty("价格")
+    @NotNull(message = "价格不能为空")
+    @Min(value = 0, message = "价格不能小于0")
+    private BigDecimal price;
+
+    @ApiModelProperty("原价")
+    @NotNull(message = "原价不能为空")
+    @Min(value = 0, message = "原价不能小于0")
+    private BigDecimal originalPrice;
+
+    @ApiModelProperty("图片;多张图片使用,分割,第一张为主图")
+    @NotBlank(message = "图片不能为空")
+    private String imgs;
+
+    @ApiModelProperty("套餐类型;1月度套餐,2季度套餐,3年度套餐,4自定义")
+    @NotBlank(message = "套餐类型不能为空")
+    @Pattern(regexp = "^[1-4]$", message = "套餐类型格式只能为1-4")
+    private String setType;
+
+    @ApiModelProperty("适用性别;1男、2女")
+    @NotBlank(message = "适用性别不能为空")
+    @Pattern(regexp = "^[1-2]$", message = "适用性别格式只能为1-2")
+    private String suitSex;
+
+    @ApiModelProperty("规则id")
+    @NotNull(message = "规则id不能为空")
+    private Long ruleId;
+
+    @ApiModelProperty("状态;1可用、2不可用")
+    @NotBlank(message = "状态不能为空")
+    @Pattern(regexp = "^[1-2]$", message = "状态格式只能为1-2")
+    private String setStatus;
+
+    @ApiModelProperty("子订单生成时机;单位:小时")
+    @NotNull(message = "子订单生成时机不能为空")
+    @Min(value = 0, message = "子订单生成时机不能小于0")
+    private Integer subOrderGenerateTime;
+
+    @ApiModelProperty("套餐开始时间")
+    @NotNull(message = "套餐开始时间不能为空")
+    private LocalDateTime startTime;
+
+    @ApiModelProperty("套餐结束时间")
+    @NotNull(message = "套餐结束时间不能为空")
+    private LocalDateTime endTime;
+
+    @ApiModelProperty("自定义时间段开始时间;type为4自定义时必填")
+    private LocalDateTime selfStartTime;
+
+    @ApiModelProperty("自定义时间段结束时间;type为4自定义时必填")
+    private LocalDateTime selfEndTime;
+
+    @ApiModelProperty("套餐详情列表")
+    @NotNull(message = "套餐详情列表不能为空")
+    @Size(min = 1, message = "套餐详情列表不能为空")
+    private List<LoversSetContentDTO> loversSetContentDTOS;
+}

+ 37 - 0
src/main/java/com/sqx/modules/lovers/dto/LoversSetContentDTO.java

@@ -0,0 +1,37 @@
+package com.sqx.modules.lovers.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.util.List;
+
+/**
+ * 情侣套餐内容
+ * @author codingliang
+ * @date 2025-08-24
+ */
+@Data
+public class LoversSetContentDTO {
+
+    @ApiModelProperty("主键id,修改时不能为空")
+    private Long id;
+
+    @ApiModelProperty("套餐id,修改时不能为空")
+    private Long loversSetId;
+
+    @ApiModelProperty("排序")
+    @NotNull(message = "排序不能为空")
+    private Integer sort;
+
+    @ApiModelProperty("内容名称")
+    @NotBlank(message = "内容名称不能为空")
+    private String contentName;
+
+    @ApiModelProperty("内容详情内容列表")
+    @NotNull(message = "内容详情内容列表不能为空")
+    @Size(min = 1, message = "内容详情内容列表不能为空")
+    private List<LoversSetContentDetailDTO> loversSetContentDetailDTOS;
+}

+ 58 - 0
src/main/java/com/sqx/modules/lovers/dto/LoversSetContentDetailDTO.java

@@ -0,0 +1,58 @@
+package com.sqx.modules.lovers.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 情侣套餐内容详情
+ */
+@Data
+@ApiModel("lovers_set_content_detail")
+public class LoversSetContentDetailDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty("主键id,修改时不能为空")
+    private Long id;
+
+    @ApiModelProperty("情侣套餐内容id,修改时不能为空")
+    private Long loversSetContentId;
+
+    @ApiModelProperty("商品id")
+    @NotNull(message = "商品id不能为空")
+    private Long goodsId;
+
+    @ApiModelProperty("商品名称")
+    @NotBlank(message = "商品名称不能为空")
+    private String goodsName;
+
+    @ApiModelProperty("店铺id")
+    @NotNull(message = "店铺id不能为空")
+    private Long shopId;
+
+    @ApiModelProperty("店铺名称")
+    @NotBlank(message = "店铺名称不能为空")
+    private String shopName;
+
+    @ApiModelProperty("数量")
+    @NotNull(message = "数量不能为空")
+    @Min(value = 1, message = "数量不能小于1")
+    private Integer num;
+
+    @ApiModelProperty("价格")
+    @NotNull(message = "价格不能为空")
+    @Min(value = 0, message = "价格不能小于0")
+    private BigDecimal price;
+
+    @ApiModelProperty("原价")
+    @NotNull(message = "原价不能为空")
+    @Min(value = 0, message = "原价不能小于0")
+    private BigDecimal originalPrice;
+
+}

+ 42 - 0
src/main/java/com/sqx/modules/lovers/dto/LoversSetMenstrualPeriodSettingDTO.java

@@ -0,0 +1,42 @@
+package com.sqx.modules.lovers.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.Date;
+
+@Data
+public class LoversSetMenstrualPeriodSettingDTO implements Serializable {
+
+    @ApiModelProperty("主键id")
+    private Long id;
+
+    @ApiModelProperty("用户id")
+    private Long userId;
+
+    @ApiModelProperty("持续天数")
+    private Integer durationDays;
+
+    @ApiModelProperty("间隔天数")
+    private Integer intervalDays;
+
+    @ApiModelProperty("上一次月经开始时间")
+    private Date lastStartDate;
+
+    @ApiModelProperty("上一次月经结束时间")
+    private Date lastEndDate;
+
+    @ApiModelProperty("预计下一次月经开始时间")
+    private Date nextStartDateOfExpect;
+
+    @ApiModelProperty("预计下一次月经结束时间")
+    private Date nextEndDateOfExpect;
+
+    @ApiModelProperty("创建时间")
+    private LocalDateTime createTime;
+
+    @ApiModelProperty("更新时间")
+    private LocalDateTime updateTime;
+}

+ 79 - 0
src/main/java/com/sqx/modules/lovers/dto/LoversSetOrderSubmitDTO.java

@@ -0,0 +1,79 @@
+package com.sqx.modules.lovers.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 情侣套餐订单提交DTO
+ * @author codingliang
+ * @date 2025-08-25
+ */
+@Data
+public class LoversSetOrderSubmitDTO {
+
+    @ApiModelProperty("情侣套餐id")
+    @NotNull(message = "情侣套餐id不能为空")
+    private Long loversSetId;
+
+    @ApiModelProperty("套餐金额,前端显示金额,用于和后台比价")
+    @NotNull(message = "套餐金额不能为空")
+    private BigDecimal payAmount;
+
+    @ApiModelProperty("防重令牌")
+    @NotBlank(message = "防重令牌不能为空")
+    private String submitToken;
+
+    @ApiModelProperty("持续天数")
+    @NotNull(message = "持续天数不能为空")
+    @Min(value = 3, message = "持续天数不能小于3")
+    private Integer durationDays;
+
+    @ApiModelProperty("间隔天数")
+    @NotNull(message = "间隔天数不能为空")
+    @Min(value = 1, message = "间隔天数不能小于1")
+    private Integer intervalDays;
+
+    @ApiModelProperty("上一次月经开始时间")
+    @NotNull(message = "上一次月经开始时间不能为空")
+    private Date lastStartDate;
+
+    @ApiModelProperty("上一次月经结束时间")
+    @NotNull(message = "上一次月经结束时间不能为空")
+    private Date lastEndDate;
+
+    @ApiModelProperty("预计下一次月经开始时间")
+    @NotNull(message = "预计下一次月经开始时间不能为空")
+    private Date nextStartDateOfExpect;
+
+    @ApiModelProperty("预计下一次月经结束时间")
+    @NotNull(message = "预计下一次月经结束时间不能为空")
+    private Date nextEndDateOfExpect;
+
+    @ApiModelProperty("收货人姓名")
+    @NotBlank(message = "收货人姓名不能为空")
+    private String receiverName;
+
+    @ApiModelProperty("收货人电话")
+    @NotBlank(message = "收货人电话不能为空")
+    private String receiverPhone;
+
+    @ApiModelProperty("接货开始时间")
+    @NotBlank(message = "接货开始时间不能为空")
+    private Date receiveStartDate;
+
+    @ApiModelProperty("接货结束时间")
+    @NotBlank(message = "接货结束时间不能为空")
+    private Date receiveEndDate;
+
+    @ApiModelProperty("期待接货时间;HH:mm:ss")
+    @NotBlank(message = "期待接货时间不能为空")
+    @Pattern(regexp = "^([01]\\d|2[0-3]):([0-5]\\d):([0-5]\\d)$", message = "期待接货时间格式错误")
+    private String expectReceiveTime;
+}

+ 22 - 0
src/main/java/com/sqx/modules/lovers/dto/LoversSetQueryDTO.java

@@ -0,0 +1,22 @@
+package com.sqx.modules.lovers.dto;
+
+import com.sqx.common.query.PageQuery;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @author codingliang
+ * @date 2025-08-25
+ */
+@Data
+public class LoversSetQueryDTO extends PageQuery {
+
+    @ApiModelProperty("套餐名称")
+    private String name;
+
+    @ApiModelProperty("套餐类型;1月度套餐,2季度套餐,3年度套餐,4自定义")
+    private String setType;
+
+    @ApiModelProperty("适用性别;1男、2女")
+    private String suitSex;
+}

+ 27 - 0
src/main/java/com/sqx/modules/lovers/dto/LoversSetRuleDTO.java

@@ -0,0 +1,27 @@
+package com.sqx.modules.lovers.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+
+@Data
+public class LoversSetRuleDTO implements Serializable {
+
+    @ApiModelProperty("id")
+    private Long id;
+
+    @ApiModelProperty("规则名称")
+    @NotBlank(message = "规则名称不能为空")
+    private String name;
+
+    @ApiModelProperty("排序")
+    @NotNull(message = "排序不能为空")
+    private Integer sort;
+
+    @ApiModelProperty("规则内容")
+    @NotBlank(message = "规则内容不能为空")
+    private String content;
+}

+ 17 - 0
src/main/java/com/sqx/modules/lovers/dto/LoversSetRuleQueryDTO.java

@@ -0,0 +1,17 @@
+package com.sqx.modules.lovers.dto;
+
+import com.sqx.common.query.PageQuery;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @author codingliang
+ * @date 2025-08-22
+ */
+@Data
+public class LoversSetRuleQueryDTO extends PageQuery {
+
+    @ApiModelProperty("规则名称")
+    private String name;
+
+}

+ 11 - 8
src/main/java/com/sqx/modules/lovers/entity/LoversSet.java

@@ -1,12 +1,17 @@
 package com.sqx.modules.lovers.entity;
 
-import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.io.Serializable;
 import java.math.BigDecimal;
+import java.time.LocalDateTime;
 
 @Data
 @ApiModel("lovers_set")
@@ -18,8 +23,8 @@ public class LoversSet implements Serializable {
     private Long id;
 
     @ApiModelProperty("删除标识;0未删除、1已删除")
+    @TableLogic(value = "0", delval = "1")
     @TableField(fill = FieldFill.INSERT)
-    @TableLogic(value="0",delval="1")
     private String delFlag;
 
     @ApiModelProperty("套餐名称")
@@ -59,16 +64,14 @@ public class LoversSet implements Serializable {
     private Integer subOrderGenerateTime;
 
     @ApiModelProperty("套餐开始时间")
-    private String startTime;
+    private LocalDateTime startTime;
 
     @ApiModelProperty("套餐结束时间")
-    private String endTime;
+    private LocalDateTime endTime;
 
     @ApiModelProperty("自定义时间段开始时间;type为4自定义时必填")
-    private String selfStartTime;
+    private LocalDateTime selfStartTime;
 
     @ApiModelProperty("自定义时间段结束时间;type为4自定义时必填")
-    private String selfEndTime;
-
-
+    private LocalDateTime selfEndTime;
 }

+ 7 - 3
src/main/java/com/sqx/modules/lovers/entity/LoversSetContent.java

@@ -1,6 +1,10 @@
 package com.sqx.modules.lovers.entity;
 
-import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
@@ -18,11 +22,11 @@ public class LoversSetContent implements Serializable {
 
     @ApiModelProperty("删除标识;0未删除、1已删除")
     @TableField(fill = FieldFill.INSERT)
-    @TableLogic(value="0",delval="1")
+    @TableLogic(value = "0", delval = "1")
     private String delFlag;
 
     @ApiModelProperty("套餐id")
-    private String loversSetId;
+    private Long loversSetId;
 
     @ApiModelProperty("排序")
     private Integer sort;

+ 6 - 2
src/main/java/com/sqx/modules/lovers/entity/LoversSetContentDetail.java

@@ -1,6 +1,10 @@
 package com.sqx.modules.lovers.entity;
 
-import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
@@ -18,8 +22,8 @@ public class LoversSetContentDetail implements Serializable {
     private Long id;
 
     @ApiModelProperty("删除标识;0未删除、1已删除")
+    @TableLogic(value = "0", delval = "1")
     @TableField(fill = FieldFill.INSERT)
-    @TableLogic(value="0",delval="1")
     private String delFlag;
 
     @ApiModelProperty("情侣套餐内容id")

+ 16 - 8
src/main/java/com/sqx/modules/lovers/entity/LoversSetMenstrualPeriodSetting.java

@@ -1,12 +1,17 @@
 package com.sqx.modules.lovers.entity;
 
-import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.Date;
 
 @Data
 @ApiModel("lovers_set_menstrual_period_setting")
@@ -18,8 +23,8 @@ public class LoversSetMenstrualPeriodSetting implements Serializable {
     private Long id;
 
     @ApiModelProperty("删除标识;0未删除、1已删除")
+    @TableLogic(value = "0", delval = "1")
     @TableField(fill = FieldFill.INSERT)
-    @TableLogic(value="0",delval="1")
     private String delFlag;
 
     @ApiModelProperty("用户id")
@@ -32,17 +37,20 @@ public class LoversSetMenstrualPeriodSetting implements Serializable {
     private Integer intervalDays;
 
     @ApiModelProperty("上一次月经开始时间")
-    private String lastStartDate;
+    private Date lastStartDate;
 
     @ApiModelProperty("上一次月经结束时间")
-    private String lastEndDate;
+    private Date lastEndDate;
 
     @ApiModelProperty("预计下一次月经开始时间")
-    private String nextStartDateOfExpect;
+    private Date nextStartDateOfExpect;
 
     @ApiModelProperty("预计下一次月经结束时间")
-    private String nextEndDateOfExpect;
+    private Date nextEndDateOfExpect;
 
     @ApiModelProperty("创建时间")
-    private String create_date;
+    private LocalDateTime createTime;
+
+    @ApiModelProperty("更新时间")
+    private LocalDateTime updateTime;
 }

+ 4 - 3
src/main/java/com/sqx/modules/lovers/entity/LoversSetOrderDeliveryInfo.java

@@ -7,6 +7,7 @@ import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.io.Serializable;
+import java.time.LocalDateTime;
 
 @Data
 @ApiModel("lovers_set_order_delivery_info")
@@ -20,11 +21,11 @@ public class LoversSetOrderDeliveryInfo implements Serializable {
     @ApiModelProperty("情侣套餐订单id")
     private Long loversSetOrderId;
 
-    @ApiModelProperty("情侣套餐订单详情id")
-    private Long loversSetOrderDetailId;
+    @ApiModelProperty("配送内容")
+    private String deliveryContent;
 
     @ApiModelProperty("预计配送时间")
-    private String deliveryTimeOfExpect;
+    private LocalDateTime deliveryTimeOfExpect;
 
     @ApiModelProperty("配送单id(跑腿订单id)")
     private Long deliveryOrderId;

+ 1 - 1
src/main/java/com/sqx/modules/lovers/entity/LoversSetOrderDetail.java

@@ -19,7 +19,7 @@ public class LoversSetOrderDetail implements Serializable {
     private Long id;
 
     @ApiModelProperty("情侣套餐订单id")
-    private String loversSetOrderInfoId;
+    private Long loversSetOrderInfoId;
 
     @ApiModelProperty("商品id")
     private Long goodsId;

+ 14 - 4
src/main/java/com/sqx/modules/lovers/entity/LoversSetOrderInfo.java

@@ -1,12 +1,18 @@
 package com.sqx.modules.lovers.entity;
 
-import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.io.Serializable;
 import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.Date;
 
 @Data
 @ApiModel("lovers_set_order_info")
@@ -18,8 +24,8 @@ public class LoversSetOrderInfo implements Serializable {
     private Long id;
 
     @ApiModelProperty("删除标识;0未删除、1已删除")
+    @TableLogic(value = "0", delval = "1")
     @TableField(fill = FieldFill.INSERT)
-    @TableLogic(value="0",delval="1")
     private String delFlag;
 
     @ApiModelProperty("订单编号")
@@ -53,10 +59,10 @@ public class LoversSetOrderInfo implements Serializable {
     private String receiverPhone;
 
     @ApiModelProperty("接货开始时间")
-    private String receiveStartDate;
+    private Date receiveStartDate;
 
     @ApiModelProperty("接货结束时间")
-    private String receiveEndDate;
+    private Date receiveEndDate;
 
     @ApiModelProperty("期待接货时间;HH:mm:ss")
     private String expectReceiveTime;
@@ -70,5 +76,9 @@ public class LoversSetOrderInfo implements Serializable {
     @ApiModelProperty("订单退款状态;0未退款、1部分退款、2整单退款")
     private String refundStatus;
 
+    @ApiModelProperty("创建时间")
+    private LocalDateTime createTime;
 
+    @ApiModelProperty("更新时间")
+    private LocalDateTime updateTime;
 }

+ 12 - 4
src/main/java/com/sqx/modules/lovers/entity/LoversSetRule.java

@@ -1,11 +1,16 @@
 package com.sqx.modules.lovers.entity;
 
-import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.io.Serializable;
+import java.time.LocalDateTime;
 
 @Data
 @ApiModel("lovers_set_rule")
@@ -17,8 +22,8 @@ public class LoversSetRule implements Serializable {
     private Long id;
 
     @ApiModelProperty("删除标识;0未删除、1已删除")
+    @TableLogic(value = "0", delval = "1")
     @TableField(fill = FieldFill.INSERT)
-    @TableLogic(value="0",delval="1")
     private String delFlag;
 
     @ApiModelProperty("规则名称")
@@ -30,6 +35,9 @@ public class LoversSetRule implements Serializable {
     @ApiModelProperty("规则内容")
     private String content;
 
-    @ApiModelProperty("下单时间")
-    private String createTime;
+    @ApiModelProperty("创建时间")
+    private LocalDateTime createTime;
+
+    @ApiModelProperty("更新时间")
+    private LocalDateTime updateTime;
 }

+ 12 - 0
src/main/java/com/sqx/modules/lovers/service/LoversSetContentDetailService.java

@@ -1,7 +1,19 @@
 package com.sqx.modules.lovers.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.sqx.modules.lovers.dto.LoversSetContentDetailDTO;
 import com.sqx.modules.lovers.entity.LoversSetContentDetail;
 
+import java.util.List;
+
 public interface LoversSetContentDetailService extends IService<LoversSetContentDetail> {
+    void add(List<LoversSetContentDetailDTO> detailDTOS);
+
+    void update(List<LoversSetContentDetailDTO> detailDTOS);
+
+    /**
+     * 根据内容id删除
+     * @param contentIds 内容id列表
+     */
+    void deleteByContentIds(List<Long> contentIds);
 }

+ 13 - 0
src/main/java/com/sqx/modules/lovers/service/LoversSetContentService.java

@@ -1,7 +1,20 @@
 package com.sqx.modules.lovers.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.sqx.modules.lovers.dto.LoversSetContentDTO;
 import com.sqx.modules.lovers.entity.LoversSetContent;
 
+import java.util.List;
+
 public interface LoversSetContentService extends IService<LoversSetContent> {
+    void add(List<LoversSetContentDTO> loversSetContentDTOS);
+
+    void update(List<LoversSetContentDTO> loversSetContentDTOS);
+
+    void deleteByIds(List<Long> ids);
+
+    /**
+     * 根据套餐id删除
+     */
+    void deleteByLoversSetIds(List<Long> loversSetIds);
 }

+ 13 - 0
src/main/java/com/sqx/modules/lovers/service/LoversSetMenstrualPeriodSettingService.java

@@ -1,9 +1,22 @@
 package com.sqx.modules.lovers.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+<<<<<<< HEAD
 import com.sqx.common.utils.Result;
 import com.sqx.modules.lovers.entity.LoversSetMenstrualPeriodSetting;
 
 public interface LoversSetMenstrualPeriodSettingService extends IService<LoversSetMenstrualPeriodSetting> {
 
+=======
+import com.sqx.modules.lovers.dto.LoversSetMenstrualPeriodSettingDTO;
+import com.sqx.modules.lovers.entity.LoversSetMenstrualPeriodSetting;
+
+public interface LoversSetMenstrualPeriodSettingService extends IService<LoversSetMenstrualPeriodSetting> {
+    /**
+     * 新增
+     *
+     * @param menstrualPeriodSettingDTO 情侣套餐经期信息
+     */
+    void add(LoversSetMenstrualPeriodSettingDTO menstrualPeriodSettingDTO);
+>>>>>>> 8850409449b9c25ada6f2ced21d909b90d5559df
 }

+ 10 - 0
src/main/java/com/sqx/modules/lovers/service/LoversSetOrderDetailService.java

@@ -3,5 +3,15 @@ package com.sqx.modules.lovers.service;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.sqx.modules.lovers.entity.LoversSetOrderDetail;
 
+import java.util.List;
+
 public interface LoversSetOrderDetailService extends IService<LoversSetOrderDetail> {
+
+    /**
+     * 根据订单id查询订单详情
+     *
+     * @param orderInfoId 订单id
+     * @return 订单详情列表
+     */
+    List<LoversSetOrderDetail> getByOrderId(Long orderInfoId);
 }

+ 35 - 0
src/main/java/com/sqx/modules/lovers/service/LoversSetOrderInfoService.java

@@ -1,7 +1,42 @@
 package com.sqx.modules.lovers.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.sqx.modules.lovers.dto.LoversSetOrderSubmitDTO;
 import com.sqx.modules.lovers.entity.LoversSetOrderInfo;
+import com.sqx.modules.pay.vo.WechatTransactionsParamVO;
 
 public interface LoversSetOrderInfoService extends IService<LoversSetOrderInfo> {
+
+    /**
+     * 创建订单
+     *
+     * @param userId 用户id
+     * @param submitDTO 提交DTO
+     * @return 订单编号
+     */
+    Long createOrder(Long userId, LoversSetOrderSubmitDTO submitDTO);
+
+    /**
+     * 获取提交订单token
+     *
+     * @param userId 用户id
+     * @return token
+     */
+    String getSubmitToken(Long userId);
+
+    /**
+     * 获取支付参数
+     *
+     * @param userId 用户id
+     * @param orderId 订单id
+     * @return 支付参数
+     */
+    WechatTransactionsParamVO getPayParams(Long userId, Long orderId);
+
+    /**
+     * 订单支付成功后更新订单状态
+     *
+     * @param orderNo 订单编号
+     */
+    void updateOrderAfterPaySuccess(String orderNo);
 }

+ 6 - 5
src/main/java/com/sqx/modules/lovers/service/LoversSetRuleService.java

@@ -1,15 +1,16 @@
 package com.sqx.modules.lovers.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.sqx.common.utils.Result;
+import com.sqx.common.utils.PageUtils;
+import com.sqx.modules.lovers.dto.LoversSetRuleDTO;
+import com.sqx.modules.lovers.dto.LoversSetRuleQueryDTO;
 import com.sqx.modules.lovers.entity.LoversSetRule;
 
 public interface LoversSetRuleService extends IService<LoversSetRule> {
-    Result saveLoverSetRule(LoversSetRule loversSetRule);
 
-    Result pageLoverSetRule(Integer page, Integer limit, String name);
+    PageUtils page(LoversSetRuleQueryDTO queryDTO);
 
-    Result updateLoverSetRule(LoversSetRule loversSetRule);
+    void add(LoversSetRuleDTO loversSetRule);
 
-    Result deleteLoverSetRule(Integer id);
+    void update(LoversSetRuleDTO loversSetRule);
 }

+ 34 - 2
src/main/java/com/sqx/modules/lovers/service/LoversSetService.java

@@ -1,9 +1,41 @@
 package com.sqx.modules.lovers.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.sqx.common.utils.Result;
+import com.sqx.common.utils.PageUtils;
+import com.sqx.modules.lovers.dto.LoversSetAddDTO;
+import com.sqx.modules.lovers.dto.LoversSetQueryDTO;
 import com.sqx.modules.lovers.entity.LoversSet;
+import com.sqx.modules.lovers.vo.LoversSetVO;
+
+import java.util.List;
 
 public interface LoversSetService extends IService<LoversSet> {
-    Result saveLoverSet(LoversSet loversSet);
+    PageUtils pages(LoversSetQueryDTO loversSetQueryDTO);
+
+    void add(LoversSetAddDTO loversSetDTO);
+
+    void update(LoversSetAddDTO loversSetDTO);
+
+    void deleteByIds(List<Long> ids);
+
+    /**
+     * 修改状态
+     * @param id 主键id
+     * @param status 状态 1-正常 2-停用
+     */
+    void updateStatus(Long id, String status);
+
+    /**
+     * 用户端套餐列表
+     * @param queryDTO 查询参数
+     * @return 套餐分页列表
+     */
+    PageUtils listForApp(LoversSetQueryDTO queryDTO);
+
+    /**
+     * 根据套餐id查询详情
+     * @param id 套餐id
+     * @return 套餐详情
+     */
+    LoversSetVO getDetailById(Long id);
 }

+ 60 - 0
src/main/java/com/sqx/modules/lovers/service/impl/LoversSetContentDetailServiceImpl.java

@@ -1,10 +1,70 @@
 package com.sqx.modules.lovers.service.impl;
 
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.sqx.modules.lovers.dao.LoversSetContentDetailDao;
+import com.sqx.modules.lovers.dto.LoversSetContentDetailDTO;
 import com.sqx.modules.lovers.entity.LoversSetContentDetail;
 import com.sqx.modules.lovers.service.LoversSetContentDetailService;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
 
+@Service
 public class LoversSetContentDetailServiceImpl extends ServiceImpl<LoversSetContentDetailDao, LoversSetContentDetail> implements LoversSetContentDetailService {
+
+    @Override
+    @Transactional
+    public void add(List<LoversSetContentDetailDTO> detailDTOS) {
+        List<LoversSetContentDetail> entities = detailDTOS.stream().map(e -> {
+            LoversSetContentDetail loversSetContentDetail = new LoversSetContentDetail();
+            BeanUtil.copyProperties(e, loversSetContentDetail);
+            loversSetContentDetail.setDelFlag("0");
+            return loversSetContentDetail;
+        }).collect(Collectors.toList());
+
+        this.saveBatch(entities);
+    }
+
+    @Override
+    @Transactional
+    public void update(List<LoversSetContentDetailDTO> detailDTOS) {
+        List<LoversSetContentDetail> updateList = new ArrayList<>();
+        List<LoversSetContentDetail> addList = new ArrayList<>();
+
+        for (LoversSetContentDetailDTO detailDTO : detailDTOS) {
+            LoversSetContentDetail loversSetContentDetail = new LoversSetContentDetail();
+            BeanUtil.copyProperties(detailDTO, loversSetContentDetail);
+
+            if (ObjectUtil.isNotNull(detailDTO.getId())) {
+                updateList.add(loversSetContentDetail);
+            } else {
+                loversSetContentDetail.setDelFlag("0");
+                addList.add(loversSetContentDetail);
+            }
+        }
+
+        // 更新数据
+        if (!updateList.isEmpty()) {
+            this.updateBatchById(updateList);
+        }
+
+        // 新增数据
+        if (!addList.isEmpty()) {
+            this.saveBatch(addList);
+        }
+    }
+
+    @Override
+    @Transactional
+    public void deleteByContentIds(List<Long> contentIds) {
+        LambdaQueryWrapper<LoversSetContentDetail> deleteWrapper = new LambdaQueryWrapper<>();
+        deleteWrapper.in(LoversSetContentDetail::getLoversSetContentId, contentIds);
+        this.remove(deleteWrapper);
+    }
 }

+ 131 - 0
src/main/java/com/sqx/modules/lovers/service/impl/LoversSetContentServiceImpl.java

@@ -1,11 +1,142 @@
 package com.sqx.modules.lovers.service.impl;
 
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.sqx.modules.lovers.dao.LoversSetContentDao;
+import com.sqx.modules.lovers.dto.LoversSetContentDTO;
+import com.sqx.modules.lovers.dto.LoversSetContentDetailDTO;
 import com.sqx.modules.lovers.entity.LoversSetContent;
+import com.sqx.modules.lovers.service.LoversSetContentDetailService;
 import com.sqx.modules.lovers.service.LoversSetContentService;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
 
 @Service
+@RequiredArgsConstructor
 public class LoversSetContentServiceImpl extends ServiceImpl<LoversSetContentDao, LoversSetContent> implements LoversSetContentService {
+
+    private final LoversSetContentDetailService loversSetContentDetailService;
+
+    @Override
+    @Transactional
+    public void add(List<LoversSetContentDTO> loversSetContentDTOS) {
+        List<LoversSetContent> loversSetContents = loversSetContentDTOS.stream().map(e -> {
+            LoversSetContent loversSetContent = new LoversSetContent();
+            BeanUtil.copyProperties(e, loversSetContent);
+            loversSetContent.setDelFlag("0");
+            return loversSetContent;
+        }).collect(Collectors.toList());
+
+        this.saveBatch(loversSetContents);
+
+        // 保存套餐内容详情
+        List<LoversSetContentDetailDTO> allDetails = getLoversSetContentDetailDTOS(loversSetContentDTOS, loversSetContents);
+        loversSetContentDetailService.add(allDetails);
+    }
+
+    @Override
+    @Transactional
+    public void update(List<LoversSetContentDTO> loversSetContentDTOS) {
+        Long loversSetId = loversSetContentDTOS.get(0).getLoversSetId();
+        LambdaQueryWrapper<LoversSetContent> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(LoversSetContent::getLoversSetId, loversSetId);
+        List<LoversSetContent> oldList = this.list(queryWrapper);
+
+        // 提取DTO中的ID列表
+        List<Long> dtoIds = loversSetContentDTOS.stream()
+                .filter(dto -> ObjectUtil.isNotNull(dto.getId()))
+                .map(LoversSetContentDTO::getId)
+                .collect(Collectors.toList());
+        // 待删除数据id列表
+        List<Long> deleteIds = oldList.stream()
+                .filter(old -> !dtoIds.contains(old.getId()))
+                .map(LoversSetContent::getId)
+                .collect(Collectors.toList());
+
+        // 区分更新和新增数据
+        List<LoversSetContent> updateList = new ArrayList<>();
+        List<LoversSetContent> addList = new ArrayList<>();
+        List<LoversSetContentDTO> updateDTOList = new ArrayList<>();
+        List<LoversSetContentDTO> addDTOList = new ArrayList<>();
+        List<Long> existingIds = oldList.stream().map(LoversSetContent::getId).collect(Collectors.toList());
+        for (LoversSetContentDTO dto : loversSetContentDTOS) {
+            LoversSetContent entity = new LoversSetContent();
+            BeanUtil.copyProperties(dto, entity);
+
+            if (ObjectUtil.isNotNull(dto.getId()) && existingIds.contains(dto.getId())) {
+                // 更新操作
+                updateList.add(entity);
+                updateDTOList.add(dto);
+            } else {
+                // 新增操作
+                entity.setId(null); // 清除可能存在的无效ID
+                entity.setDelFlag("0");
+                addList.add(entity);
+                addDTOList.add(dto);
+            }
+        }
+
+        // 删除数据
+        if (CollUtil.isNotEmpty(deleteIds)) {
+            deleteByIds(deleteIds);
+        }
+
+        // 更新数据
+        if (!updateList.isEmpty()) {
+            this.updateBatchById(updateList);
+        }
+
+        // 新增数据
+        if (!addList.isEmpty()) {
+            this.saveBatch(addList);
+        }
+
+        // 合并更新和新增的内容详情
+        List<LoversSetContentDetailDTO> unionDetails = CollUtil.union(
+                    getLoversSetContentDetailDTOS(updateDTOList, updateList),
+                    getLoversSetContentDetailDTOS(addDTOList, addList)
+                )
+                .stream()
+                .collect(Collectors.toList());
+        loversSetContentDetailService.update(unionDetails);
+    }
+
+    @Override
+    @Transactional
+    public void deleteByIds(List<Long> ids) {
+        removeByIds(ids);
+        // 删除内容详情
+        loversSetContentDetailService.deleteByContentIds(ids);
+    }
+
+    @Override
+    @Transactional
+    public void deleteByLoversSetIds(List<Long> loversSetIds) {
+        LambdaQueryWrapper<LoversSetContent> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.in(LoversSetContent::getLoversSetId, loversSetIds);
+        List<LoversSetContent> list = list(queryWrapper);
+        List<Long> ids = list.stream().map(LoversSetContent::getId).collect(Collectors.toList());
+
+        deleteByIds(ids);
+    }
+
+    private List<LoversSetContentDetailDTO> getLoversSetContentDetailDTOS(List<LoversSetContentDTO> loversSetContentDTOS, List<LoversSetContent> loversSetContents) {
+        List<LoversSetContentDetailDTO> allDetails = new ArrayList<>();
+        for (int i = 0; i < loversSetContentDTOS.size(); i++) {
+            LoversSetContentDTO dto = loversSetContentDTOS.get(i);
+            LoversSetContent entity = loversSetContents.get(i);
+            List<LoversSetContentDetailDTO> details = dto.getLoversSetContentDetailDTOS();
+            details.forEach(detail -> detail.setLoversSetContentId(entity.getId()));
+            allDetails.addAll(details);
+        }
+        return allDetails;
+    }
 }

+ 11 - 0
src/main/java/com/sqx/modules/lovers/service/impl/LoversSetMenstrualPeriodSettingServiceImpl.java

@@ -1,8 +1,10 @@
 package com.sqx.modules.lovers.service.impl;
 
+import cn.hutool.core.bean.BeanUtil;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.sqx.common.utils.Result;
 import com.sqx.modules.lovers.dao.LoversSetMenstrualPeriodSettingDao;
+import com.sqx.modules.lovers.dto.LoversSetMenstrualPeriodSettingDTO;
 import com.sqx.modules.lovers.entity.LoversSetMenstrualPeriodSetting;
 import com.sqx.modules.lovers.service.LoversSetMenstrualPeriodSettingService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -11,8 +13,17 @@ import org.springframework.stereotype.Service;
 @Service
 public class LoversSetMenstrualPeriodSettingServiceImpl extends ServiceImpl<LoversSetMenstrualPeriodSettingDao,LoversSetMenstrualPeriodSetting> implements LoversSetMenstrualPeriodSettingService {
 
+<<<<<<< HEAD
     @Autowired
     LoversSetMenstrualPeriodSettingDao loversSetMenstrualPeriodSettingDao;
 
 
+=======
+    @Override
+    public void add(LoversSetMenstrualPeriodSettingDTO menstrualPeriodSettingDTO) {
+        LoversSetMenstrualPeriodSetting menstrualPeriodSetting = new LoversSetMenstrualPeriodSetting();
+        BeanUtil.copyProperties(menstrualPeriodSettingDTO, menstrualPeriodSetting);
+        save(menstrualPeriodSetting);
+    }
+>>>>>>> 8850409449b9c25ada6f2ced21d909b90d5559df
 }

+ 10 - 0
src/main/java/com/sqx/modules/lovers/service/impl/LoversSetOrderDetailServiceImpl.java

@@ -1,11 +1,21 @@
 package com.sqx.modules.lovers.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.sqx.modules.lovers.dao.LoversSetOrderDetailDao;
 import com.sqx.modules.lovers.entity.LoversSetOrderDetail;
 import com.sqx.modules.lovers.service.LoversSetOrderDetailService;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
+
 @Service
 public class LoversSetOrderDetailServiceImpl extends ServiceImpl<LoversSetOrderDetailDao, LoversSetOrderDetail> implements LoversSetOrderDetailService {
+
+    @Override
+    public List<LoversSetOrderDetail> getByOrderId(Long orderInfoId) {
+        LambdaQueryWrapper<LoversSetOrderDetail> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(LoversSetOrderDetail::getLoversSetOrderInfoId, orderInfoId);
+        return baseMapper.selectList(wrapper);
+    }
 }

+ 239 - 0
src/main/java/com/sqx/modules/lovers/service/impl/LoversSetOrderInfoServiceImpl.java

@@ -1,11 +1,250 @@
 package com.sqx.modules.lovers.service.impl;
 
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.sqx.common.constant.RedisKey;
+import com.sqx.common.exception.SqxException;
+import com.sqx.common.utils.Constant;
+import com.sqx.common.utils.RedisUtils;
+import com.sqx.modules.app.entity.UserEntity;
+import com.sqx.modules.app.service.UserService;
 import com.sqx.modules.lovers.dao.LoversSetOrderInfoDao;
+import com.sqx.modules.lovers.dto.LoversSetMenstrualPeriodSettingDTO;
+import com.sqx.modules.lovers.dto.LoversSetOrderSubmitDTO;
+import com.sqx.modules.lovers.entity.LoversSetOrderDeliveryInfo;
+import com.sqx.modules.lovers.entity.LoversSetOrderDetail;
 import com.sqx.modules.lovers.entity.LoversSetOrderInfo;
+import com.sqx.modules.lovers.service.LoversSetMenstrualPeriodSettingService;
+import com.sqx.modules.lovers.service.LoversSetOrderDeliveryInfoService;
+import com.sqx.modules.lovers.service.LoversSetOrderDetailService;
 import com.sqx.modules.lovers.service.LoversSetOrderInfoService;
+import com.sqx.modules.lovers.service.LoversSetService;
+import com.sqx.modules.lovers.vo.LoversSetVO;
+import com.sqx.modules.pay.dto.GetPayParamDTO;
+import com.sqx.modules.pay.enums.PayChannelEnum;
+import com.sqx.modules.pay.enums.PaySceneEnum;
+import com.sqx.modules.pay.service.NewPayService;
+import com.sqx.modules.pay.vo.WechatTransactionsParamVO;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.RoundingMode;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 
 @Service
+@RequiredArgsConstructor
 public class LoversSetOrderInfoServiceImpl extends ServiceImpl<LoversSetOrderInfoDao, LoversSetOrderInfo> implements LoversSetOrderInfoService {
+
+    private final RedisUtils redisUtils;
+    private final LoversSetService loversSetService;
+    private final LoversSetMenstrualPeriodSettingService loversSetMenstrualPeriodSettingService;
+    private final LoversSetOrderDetailService loversSetOrderDetailService;
+    private final LoversSetOrderDeliveryInfoService loversSetOrderDeliveryInfoService;
+    private final NewPayService newPayService;
+    private final UserService userService;
+
+    @Override
+    @Transactional
+    public Long createOrder(Long userId, LoversSetOrderSubmitDTO submitDTO) {
+        // 校验令牌
+        checkToken(userId, submitDTO.getSubmitToken());
+
+        // 校验套餐信息
+        LoversSetVO loversSetVO = checkLoversSetInfo(submitDTO);
+
+        // 保存经期信息
+        LoversSetMenstrualPeriodSettingDTO menstrualPeriodSettingDTO = generateLoversSetMenstrualPeriodSettingDTO(userId, submitDTO);
+        loversSetMenstrualPeriodSettingService.add(menstrualPeriodSettingDTO);
+
+        // 保存情侣套餐订单
+        LoversSetOrderInfo loversSetOrderInfo = generateLoversSetOrder(userId, submitDTO, loversSetVO);
+
+        return loversSetOrderInfo.getId();
+    }
+
+    @Override
+    public String getSubmitToken(Long userId) {
+        String token = UUID.randomUUID().toString().replace("-", "");
+        String key = String.format(RedisKey.LOVERS_SET_ORDER_SUBMIT_TOKEN, userId.toString());
+
+        // 过期时间设置为5分钟
+        redisUtils.set(key, token, 60 * 5);
+
+        return token;
+    }
+
+    @Override
+    public WechatTransactionsParamVO getPayParams(Long userId, Long orderId) {
+        LoversSetOrderInfo orderInfo = getById(orderId);
+
+        UserEntity userEntity = userService.queryByUserId(userId);
+
+        GetPayParamDTO dto = GetPayParamDTO.builder()
+                .orderNo(orderInfo.getOrderNumber())
+                .orderDesc("情侣套餐:" + orderInfo.getLoversSetName())
+                .amount(orderInfo.getPayAmount().setScale(2, RoundingMode.HALF_UP))
+                .userId(userId)
+                .userThirdId(userEntity.getOpenId())
+                .payChannel(PayChannelEnum.WECHAT_JS_API)
+                .paySceneEnum(PaySceneEnum.LOVERS_SET_ORDER_PAY)
+                .build();
+
+        return newPayService.getWechatTransactionsParamVO(dto);
+    }
+
+    @Override
+    @Transactional
+    public void updateOrderAfterPaySuccess(String orderNo) {
+        LoversSetOrderInfo orderInfo = getOne(new LambdaQueryWrapper<LoversSetOrderInfo>()
+                .eq(LoversSetOrderInfo::getOrderNumber, orderNo));
+
+        orderInfo.setPayStatus(Constant.YES);
+        orderInfo.setActiveStatus(Constant.YES);
+        orderInfo.setUpdateTime(LocalDateTime.now());
+        updateById(orderInfo);
+
+        // 新增并保存配送信息
+        saveDeliveryInfo(orderInfo);
+    }
+
+    private void saveDeliveryInfo(LoversSetOrderInfo orderInfo) {
+        // 生成订单配送信息
+        List<LoversSetOrderDetail> orderDetails = loversSetOrderDetailService.getByOrderId(orderInfo.getId());
+        // 按shopId分组订单详情
+        Map<Long, List<LoversSetOrderDetail>> detailsByShopId = orderDetails.stream()
+                .collect(Collectors.groupingBy(LoversSetOrderDetail::getShopId));
+
+        // 配送起止时间
+        LocalDate startDate = orderInfo.getReceiveStartDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+        LocalDate endDate = orderInfo.getReceiveEndDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+
+        List<LoversSetOrderDeliveryInfo> deliveryInfoList = IntStream.range(0, (int) ChronoUnit.DAYS.between(startDate, endDate))
+                .mapToObj(i -> startDate.plusDays(i))
+                .flatMap(date -> {
+                    LocalDateTime expectReceiveTime = LocalDateTime.parse(
+                            date + " " + orderInfo.getExpectReceiveTime(),
+                            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
+                    );
+
+                    return detailsByShopId.values().stream()
+                            .map(orderDetailList -> {
+                                String content = orderDetailList.stream()
+                                        .map(e -> e.getGoodsName() + "x" + e.getNum())
+                                        .collect(Collectors.joining(";"));
+
+                                return new LoversSetOrderDeliveryInfo() {
+                                    {
+                                        setLoversSetOrderId(orderInfo.getId());
+                                        setDeliveryContent(content);
+                                        setDeliveryTimeOfExpect(expectReceiveTime);
+                                        // 1等待生成配送单
+                                        setDeliveryStatus("1");
+                                    }
+                                };
+                            });
+                })
+                .collect(Collectors.toList());
+
+        // 保存配送信息
+        loversSetOrderDeliveryInfoService.saveBatch(deliveryInfoList);
+    }
+
+    private LoversSetOrderInfo generateLoversSetOrder(Long userId, LoversSetOrderSubmitDTO submitDTO, LoversSetVO loversSetVO) {
+        LoversSetOrderInfo loversSetOrderInfo = new LoversSetOrderInfo();
+        loversSetOrderInfo.setOrderNumber(IdWorker.getTimeId());
+        loversSetOrderInfo.setUserId(userId);
+        loversSetOrderInfo.setLoversSetId(submitDTO.getLoversSetId());
+        loversSetOrderInfo.setLoversSetName(loversSetVO.getName());
+        loversSetOrderInfo.setLoversSetMasterImg(loversSetVO.getImgs().split(",")[0]);
+        loversSetOrderInfo.setLoversSetAmount(loversSetVO.getPrice());
+        loversSetOrderInfo.setPayAmount(submitDTO.getPayAmount());
+        loversSetOrderInfo.setReceiverName(submitDTO.getReceiverName());
+        loversSetOrderInfo.setReceiverPhone(submitDTO.getReceiverPhone());
+        loversSetOrderInfo.setExpectReceiveTime(submitDTO.getExpectReceiveTime());
+        loversSetOrderInfo.setReceiveStartDate(submitDTO.getReceiveStartDate());
+        loversSetOrderInfo.setReceiveEndDate(submitDTO.getReceiveEndDate());
+        loversSetOrderInfo.setActiveStatus(Constant.NO);
+        loversSetOrderInfo.setPayStatus(Constant.NO);
+        loversSetOrderInfo.setRefundStatus(Constant.NO);
+        loversSetOrderInfo.setCreateTime(LocalDateTime.now());
+        loversSetOrderInfo.setUpdateTime(LocalDateTime.now());
+
+        this.save(loversSetOrderInfo);
+
+        // 生成订单详情
+        List<LoversSetOrderDetail> orderDetailList = loversSetVO.getContentList()
+                .stream()
+                .flatMap(contentVO -> contentVO.getContentDetailList().stream())
+                .map(detailVO -> {
+                    LoversSetOrderDetail orderDetail = new LoversSetOrderDetail();
+                    BeanUtil.copyProperties(detailVO, orderDetail);
+                    orderDetail.setLoversSetOrderInfoId(loversSetOrderInfo.getId());
+                    return orderDetail;
+                })
+                .collect(Collectors.toList());
+
+        loversSetOrderDetailService.saveBatch(orderDetailList);
+
+        return loversSetOrderInfo;
+    }
+
+    private LoversSetMenstrualPeriodSettingDTO generateLoversSetMenstrualPeriodSettingDTO(Long userId, LoversSetOrderSubmitDTO submitDTO) {
+        LoversSetMenstrualPeriodSettingDTO dto = new LoversSetMenstrualPeriodSettingDTO();
+        BeanUtil.copyProperties(submitDTO, dto);
+        dto.setUserId(userId);
+        dto.setCreateTime(LocalDateTime.now());
+        dto.setUpdateTime(LocalDateTime.now());
+        return dto;
+    }
+
+    private LoversSetVO checkLoversSetInfo(LoversSetOrderSubmitDTO submitDTO) {
+        LoversSetVO loversSetVO = loversSetService.getDetailById(submitDTO.getLoversSetId());
+        if (ObjectUtil.isNull(loversSetVO)) {
+            throw new SqxException("无效的情侣套餐id");
+        }
+
+        // 校验套餐状态
+        if (!StrUtil.equals(loversSetVO.getSetStatus(), Constant.YES)) {
+            throw new SqxException("当前情侣套餐状态异常");
+        }
+
+        // 校验套餐金额
+        if (loversSetVO.getPrice().compareTo(submitDTO.getPayAmount()) != 0 ) {
+            throw new SqxException("订单价格发生变动,请刷新页面后重试");
+        }
+
+        // 校验套餐有效时间
+        LocalDateTime now = LocalDateTime.now();
+        if (now.isBefore(loversSetVO.getStartTime()) || now.isAfter(loversSetVO.getEndTime())) {
+            throw new SqxException("当前时间不在套餐有效时间内");
+        }
+
+        return loversSetVO;
+    }
+
+    private void checkToken(Long userId, String submitToken) {
+        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
+        String key = String.format(RedisKey.LOVERS_SET_ORDER_SUBMIT_TOKEN, userId.toString());
+
+        // 执行redis脚本,成功返回1,失败返回
+        Long result = redisUtils.execute(key, script, submitToken);
+        if (result == 0) {
+            // 令牌验证失败
+            throw new SqxException("无效的提交token,请刷新页面重新提交订单");
+        }
+    }
 }

+ 47 - 41
src/main/java/com/sqx/modules/lovers/service/impl/LoversSetRuleServiceImpl.java

@@ -1,69 +1,75 @@
 package com.sqx.modules.lovers.service.impl;
 
-import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.sqx.common.exception.SqxException;
 import com.sqx.common.utils.PageUtils;
-import com.sqx.common.utils.Result;
 import com.sqx.modules.lovers.dao.LoversSetRuleDao;
+import com.sqx.modules.lovers.dto.LoversSetRuleDTO;
+import com.sqx.modules.lovers.dto.LoversSetRuleQueryDTO;
 import com.sqx.modules.lovers.entity.LoversSetRule;
 import com.sqx.modules.lovers.service.LoversSetRuleService;
-import com.sqx.modules.order.entity.OrderGoods;
-import com.sqx.modules.order.entity.TbOrder;
-import org.checkerframework.checker.units.qual.A;
-import org.springframework.beans.factory.annotation.Autowired;
+import com.sqx.modules.lovers.vo.LoversSetRuleVO;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
+import java.util.stream.Collectors;
 
 @Service
 public class LoversSetRuleServiceImpl extends ServiceImpl<LoversSetRuleDao, LoversSetRule> implements LoversSetRuleService {
 
-    @Autowired
-    LoversSetRuleDao loversSetRuleDao;
-
     @Override
-    public Result saveLoverSetRule(LoversSetRule loversSetRule) {
-        int insert = loversSetRuleDao.insert(loversSetRule);
-        return Result.success();
+    public PageUtils page(LoversSetRuleQueryDTO queryDTO) {
+        Page<LoversSetRule> pages = new Page<>(queryDTO.getPage(), queryDTO.getLimit());
+        LambdaQueryWrapper<LoversSetRule> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(StrUtil.isNotBlank(queryDTO.getName()), LoversSetRule::getName, queryDTO.getName());
+
+        IPage<LoversSetRule> page = this.page(pages, queryWrapper);
+        PageUtils pageUtils = new PageUtils(page);
+
+        List<LoversSetRuleVO> vos = pageUtils.getList().stream().map(e -> {
+            LoversSetRuleVO vo = new LoversSetRuleVO();
+            BeanUtil.copyProperties(e, vo);
+            return vo;
+        }).collect(Collectors.toList());
+
+        pageUtils.setList(vos);
+
+        return pageUtils;
     }
 
     @Override
-    public Result pageLoverSetRule(Integer page, Integer limit, String name) {
-        Page<LoversSetRule> pages = new Page<>(page, limit);
-        LambdaQueryWrapper<LoversSetRule> wrapper=new LambdaQueryWrapper<>();
-        wrapper.like(ObjectUtils.isNotEmpty(name),LoversSetRule::getName,name);
-        wrapper.eq(LoversSetRule::getDelFlag,0);
-        wrapper.orderByAsc(LoversSetRule::getSort);
-        IPage<LoversSetRule> loversSetRuleIPage = loversSetRuleDao.selectPage(pages,wrapper);
-        PageUtils pageUtils = new PageUtils(loversSetRuleIPage);
-        return Result.success().put("data", pageUtils);
+    public void add(LoversSetRuleDTO loversSetRule) {
+        // 检测名称是否重复
+        checkNameUnique(null, loversSetRule.getName());
+
+        LoversSetRule entity = new LoversSetRule();
+        BeanUtil.copyProperties(loversSetRule, entity);
+        entity.setDelFlag("0");
+
+        this.save(entity);
     }
 
     @Override
-    public Result updateLoverSetRule(LoversSetRule loversSetRule) {
-        String name = loversSetRule.getName();
-//        判定该名称是否已存在
-        LambdaQueryWrapper<LoversSetRule> warpper=new LambdaQueryWrapper<>();
-        warpper.eq(LoversSetRule::getName,name)
-                        .eq(LoversSetRule::getDelFlag,0);
-        LoversSetRule old = loversSetRuleDao.selectOne(warpper);
-        if (ObjectUtils.isNotEmpty(old)) {
-            if (!old.getId().equals(loversSetRule.getId())) {
-                return Result.error("该规则名称已存在");
-            }
-        }
-        loversSetRuleDao.updateById(loversSetRule);
-        return Result.success();
+    public void update(LoversSetRuleDTO loversSetRule) {
+        checkNameUnique(loversSetRule.getId(), loversSetRule.getName());
+
+        LoversSetRule entity = new LoversSetRule();
+        BeanUtil.copyProperties(loversSetRule, entity);
+        this.updateById(entity);
     }
 
-    @Override
-    public Result deleteLoverSetRule(Integer id) {
-        loversSetRuleDao.deleteById(id);
-        return Result.success();
+    private void checkNameUnique(Long id, String name) {
+        LambdaQueryWrapper<LoversSetRule> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.ne(ObjectUtil.isNotNull(id), LoversSetRule::getId, id);
+        queryWrapper.eq(LoversSetRule::getName, name);
+        if (this.count(queryWrapper) > 0) {
+            throw new SqxException("规则名称重复");
+        }
     }
 }

+ 76 - 6
src/main/java/com/sqx/modules/lovers/service/impl/LoversSetServiceImpl.java

@@ -1,21 +1,91 @@
 package com.sqx.modules.lovers.service.impl;
 
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.sqx.common.utils.Result;
+import com.sqx.common.utils.PageUtils;
 import com.sqx.modules.lovers.dao.LoversSetDao;
+import com.sqx.modules.lovers.dto.LoversSetAddDTO;
+import com.sqx.modules.lovers.dto.LoversSetQueryDTO;
 import com.sqx.modules.lovers.entity.LoversSet;
+import com.sqx.modules.lovers.service.LoversSetContentService;
 import com.sqx.modules.lovers.service.LoversSetService;
-import org.springframework.beans.factory.annotation.Autowired;
+import com.sqx.modules.lovers.vo.AppLoversSetShortVO;
+import com.sqx.modules.lovers.vo.LoversSetVO;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
 
 @Service
+@RequiredArgsConstructor
 public class LoversSetServiceImpl extends ServiceImpl<LoversSetDao, LoversSet> implements LoversSetService {
-    @Autowired
-    LoversSetDao loversSetDao;
+
+    private final LoversSetContentService loversSetContentService;
+
+    @Override
+    public PageUtils pages(LoversSetQueryDTO queryDTO) {
+        IPage<LoversSetVO> page = baseMapper.pages(new Page<>(queryDTO.getPage(), queryDTO.getLimit()), queryDTO);
+        PageUtils pageUtils = new PageUtils(page);
+        return pageUtils;
+    }
+
+    @Override
+    @Transactional
+    public void add(LoversSetAddDTO loversSetDTO) {
+        // 新增主信息
+        LoversSet loversSet = new LoversSet();
+        BeanUtil.copyProperties(loversSetDTO, loversSet);
+        loversSet.setDelFlag("0");
+        this.save(loversSet);
+
+        loversSetDTO.getLoversSetContentDTOS().forEach(e -> e.setLoversSetId(loversSet.getId()));
+        // 新增套餐内容
+        loversSetContentService.add(loversSetDTO.getLoversSetContentDTOS());
+    }
 
     @Override
-    public Result saveLoverSet(LoversSet loversSet) {
+    @Transactional
+    public void update(LoversSetAddDTO loversSetDTO) {
+        LoversSet loversSet = new LoversSet();
+        BeanUtil.copyProperties(loversSetDTO, loversSet);
+
+        this.updateById(loversSet);
+
+        loversSetDTO.getLoversSetContentDTOS().stream().filter(e -> ObjectUtil.isNull(e.getId())).forEach(e -> e.setLoversSetId(loversSet.getId()));
+        // 修改套餐内容
+        loversSetContentService.update(loversSetDTO.getLoversSetContentDTOS());
+    }
 
-        return null;
+    @Override
+    @Transactional
+    public void deleteByIds(List<Long> ids) {
+        this.removeByIds(ids);
+
+        // 删除套餐内容
+        loversSetContentService.deleteByLoversSetIds(ids);
+    }
+
+    @Override
+    public void updateStatus(Long id, String status) {
+        LoversSet loversSet = new LoversSet();
+        loversSet.setId(id);
+        loversSet.setSetStatus(status);
+        this.updateById(loversSet);
+    }
+
+    @Override
+    public PageUtils listForApp(LoversSetQueryDTO queryDTO) {
+        IPage<AppLoversSetShortVO> page = baseMapper.listForApp(new Page<>(queryDTO.getPage(), queryDTO.getLimit()), queryDTO);
+        PageUtils pageUtils = new PageUtils(page);
+        return pageUtils;
+    }
+
+    @Override
+    public LoversSetVO getDetailById(Long id) {
+        return baseMapper.getDetailById(id);
     }
 }

+ 58 - 0
src/main/java/com/sqx/modules/lovers/vo/AppLoversSetShortVO.java

@@ -0,0 +1,58 @@
+package com.sqx.modules.lovers.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 用户端套餐简略信息
+ * @author codingliang
+ * @date 2025-08-25
+ */
+@Data
+public class AppLoversSetShortVO {
+
+    @ApiModelProperty("主键id")
+    private Long id;
+
+    @ApiModelProperty("套餐名称")
+    private String name;
+
+    @ApiModelProperty("套餐子名称")
+    private String subName;
+
+    @ApiModelProperty("套餐标签;多个标签之间使用,分割")
+    private String setTag;
+
+    @ApiModelProperty("服务标签;多个标签之间使用,分割")
+    private String serviceTag;
+
+    @ApiModelProperty("价格")
+    private BigDecimal price;
+
+    @ApiModelProperty("原价")
+    private BigDecimal originalPrice;
+
+    @ApiModelProperty("图片;多张图片使用,分割,第一张为主图")
+    private String imgs;
+
+    @ApiModelProperty("套餐类型;1月度套餐,2季度套餐,3年度套餐,4自定义")
+    private String setType;
+
+    @ApiModelProperty("适用性别;1男、2女")
+    private String suitSex;
+
+    @ApiModelProperty("套餐开始时间")
+    private LocalDateTime startTime;
+
+    @ApiModelProperty("套餐结束时间")
+    private LocalDateTime endTime;
+
+    @ApiModelProperty("自定义时间段开始时间;type为4自定义时必填")
+    private LocalDateTime selfStartTime;
+
+    @ApiModelProperty("自定义时间段结束时间;type为4自定义时必填")
+    private LocalDateTime selfEndTime;
+}

+ 38 - 0
src/main/java/com/sqx/modules/lovers/vo/LoversSetContentDetailVO.java

@@ -0,0 +1,38 @@
+package com.sqx.modules.lovers.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+@ApiModel("lovers_set_content_detail")
+public class LoversSetContentDetailVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty("内容详情id")
+    private Long contentDetailId;
+
+    @ApiModelProperty("商品id")
+    private Long goodsId;
+
+    @ApiModelProperty("商品名称")
+    private String goodsName;
+
+    @ApiModelProperty("店铺id")
+    private Long shopId;
+
+    @ApiModelProperty("店铺名称")
+    private String shopName;
+
+    @ApiModelProperty("数量")
+    private Integer num;
+
+    @ApiModelProperty("价格")
+    private BigDecimal price;
+
+    @ApiModelProperty("原价")
+    private BigDecimal originalPrice;
+}

+ 26 - 0
src/main/java/com/sqx/modules/lovers/vo/LoversSetContentVO.java

@@ -0,0 +1,26 @@
+package com.sqx.modules.lovers.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+@ApiModel("lovers_set_content")
+public class LoversSetContentVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty("主键id")
+    private Long contentId;
+
+    @ApiModelProperty("排序")
+    private Integer sort;
+
+    @ApiModelProperty("内容名称")
+    private String contentName;
+
+    @ApiModelProperty("内容详情列表")
+    private List<LoversSetContentDetailVO> contentDetailList;
+}

+ 22 - 0
src/main/java/com/sqx/modules/lovers/vo/LoversSetRuleVO.java

@@ -0,0 +1,22 @@
+package com.sqx.modules.lovers.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class LoversSetRuleVO implements Serializable {
+
+    @ApiModelProperty("主键id")
+    private Long id;
+
+    @ApiModelProperty("规则名称")
+    private String name;
+
+    @ApiModelProperty("排序")
+    private Integer sort;
+
+    @ApiModelProperty("规则内容")
+    private String content;
+}

+ 76 - 0
src/main/java/com/sqx/modules/lovers/vo/LoversSetVO.java

@@ -0,0 +1,76 @@
+package com.sqx.modules.lovers.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * @author codingliang
+ * @date 2025-08-25
+ */
+@Data
+public class LoversSetVO {
+
+    @ApiModelProperty("主键id")
+    private Long id;
+
+    @ApiModelProperty("套餐名称")
+    private String name;
+
+    @ApiModelProperty("套餐子名称")
+    private String subName;
+
+    @ApiModelProperty("套餐标签;多个标签之间使用,分割")
+    private String setTag;
+
+    @ApiModelProperty("服务标签;多个标签之间使用,分割")
+    private String serviceTag;
+
+    @ApiModelProperty("价格")
+    private BigDecimal price;
+
+    @ApiModelProperty("原价")
+    private BigDecimal originalPrice;
+
+    @ApiModelProperty("图片;多张图片使用,分割,第一张为主图")
+    private String imgs;
+
+    @ApiModelProperty("套餐类型;1月度套餐,2季度套餐,3年度套餐,4自定义")
+    private String setType;
+
+    @ApiModelProperty("适用性别;1男、2女")
+    private String suitSex;
+
+    @ApiModelProperty("规则id")
+    private Long ruleId;
+
+    @ApiModelProperty("规则名称")
+    private String ruleName;
+
+    @ApiModelProperty("规则内容")
+    private String ruleContent;
+
+    @ApiModelProperty("状态;1可用、2不可用")
+    private String setStatus;
+
+    @ApiModelProperty("子订单生成时机;单位:小时")
+    private Integer subOrderGenerateTime;
+
+    @ApiModelProperty("套餐开始时间")
+    private LocalDateTime startTime;
+
+    @ApiModelProperty("套餐结束时间")
+    private LocalDateTime endTime;
+
+    @ApiModelProperty("自定义时间段开始时间;type为4自定义时必填")
+    private LocalDateTime selfStartTime;
+
+    @ApiModelProperty("自定义时间段结束时间;type为4自定义时必填")
+    private LocalDateTime selfEndTime;
+
+    @ApiModelProperty("套餐内容列表")
+    private List<LoversSetContentVO> contentList;
+}

+ 2 - 1
src/main/java/com/sqx/modules/pay/enums/PaySceneEnum.java

@@ -18,7 +18,8 @@ public enum PaySceneEnum {
     ORDER_PAY(1, "订单支付"),
     BALANCE_RECHARGE(2, "余额充值"),
     BOND_PAY(3, "保证金缴纳"),
-    VIP_PAY(4, "购买会员");
+    VIP_PAY(4, "购买会员"),
+    LOVERS_SET_ORDER_PAY(5, "情侣套餐订单支付");
 
     private int sceneCode;
     private String sceneDesc;

+ 11 - 45
src/main/java/com/sqx/modules/pay/service/impl/NewPayServiceImpl.java

@@ -4,8 +4,6 @@ import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.ekyong.www.pay.common.Constant;
 import com.ekyong.www.pay.pay.qrcode.api.RhtQrcodePayApi;
 import com.ekyong.www.pay.pay.qrcode.bean.QrcodeOpenPayRequestBean;
@@ -18,43 +16,15 @@ import com.ekyong.www.pay.pay.split.bean.SplitPayResponseBean;
 import com.ekyong.www.pay.util.SignUtil;
 import com.sqx.common.exception.SqxException;
 import com.sqx.common.utils.SpringContextUtils;
-import com.sqx.modules.activity.service.ActivityPartRecordService;
-import com.sqx.modules.activity.service.ActivityService;
-import com.sqx.modules.address.entity.Address;
-import com.sqx.modules.address.service.AddressService;
 import com.sqx.modules.app.bo.UpdateMoneyBO;
-import com.sqx.modules.app.dao.UserBrowseDao;
-import com.sqx.modules.app.dao.UserDao;
-import com.sqx.modules.app.dao.UserMoneyDao;
-import com.sqx.modules.app.dao.UserMoneyDetailsDao;
 import com.sqx.modules.app.service.UserMoneyService;
-import com.sqx.modules.app.service.UserService;
 import com.sqx.modules.common.service.CommonInfoService;
-import com.sqx.modules.coupon.dao.TbCouponUserDao;
 import com.sqx.modules.datacentre.service.DataCentreService;
-import com.sqx.modules.errand.dao.TbIndentDao;
-import com.sqx.modules.errand.service.TbIndentService;
-import com.sqx.modules.errand.service.TbIndentSmsSendLogService;
-import com.sqx.modules.errand.service.TbIndentSmsTemplateService;
-import com.sqx.modules.goods.dao.GoodsDao;
-import com.sqx.modules.goods.dao.GoodsShopDao;
-import com.sqx.modules.goods.dao.GoodsShopRelevancyDao;
-import com.sqx.modules.goods.dao.GoodsSkuDao;
-import com.sqx.modules.goods.entity.GoodsShop;
 import com.sqx.modules.goods.service.GoodsShopService;
-import com.sqx.modules.integral.dao.UserIntegralDao;
-import com.sqx.modules.integral.dao.UserIntegralDetailsDao;
-import com.sqx.modules.message.dao.MessageInfoDao;
-import com.sqx.modules.order.dao.AppOrderDao;
-import com.sqx.modules.order.dao.EvaluateDao;
-import com.sqx.modules.order.dao.OrderGoodsDao;
-import com.sqx.modules.order.entity.OrderGoods;
+import com.sqx.modules.lovers.service.LoversSetOrderInfoService;
 import com.sqx.modules.order.entity.TbOrder;
 import com.sqx.modules.order.service.AppOrderService;
-import com.sqx.modules.order.service.EvaluateRiderService;
 import com.sqx.modules.pay.config.WechatPayConfig;
-import com.sqx.modules.pay.controller.app.AliPayController;
-import com.sqx.modules.pay.dao.PayDetailsDao;
 import com.sqx.modules.pay.dto.GetPayParamDTO;
 import com.sqx.modules.pay.entity.PayDetails;
 import com.sqx.modules.pay.enums.PayChannelEnum;
@@ -62,32 +32,18 @@ import com.sqx.modules.pay.enums.PaySceneEnum;
 import com.sqx.modules.pay.enums.PayStateEnums;
 import com.sqx.modules.pay.service.NewPayService;
 import com.sqx.modules.pay.service.PayDetailsService;
-import com.sqx.modules.pay.service.WxErrService;
 import com.sqx.modules.pay.vo.WechatTransactionsParamVO;
-import com.sqx.modules.shop.service.ShopMessageService;
-import com.sqx.modules.shop.service.ShopTypeService;
-import com.sqx.modules.sys.service.SysUserService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.entity.StringEntity;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClients;
-import org.apache.http.util.EntityUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
-import org.springframework.transaction.PlatformTransactionManager;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
 import java.net.URLDecoder;
-import java.nio.charset.StandardCharsets;
 import java.time.Duration;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.Arrays;
-import java.util.List;
 import java.util.Map;
 
 @Slf4j
@@ -280,6 +236,7 @@ public class NewPayServiceImpl implements NewPayService {
                     case BALANCE_RECHARGE: handleBalanceRechargePaySuccess(payDetails); break;
                     case BOND_PAY: handleBondPaySuccess(payDetails); break;
                     case VIP_PAY: handleVipPaySuccess(payDetails); break;
+                    case LOVERS_SET_ORDER_PAY: handleLoversSetOrderPaySuccess(orderNo); break;
                     default:
                         log.error("监测到不支持的支付成功场景,支付订单信息:{}", JSONUtil.toJsonStr(payDetails));
                 }
@@ -299,6 +256,15 @@ public class NewPayServiceImpl implements NewPayService {
     }
 
     /**
+     * 处理情侣套餐订单支付成功通知
+     * @param orderNo 订单编号
+     */
+    private void handleLoversSetOrderPaySuccess(String orderNo) {
+        LoversSetOrderInfoService loversSetOrderInfoService = SpringContextUtils.getBean(LoversSetOrderInfoService.class);
+        loversSetOrderInfoService.updateOrderAfterPaySuccess(orderNo);
+    }
+
+    /**
      * 处理vip购买成功通知
      * @param payDetails
      */

+ 172 - 1
src/main/resources/mapper/lovers/LoversSetDao.xml

@@ -3,4 +3,175 @@
 
 <mapper namespace="com.sqx.modules.lovers.dao.LoversSetDao">
 
-</mapper>
+    <resultMap id="LoversSetVOMap" type="com.sqx.modules.lovers.vo.LoversSetVO">
+        <id column="id" property="id"/>
+        <result column="name" property="name"/>
+        <result column="sub_name" property="subName"/>
+        <result column="set_tag" property="setTag"/>
+        <result column="service_tag" property="serviceTag"/>
+        <result column="price" property="price"/>
+        <result column="original_price" property="originalPrice"/>
+        <result column="imgs" property="imgs"/>
+        <result column="set_type" property="setType"/>
+        <result column="suit_sex" property="suitSex"/>
+        <result column="rule_id" property="ruleId"/>
+        <result column="ruleName" property="ruleName"/>
+        <result column="ruleContent" property="ruleContent"/>
+        <result column="set_status" property="setStatus"/>
+        <result column="sub_order_generate_time" property="subOrderGenerateTime"/>
+        <result column="start_time" property="startTime"/>
+        <result column="end_time" property="endTime"/>
+        <result column="self_start_time" property="selfStartTime"/>
+        <result column="self_end_time" property="selfEndTime"/>
+
+        <!-- 内容列表映射 -->
+        <collection property="contentList" ofType="com.sqx.modules.lovers.vo.LoversSetContentVO">
+            <result column="contentId" property="contentId"/>
+            <result column="sort" property="sort"/>
+            <result column="content_name" property="contentName"/>
+
+            <!-- 详情列表映射 -->
+            <collection property="contentDetailList" ofType="com.sqx.modules.lovers.vo.LoversSetContentDetailVO">
+                <result column="content_detail_id" property="contentDetailId"/>
+                <result column="goods_id" property="goodsId"/>
+                <result column="goods_name" property="goodsName"/>
+                <result column="shop_id" property="shopId"/>
+                <result column="shop_name" property="shopName"/>
+                <result column="num" property="num"/>
+                <result column="detail_price" property="price"/>
+                <result column="detail_original_price" property="originalPrice"/>
+            </collection>
+        </collection>
+    </resultMap>
+
+    <select id="pages" resultMap="LoversSetVOMap">
+        SELECT
+            s.id,
+            s.name,
+            s.sub_name,
+            s.set_tag,
+            s.service_tag,
+            s.price,
+            s.original_price,
+            s.imgs,
+            s.set_type,
+            s.suit_sex,
+            s.rule_id,
+            r.name as ruleName,
+            r.content as ruleContent,
+            s.set_status,
+            s.sub_order_generate_time,
+            s.start_time,
+            s.end_time,
+            s.self_start_time,
+            s.self_end_time,
+            sc.id as contentId,
+            sc.sort,
+            sc.content_name as contentName,
+            scd.id as contentDetailId,
+            scd.goods_id,
+            scd.goods_name,
+            scd.shop_id,
+            scd.shop_name,
+            scd.num,
+            scd.detail_price,
+            scd.detail_original_price
+        FROM
+            lovers_set s
+            left join lovers_set_rule r on r.id = s.rule_id
+            left join lovers_set_content sc on sc.lovers_set_id = s.id
+            left join lovers_set_content_detail scd on scd.lovers_set_content_id = sc.id
+        WHERE
+            s.del_flag = 0
+            and sc.del_flag = 0
+            and scd.del_flag = 0
+        <if test="queryDTO.name != null and queryDTO.name != ''">
+            and s.name like concat('%', #{queryDTO.name}, '%')
+        </if>
+        <if test="queryDTO.setType != null and queryDTO.setType != ''">
+            and s.set_type = #{queryDTO.setType}
+        </if>
+        <if test="queryDTO.suitSex != null and queryDTO.suitSex != ''">
+            and s.suit_sex = #{queryDTO.suitSex}
+        </if>
+    </select>
+
+    <select id="listForApp" resultType="com.sqx.modules.lovers.vo.AppLoversSetShortVO">
+        SELECT
+            s.id,
+            s.name,
+            s.sub_name,
+            s.set_tag,
+            s.service_tag,
+            s.price,
+            s.original_price,
+            s.imgs,
+            s.set_type,
+            s.suit_sex,
+            s.rule_id,
+            s.set_status,
+            s.sub_order_generate_time,
+            s.start_time,
+            s.end_time,
+            s.self_start_time,
+            s.self_end_time
+        FROM
+            lovers_set s
+        WHERE
+            s.del_flag = 0
+            and s.set_status = 1
+        <if test="queryDTO.name != null and queryDTO.name != ''">
+            and s.name like concat('%', #{queryDTO.name}, '%')
+        </if>
+        <if test="queryDTO.setType != null and queryDTO.setType != ''">
+            and s.set_type = #{queryDTO.setType}
+        </if>
+        <if test="queryDTO.suitSex != null and queryDTO.suitSex != ''">
+            and s.suit_sex = #{queryDTO.suitSex}
+        </if>
+    </select>
+
+    <select id="getDetailById" resultMap="LoversSetVOMap">
+        SELECT
+        s.id,
+        s.name,
+        s.sub_name,
+        s.set_tag,
+        s.service_tag,
+        s.price,
+        s.original_price,
+        s.imgs,
+        s.set_type,
+        s.suit_sex,
+        s.rule_id,
+        r.name as ruleName,
+        r.content as ruleContent,
+        s.set_status,
+        s.sub_order_generate_time,
+        s.start_time,
+        s.end_time,
+        s.self_start_time,
+        s.self_end_time,
+        sc.id as contentId,
+        sc.sort,
+        sc.content_name as contentName,
+        scd.id as contentDetailId,
+        scd.goods_id,
+        scd.goods_name,
+        scd.shop_id,
+        scd.shop_name,
+        scd.num,
+        scd.detail_price,
+        scd.detail_original_price
+        FROM
+        lovers_set s
+        left join lovers_set_rule r on r.id = s.rule_id
+        left join lovers_set_content sc on sc.lovers_set_id = s.id
+        left join lovers_set_content_detail scd on scd.lovers_set_content_id = sc.id
+        WHERE
+            s.del_flag = 0
+            and s.id = #{id}
+            and sc.del_flag = 0
+            and scd.del_flag = 0
+    </select>
+</mapper>