Переглянути джерело

!522 mall seckill
Merge pull request !522 from puhui999/feature/mall_product

芋道源码 1 рік тому
батько
коміт
b16632ea41
100 змінених файлів з 1791 додано та 1354 видалено
  1. 106 21
      sql/dm/ruoyi-vue-pro-dm8.sql
  2. 106 21
      sql/mysql/ruoyi-vue-pro.sql
  3. 1 3
      yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/comment/ProductCommentApi.java
  4. 5 19
      yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/comment/dto/ProductCommentCreateReqDTO.java
  5. 9 1
      yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java
  6. 2 5
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/comment/ProductCommentApiImpl.java
  7. 9 0
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java
  8. 5 4
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java
  9. 2 3
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandSimpleRespVO.java
  10. 18 10
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentBaseVO.java
  11. 0 11
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentCreateReqVO.java
  12. 2 2
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentReplyReqVO.java
  13. 9 15
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentRespVO.java
  14. 2 2
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentUpdateVisibleReqVO.java
  15. 4 4
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java
  16. 1 2
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java
  17. 2 7
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java
  18. 37 56
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java
  19. 4 4
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppCommentStatisticsRespVO.java
  20. 10 10
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentCreateReqVO.java
  21. 17 17
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentRespVO.java
  22. 10 10
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageRespVO.java
  23. 15 2
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java
  24. 17 9
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java
  25. 15 3
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentService.java
  26. 40 44
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java
  27. 5 4
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
  28. 1 1
      yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java
  29. 19 69
      yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/create_tables.sql
  30. 2 0
      yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
  31. 99 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java
  32. 0 72
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillTimeController.java
  33. 24 28
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityBaseVO.java
  34. 9 20
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityCreateReqVO.java
  35. 12 7
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityDetailRespVO.java
  36. 1 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityPageReqVO.java
  37. 10 19
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java
  38. 10 18
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityUpdateReqVO.java
  39. 17 8
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigBaseVO.java
  40. 7 2
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigCreateReqVO.java
  41. 9 12
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigPageReqVO.java
  42. 12 3
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigRespVO.java
  43. 29 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigSimpleRespVO.java
  44. 7 2
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigUpdateReqVO.java
  45. 28 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigUpdateStatusReqVo.java
  46. 34 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductBaseVO.java
  47. 20 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductCreateReqVO.java
  48. 24 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductRespVO.java
  49. 22 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductUpdateReqVO.java
  50. 6 5
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/vo/AppActivityRespVO.java
  51. 11 11
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/activity/AppCombinationActivityDetailRespVO.java
  52. 10 7
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/activity/AppCombinationActivityRespVO.java
  53. 4 3
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/record/AppCombinationRecordDetailRespVO.java
  54. 11 11
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/record/AppCombinationRecordRespVO.java
  55. 2 2
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/record/AppCombinationRecordSummaryRespVO.java
  56. 9 8
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/template/AppCouponTemplateRespVO.java
  57. 12 12
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillActivityDetailRespVO.java
  58. 2 2
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillActivityNowRespVO.java
  59. 11 8
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillActivityRespVO.java
  60. 4 4
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/config/AppSeckillConfigRespVO.java
  61. 31 23
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java
  62. 36 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillconfig/SeckillConfigConvert.java
  63. 0 34
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckilltime/SeckillTimeConvert.java
  64. 25 4
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillActivityDO.java
  65. 32 25
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillProductDO.java
  66. 15 10
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillconfig/SeckillConfigDO.java
  67. 8 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java
  68. 1 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java
  69. 20 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillconfig/SeckillConfigMapper.java
  70. 0 32
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckilltime/SeckillTimeMapper.java
  71. 2 2
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java
  72. 2 2
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
  73. 6 4
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityService.java
  74. 102 91
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java
  75. 87 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigService.java
  76. 154 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigServiceImpl.java
  77. 0 76
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckilltime/SeckillTimeService.java
  78. 0 124
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckilltime/SeckillTimeServiceImpl.java
  79. 3 10
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/util/PromotionUtils.java
  80. 23 23
      yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckillactivity/SeckillActivityServiceImplTest.java
  81. 190 0
      yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckillconfig/SeckillConfigServiceImplTest.java
  82. 0 190
      yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckilltime/SeckillTimeServiceImplTest.java
  83. 1 0
      yudao-module-mall/yudao-module-promotion-biz/src/test/resources/sql/clean.sql
  84. 42 15
      yudao-module-mall/yudao-module-promotion-biz/src/test/resources/sql/create_tables.sql
  85. 4 4
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressBaseVO.java
  86. 6 3
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressRespVO.java
  87. 1 1
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressUpdateReqVO.java
  88. 3 3
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateBaseVO.java
  89. 6 3
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateRespVO.java
  90. 2 2
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateSimpleRespVO.java
  91. 1 1
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateUpdateReqVO.java
  92. 10 10
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/pickup/DeliveryPickUpStoreBaseVO.java
  93. 6 3
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/pickup/DeliveryPickUpStoreRespVO.java
  94. 6 4
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/pickup/DeliveryPickUpStoreUpdateReqVO.java
  95. 1 1
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleCreateReqVO.java
  96. 16 16
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSalePageItemRespVO.java
  97. 1 1
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartAddReqVO.java
  98. 2 2
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartListRespVO.java
  99. 2 2
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartUpdateReqVO.java
  100. 13 7
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java

+ 106 - 21
sql/dm/ruoyi-vue-pro-dm8.sql

@@ -1797,27 +1797,112 @@ INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT"
 INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2046,'满减送活动关闭','promotion:reward-activity:close',3,5,2041,'','','',null,0,1,1,1,'1','2022-11-05 10:42:53','1','2022-11-05 10:42:53',0);
 INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2047,'限时折扣活动','',2,7,2030,'discount-activity','time','mall/promotion/discountActivity/index','PromotionDiscountActivity',0,1,1,1,'','2022-11-05 17:12:15','1','2023-04-08 11:45:44',0);
 INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2048,'限时折扣活动查询','promotion:discount-activity:query',3,1,2047,'','','',null,0,1,1,1,'','2022-11-05 17:12:15','','2022-11-05 17:12:15',0);
-INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2049,'限时折扣活动创建','promotion:discount-activity:create',3,2,2047,'','','',null,0,1,1,1,'','2022-11-05 17:12:15','','2022-11-05 17:12:15',0);
-INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2050,'限时折扣活动更新','promotion:discount-activity:update',3,3,2047,'','','',null,0,1,1,1,'','2022-11-05 17:12:16','','2022-11-05 17:12:16',0);
-INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2051,'限时折扣活动删除','promotion:discount-activity:delete',3,4,2047,'','','',null,0,1,1,1,'','2022-11-05 17:12:16','','2022-11-05 17:12:16',0);
-INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2052,'限时折扣活动关闭','promotion:discount-activity:close',3,5,2047,'','','',null,0,1,1,1,'','2022-11-05 17:12:16','','2022-11-05 17:12:16',0);
-INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2059,'秒杀活动管理','',2,0,2030,'seckill-activity','time-range','mall/promotion/seckill/seckillActivity/index','PromotionSeckillActivity',0,1,1,1,'','2022-11-06 22:24:49','1','2023-04-08 11:46:02',0);
-INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2060,'秒杀活动查询','promotion:seckill-activity:query',3,1,2059,'','','',null,0,1,1,1,'','2022-11-06 22:24:49','','2022-11-06 22:24:49',0);
-INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2061,'秒杀活动创建','promotion:seckill-activity:create',3,2,2059,'','','',null,0,1,1,1,'','2022-11-06 22:24:49','','2022-11-06 22:24:49',0);
-INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2062,'秒杀活动更新','promotion:seckill-activity:update',3,3,2059,'','','',null,0,1,1,1,'','2022-11-06 22:24:49','','2022-11-06 22:24:49',0);
-INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2063,'秒杀活动删除','promotion:seckill-activity:delete',3,4,2059,'','','',null,0,1,1,1,'','2022-11-06 22:24:49','','2022-11-06 22:24:49',0);
-INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2064,'秒杀活动导出','promotion:seckill-activity:export',3,5,2059,'','','',null,0,1,1,1,'','2022-11-06 22:24:49','','2022-11-06 22:24:49',0);
-INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2066,'秒杀时段管理','',2,0,2030,'seckill-time','','mall/promotion/seckill/seckillTime/index','PromotionSeckillTime',0,0,1,1,'','2022-11-15 19:46:50','1','2023-04-08 11:46:17',0);
-INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2067,'秒杀时段查询','promotion:seckill-time:query',3,1,2066,'','','',null,0,1,1,1,'','2022-11-15 19:46:51','','2022-11-15 19:46:51',0);
-INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2068,'秒杀时段创建','promotion:seckill-time:create',3,2,2066,'','','',null,0,1,1,1,'','2022-11-15 19:46:51','','2022-11-15 19:46:51',0);
-INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2069,'秒杀时段更新','promotion:seckill-time:update',3,3,2066,'','','',null,0,1,1,1,'','2022-11-15 19:46:51','','2022-11-15 19:46:51',0);
-INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2070,'秒杀时段删除','promotion:seckill-time:delete',3,4,2066,'','','',null,0,1,1,1,'','2022-11-15 19:46:51','','2022-11-15 19:46:51',0);
-INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2071,'秒杀时段导出','promotion:seckill-time:export',3,5,2066,'','','',null,0,1,1,1,'','2022-11-15 19:46:51','','2022-11-15 19:46:51',0);
-INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2072,'订单中心','',1,65,0,'/trade','order',null,null,0,1,1,1,'1','2022-11-19 18:57:19','1','2022-12-10 16:32:57',0);
-INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2073,'售后退款','',2,1,2072,'trade/after-sale','education','mall/trade/afterSale/index','TradeAfterSale',0,1,1,1,'','2022-11-19 20:15:32','1','2023-04-08 11:43:19',0);
-INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2074,'售后查询','trade:after-sale:query',3,1,2073,'','','',null,0,1,1,1,'','2022-11-19 20:15:33','1','2022-12-10 21:04:29',0);
-INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2075,'秒杀活动关闭','promotion:sekill-activity:close',3,6,2059,'','','',null,0,1,1,1,'1','2022-11-28 20:20:15','1','2022-11-28 20:20:15',0);
-INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2076,'订单列表','',2,0,2072,'trade/order','list','mall/trade/order/index','TradeOrder',0,1,1,1,'1','2022-12-10 21:05:44','1','2023-04-08 11:42:23',0);
+INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
+                                          "COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
+                                          "ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
+VALUES (2049, '限时折扣活动创建', 'promotion:discount-activity:create', 3, 2, 2047, '', '', '', null, 0, 1, 1, 1, '',
+        '2022-11-05 17:12:15', '', '2022-11-05 17:12:15', 0);
+INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
+                                          "COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
+                                          "ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
+VALUES (2050, '限时折扣活动更新', 'promotion:discount-activity:update', 3, 3, 2047, '', '', '', null, 0, 1, 1, 1, '',
+        '2022-11-05 17:12:16', '', '2022-11-05 17:12:16', 0);
+INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
+                                          "COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
+                                          "ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
+VALUES (2051, '限时折扣活动删除', 'promotion:discount-activity:delete', 3, 4, 2047, '', '', '', null, 0, 1, 1, 1, '',
+        '2022-11-05 17:12:16', '', '2022-11-05 17:12:16', 0);
+INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
+                                          "COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
+                                          "ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
+VALUES (2052, '限时折扣活动关闭', 'promotion:discount-activity:close', 3, 5, 2047, '', '', '', null, 0, 1, 1, 1, '',
+        '2022-11-05 17:12:16', '', '2022-11-05 17:12:16', 0);
+INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
+                                          "COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
+                                          "ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
+VALUES (2059, '秒杀活动管理', '', 2, 0, 2030, 'seckill-activity', 'time-range',
+        'mall/promotion/seckill/seckillActivity/index', 'PromotionSeckillActivity', 0, 1, 1, 1, '',
+        '2022-11-06 22:24:49', '1', '2023-04-08 11:46:02', 0);
+INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
+                                          "COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
+                                          "ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
+VALUES (2060, '秒杀活动查询', 'promotion:seckill-activity:query', 3, 1, 2059, '', '', '', null, 0, 1, 1, 1, '',
+        '2022-11-06 22:24:49', '', '2022-11-06 22:24:49', 0);
+INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
+                                          "COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
+                                          "ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
+VALUES (2061, '秒杀活动创建', 'promotion:seckill-activity:create', 3, 2, 2059, '', '', '', null, 0, 1, 1, 1, '',
+        '2022-11-06 22:24:49', '', '2022-11-06 22:24:49', 0);
+INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
+                                          "COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
+                                          "ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
+VALUES (2062, '秒杀活动更新', 'promotion:seckill-activity:update', 3, 3, 2059, '', '', '', null, 0, 1, 1, 1, '',
+        '2022-11-06 22:24:49', '', '2022-11-06 22:24:49', 0);
+INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
+                                          "COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
+                                          "ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
+VALUES (2063, '秒杀活动删除', 'promotion:seckill-activity:delete', 3, 4, 2059, '', '', '', null, 0, 1, 1, 1, '',
+        '2022-11-06 22:24:49', '', '2022-11-06 22:24:49', 0);
+INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
+                                          "COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
+                                          "ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
+VALUES (2064, '秒杀活动导出', 'promotion:seckill-activity:export', 3, 5, 2059, '', '', '', null, 0, 1, 1, 1, '',
+        '2022-11-06 22:24:49', '', '2022-11-06 22:24:49', 0);
+INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
+                                          "COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
+                                          "ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
+VALUES (2066, '秒杀时段管理', '', 2, 0, 2030, 'seckill-time', '', 'mall/promotion/seckill/SeckillConfig/index',
+        'PromotionSeckillConfig', 0, 0, 1, 1, '', '2022-11-15 19:46:50', '1', '2023-04-08 11:46:17', 0);
+INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
+                                          "COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
+                                          "ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
+VALUES (2067, '秒杀时段查询', 'promotion:seckill-time:query', 3, 1, 2066, '', '', '', null, 0, 1, 1, 1, '',
+        '2022-11-15 19:46:51', '', '2022-11-15 19:46:51', 0);
+INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
+                                          "COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
+                                          "ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
+VALUES (2068, '秒杀时段创建', 'promotion:seckill-time:create', 3, 2, 2066, '', '', '', null, 0, 1, 1, 1, '',
+        '2022-11-15 19:46:51', '', '2022-11-15 19:46:51', 0);
+INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
+                                          "COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
+                                          "ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
+VALUES (2069, '秒杀时段更新', 'promotion:seckill-time:update', 3, 3, 2066, '', '', '', null, 0, 1, 1, 1, '',
+        '2022-11-15 19:46:51', '', '2022-11-15 19:46:51', 0);
+INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
+                                          "COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
+                                          "ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
+VALUES (2070, '秒杀时段删除', 'promotion:seckill-time:delete', 3, 4, 2066, '', '', '', null, 0, 1, 1, 1, '',
+        '2022-11-15 19:46:51', '', '2022-11-15 19:46:51', 0);
+INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
+                                          "COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
+                                          "ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
+VALUES (2071, '秒杀时段导出', 'promotion:seckill-time:export', 3, 5, 2066, '', '', '', null, 0, 1, 1, 1, '',
+        '2022-11-15 19:46:51', '', '2022-11-15 19:46:51', 0);
+INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
+                                          "COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
+                                          "ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
+VALUES (2072, '订单中心', '', 1, 65, 0, '/trade', 'order', null, null, 0, 1, 1, 1, '1', '2022-11-19 18:57:19', '1',
+        '2022-12-10 16:32:57', 0);
+INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
+                                          "COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
+                                          "ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
+VALUES (2073, '售后退款', '', 2, 1, 2072, 'trade/after-sale', 'education', 'mall/trade/afterSale/index',
+        'TradeAfterSale', 0, 1, 1, 1, '', '2022-11-19 20:15:32', '1', '2023-04-08 11:43:19', 0);
+INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
+                                          "COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
+                                          "ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
+VALUES (2074, '售后查询', 'trade:after-sale:query', 3, 1, 2073, '', '', '', null, 0, 1, 1, 1, '', '2022-11-19 20:15:33',
+        '1', '2022-12-10 21:04:29', 0);
+INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
+                                          "COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
+                                          "ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
+VALUES (2075, '秒杀活动关闭', 'promotion:sekill-activity:close', 3, 6, 2059, '', '', '', null, 0, 1, 1, 1, '1',
+        '2022-11-28 20:20:15', '1', '2022-11-28 20:20:15', 0);
+INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
+                                          "COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
+                                          "ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
+VALUES (2076, '订单列表', '', 2, 0, 2072, 'trade/order', 'list', 'mall/trade/order/index', 'TradeOrder', 0, 1, 1, 1,
+        '1', '2022-12-10 21:05:44', '1', '2023-04-08 11:42:23', 0);
 INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2077,'物流公司管理管理','',2,0,2072,'express-company','','mall/trade/expressCompany/index',null,0,1,1,1,'','2022-12-20 23:27:55','1','2022-12-20 23:36:20',0);
 INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2078,'物流公司管理查询','trade:express-company:query',3,1,2077,'','','',null,0,1,1,1,'','2022-12-20 23:27:55','','2022-12-20 23:27:55',0);
 INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2079,'物流公司管理创建','trade:express-company:create',3,2,2077,'','','',null,0,1,1,1,'','2022-12-20 23:27:55','','2022-12-20 23:27:55',0);

+ 106 - 21
sql/mysql/ruoyi-vue-pro.sql

@@ -1980,27 +1980,112 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i
 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2046, '满减送活动关闭', 'promotion:reward-activity:close', 3, 5, 2041, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2022-11-05 10:42:53', '1', '2022-11-05 10:42:53', b'0');
 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2047, '限时折扣活动', '', 2, 7, 2030, 'discount-activity', 'time', 'mall/promotion/discountActivity/index', 'PromotionDiscountActivity', 0, b'1', b'1', b'1', '', '2022-11-05 17:12:15', '1', '2023-04-08 11:45:44', b'0');
 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2048, '限时折扣活动查询', 'promotion:discount-activity:query', 3, 1, 2047, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-05 17:12:15', '', '2022-11-05 17:12:15', b'0');
-INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2049, '限时折扣活动创建', 'promotion:discount-activity:create', 3, 2, 2047, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-05 17:12:15', '', '2022-11-05 17:12:15', b'0');
-INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2050, '限时折扣活动更新', 'promotion:discount-activity:update', 3, 3, 2047, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-05 17:12:16', '', '2022-11-05 17:12:16', b'0');
-INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2051, '限时折扣活动删除', 'promotion:discount-activity:delete', 3, 4, 2047, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-05 17:12:16', '', '2022-11-05 17:12:16', b'0');
-INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2052, '限时折扣活动关闭', 'promotion:discount-activity:close', 3, 5, 2047, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-05 17:12:16', '', '2022-11-05 17:12:16', b'0');
-INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2059, '秒杀活动管理', '', 2, 0, 2030, 'seckill-activity', 'time-range', 'mall/promotion/seckill/seckillActivity/index', 'PromotionSeckillActivity', 0, b'1', b'1', b'1', '', '2022-11-06 22:24:49', '1', '2023-04-08 11:46:02', b'0');
-INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2060, '秒杀活动查询', 'promotion:seckill-activity:query', 3, 1, 2059, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-06 22:24:49', '', '2022-11-06 22:24:49', b'0');
-INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2061, '秒杀活动创建', 'promotion:seckill-activity:create', 3, 2, 2059, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-06 22:24:49', '', '2022-11-06 22:24:49', b'0');
-INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2062, '秒杀活动更新', 'promotion:seckill-activity:update', 3, 3, 2059, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-06 22:24:49', '', '2022-11-06 22:24:49', b'0');
-INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2063, '秒杀活动删除', 'promotion:seckill-activity:delete', 3, 4, 2059, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-06 22:24:49', '', '2022-11-06 22:24:49', b'0');
-INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2064, '秒杀活动导出', 'promotion:seckill-activity:export', 3, 5, 2059, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-06 22:24:49', '', '2022-11-06 22:24:49', b'0');
-INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2066, '秒杀时段管理', '', 2, 0, 2030, 'seckill-time', '', 'mall/promotion/seckill/seckillTime/index', 'PromotionSeckillTime', 0, b'0', b'1', b'1', '', '2022-11-15 19:46:50', '1', '2023-04-08 11:46:17', b'0');
-INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2067, '秒杀时段查询', 'promotion:seckill-time:query', 3, 1, 2066, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-15 19:46:51', '', '2022-11-15 19:46:51', b'0');
-INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2068, '秒杀时段创建', 'promotion:seckill-time:create', 3, 2, 2066, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-15 19:46:51', '', '2022-11-15 19:46:51', b'0');
-INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2069, '秒杀时段更新', 'promotion:seckill-time:update', 3, 3, 2066, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-15 19:46:51', '', '2022-11-15 19:46:51', b'0');
-INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2070, '秒杀时段删除', 'promotion:seckill-time:delete', 3, 4, 2066, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-15 19:46:51', '', '2022-11-15 19:46:51', b'0');
-INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2071, '秒杀时段导出', 'promotion:seckill-time:export', 3, 5, 2066, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-15 19:46:51', '', '2022-11-15 19:46:51', b'0');
-INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2072, '订单中心', '', 1, 65, 0, '/trade', 'order', NULL, NULL, 0, b'1', b'1', b'1', '1', '2022-11-19 18:57:19', '1', '2022-12-10 16:32:57', b'0');
-INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2073, '售后退款', '', 2, 1, 2072, 'trade/after-sale', 'education', 'mall/trade/afterSale/index', 'TradeAfterSale', 0, b'1', b'1', b'1', '', '2022-11-19 20:15:32', '1', '2023-04-08 11:43:19', b'0');
-INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2074, '售后查询', 'trade:after-sale:query', 3, 1, 2073, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-19 20:15:33', '1', '2022-12-10 21:04:29', b'0');
-INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2075, '秒杀活动关闭', 'promotion:sekill-activity:close', 3, 6, 2059, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2022-11-28 20:20:15', '1', '2022-11-28 20:20:15', b'0');
-INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2076, '订单列表', '', 2, 0, 2072, 'trade/order', 'list', 'mall/trade/order/index', 'TradeOrder', 0, b'1', b'1', b'1', '1', '2022-12-10 21:05:44', '1', '2023-04-08 11:42:23', b'0');
+INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`,
+                           `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`,
+                           `updater`, `update_time`, `deleted`)
+VALUES (2049, '限时折扣活动创建', 'promotion:discount-activity:create', 3, 2, 2047, '', '', '', NULL, 0, b'1', b'1',
+        b'1', '', '2022-11-05 17:12:15', '', '2022-11-05 17:12:15', b'0');
+INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`,
+                           `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`,
+                           `updater`, `update_time`, `deleted`)
+VALUES (2050, '限时折扣活动更新', 'promotion:discount-activity:update', 3, 3, 2047, '', '', '', NULL, 0, b'1', b'1',
+        b'1', '', '2022-11-05 17:12:16', '', '2022-11-05 17:12:16', b'0');
+INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`,
+                           `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`,
+                           `updater`, `update_time`, `deleted`)
+VALUES (2051, '限时折扣活动删除', 'promotion:discount-activity:delete', 3, 4, 2047, '', '', '', NULL, 0, b'1', b'1',
+        b'1', '', '2022-11-05 17:12:16', '', '2022-11-05 17:12:16', b'0');
+INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`,
+                           `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`,
+                           `updater`, `update_time`, `deleted`)
+VALUES (2052, '限时折扣活动关闭', 'promotion:discount-activity:close', 3, 5, 2047, '', '', '', NULL, 0, b'1', b'1',
+        b'1', '', '2022-11-05 17:12:16', '', '2022-11-05 17:12:16', b'0');
+INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`,
+                           `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`,
+                           `updater`, `update_time`, `deleted`)
+VALUES (2059, '秒杀活动管理', '', 2, 0, 2030, 'seckill-activity', 'time-range',
+        'mall/promotion/seckill/seckillActivity/index', 'PromotionSeckillActivity', 0, b'1', b'1', b'1', '',
+        '2022-11-06 22:24:49', '1', '2023-04-08 11:46:02', b'0');
+INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`,
+                           `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`,
+                           `updater`, `update_time`, `deleted`)
+VALUES (2060, '秒杀活动查询', 'promotion:seckill-activity:query', 3, 1, 2059, '', '', '', NULL, 0, b'1', b'1', b'1', '',
+        '2022-11-06 22:24:49', '', '2022-11-06 22:24:49', b'0');
+INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`,
+                           `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`,
+                           `updater`, `update_time`, `deleted`)
+VALUES (2061, '秒杀活动创建', 'promotion:seckill-activity:create', 3, 2, 2059, '', '', '', NULL, 0, b'1', b'1', b'1',
+        '', '2022-11-06 22:24:49', '', '2022-11-06 22:24:49', b'0');
+INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`,
+                           `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`,
+                           `updater`, `update_time`, `deleted`)
+VALUES (2062, '秒杀活动更新', 'promotion:seckill-activity:update', 3, 3, 2059, '', '', '', NULL, 0, b'1', b'1', b'1',
+        '', '2022-11-06 22:24:49', '', '2022-11-06 22:24:49', b'0');
+INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`,
+                           `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`,
+                           `updater`, `update_time`, `deleted`)
+VALUES (2063, '秒杀活动删除', 'promotion:seckill-activity:delete', 3, 4, 2059, '', '', '', NULL, 0, b'1', b'1', b'1',
+        '', '2022-11-06 22:24:49', '', '2022-11-06 22:24:49', b'0');
+INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`,
+                           `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`,
+                           `updater`, `update_time`, `deleted`)
+VALUES (2064, '秒杀活动导出', 'promotion:seckill-activity:export', 3, 5, 2059, '', '', '', NULL, 0, b'1', b'1', b'1',
+        '', '2022-11-06 22:24:49', '', '2022-11-06 22:24:49', b'0');
+INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`,
+                           `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`,
+                           `updater`, `update_time`, `deleted`)
+VALUES (2066, '秒杀时段管理', '', 2, 0, 2030, 'seckill-time', '', 'mall/promotion/seckill/SeckillConfig/index',
+        'PromotionSeckillConfig', 0, b'0', b'1', b'1', '', '2022-11-15 19:46:50', '1', '2023-04-08 11:46:17', b'0');
+INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`,
+                           `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`,
+                           `updater`, `update_time`, `deleted`)
+VALUES (2067, '秒杀时段查询', 'promotion:seckill-time:query', 3, 1, 2066, '', '', '', NULL, 0, b'1', b'1', b'1', '',
+        '2022-11-15 19:46:51', '', '2022-11-15 19:46:51', b'0');
+INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`,
+                           `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`,
+                           `updater`, `update_time`, `deleted`)
+VALUES (2068, '秒杀时段创建', 'promotion:seckill-time:create', 3, 2, 2066, '', '', '', NULL, 0, b'1', b'1', b'1', '',
+        '2022-11-15 19:46:51', '', '2022-11-15 19:46:51', b'0');
+INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`,
+                           `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`,
+                           `updater`, `update_time`, `deleted`)
+VALUES (2069, '秒杀时段更新', 'promotion:seckill-time:update', 3, 3, 2066, '', '', '', NULL, 0, b'1', b'1', b'1', '',
+        '2022-11-15 19:46:51', '', '2022-11-15 19:46:51', b'0');
+INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`,
+                           `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`,
+                           `updater`, `update_time`, `deleted`)
+VALUES (2070, '秒杀时段删除', 'promotion:seckill-time:delete', 3, 4, 2066, '', '', '', NULL, 0, b'1', b'1', b'1', '',
+        '2022-11-15 19:46:51', '', '2022-11-15 19:46:51', b'0');
+INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`,
+                           `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`,
+                           `updater`, `update_time`, `deleted`)
+VALUES (2071, '秒杀时段导出', 'promotion:seckill-time:export', 3, 5, 2066, '', '', '', NULL, 0, b'1', b'1', b'1', '',
+        '2022-11-15 19:46:51', '', '2022-11-15 19:46:51', b'0');
+INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`,
+                           `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`,
+                           `updater`, `update_time`, `deleted`)
+VALUES (2072, '订单中心', '', 1, 65, 0, '/trade', 'order', NULL, NULL, 0, b'1', b'1', b'1', '1', '2022-11-19 18:57:19',
+        '1', '2022-12-10 16:32:57', b'0');
+INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`,
+                           `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`,
+                           `updater`, `update_time`, `deleted`)
+VALUES (2073, '售后退款', '', 2, 1, 2072, 'trade/after-sale', 'education', 'mall/trade/afterSale/index',
+        'TradeAfterSale', 0, b'1', b'1', b'1', '', '2022-11-19 20:15:32', '1', '2023-04-08 11:43:19', b'0');
+INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`,
+                           `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`,
+                           `updater`, `update_time`, `deleted`)
+VALUES (2074, '售后查询', 'trade:after-sale:query', 3, 1, 2073, '', '', '', NULL, 0, b'1', b'1', b'1', '',
+        '2022-11-19 20:15:33', '1', '2022-12-10 21:04:29', b'0');
+INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`,
+                           `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`,
+                           `updater`, `update_time`, `deleted`)
+VALUES (2075, '秒杀活动关闭', 'promotion:sekill-activity:close', 3, 6, 2059, '', '', '', NULL, 0, b'1', b'1', b'1', '1',
+        '2022-11-28 20:20:15', '1', '2022-11-28 20:20:15', b'0');
+INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`,
+                           `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`,
+                           `updater`, `update_time`, `deleted`)
+VALUES (2076, '订单列表', '', 2, 0, 2072, 'trade/order', 'list', 'mall/trade/order/index', 'TradeOrder', 0, b'1', b'1',
+        b'1', '1', '2022-12-10 21:05:44', '1', '2023-04-08 11:42:23', b'0');
 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2077, '物流公司管理管理', '', 2, 0, 2072, 'express-company', '', 'mall/trade/expressCompany/index', NULL, 0, b'1', b'1', b'1', '', '2022-12-20 23:27:55', '1', '2022-12-20 23:36:20', b'0');
 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2078, '物流公司管理查询', 'trade:express-company:query', 3, 1, 2077, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-12-20 23:27:55', '', '2022-12-20 23:27:55', b'0');
 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2079, '物流公司管理创建', 'trade:express-company:create', 3, 2, 2077, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-12-20 23:27:55', '', '2022-12-20 23:27:55', b'0');

+ 1 - 3
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/comment/ProductCommentApi.java

@@ -9,14 +9,12 @@ import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDT
  */
 public interface ProductCommentApi {
 
-    // TODO @puhui:Long orderId 放到 createReqDTO 里噶?
     /**
      * 创建评论
      *
      * @param createReqDTO 评论参数
-     * @param orderId      订单 id
      * @return 返回评论创建后的 id
      */
-    Long createComment(ProductCommentCreateReqDTO createReqDTO, Long orderId);
+    Long createComment(ProductCommentCreateReqDTO createReqDTO);
 
 }

+ 5 - 19
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/comment/dto/ProductCommentCreateReqDTO.java

@@ -17,19 +17,13 @@ public class ProductCommentCreateReqDTO {
      */
     private Long skuId;
     /**
-     * 交易订单项编号
-     */
-    private Long orderItemId;
-
-    // TODO @huihui:spuId、spuName 去查询哇?通过 skuId
-    /**
-     * 商品 SPU 编号
+     * 订单编号
      */
-    private Long spuId;
+    private Long orderId;
     /**
-     * 商品 SPU 名称
+     * 交易订单项编号
      */
-    private String spuName;
+    private Long orderItemId;
 
     /**
      * 评分星级 1-5 分
@@ -60,14 +54,6 @@ public class ProductCommentCreateReqDTO {
      * 评价人
      */
     private Long userId;
-    // TODO @puhui999:是不是 userNickname、userAvatar 去掉?通过 userId 查询
-    /**
-     * 评价人名称
-     */
-    private String userNickname;
-    /**
-     * 评价人头像
-     */
-    private String userAvatar;
+
 
 }

+ 9 - 1
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java

@@ -1,7 +1,7 @@
 package cn.iocoder.yudao.module.product.api.sku;
 
-import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
+import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
 
 import java.util.Collection;
 import java.util.List;
@@ -30,6 +30,14 @@ public interface ProductSkuApi {
      */
     List<ProductSkuRespDTO> getSkuList(Collection<Long> ids);
 
+    /**
+     * 批量查询 SKU 数组
+     *
+     * @param spuIds SPU 编号列表
+     * @return SKU 数组
+     */
+    List<ProductSkuRespDTO> getSkuListBySpuId(List<Long> spuIds);
+
     /**
      * 更新 SKU 库存
      *

+ 2 - 5
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/comment/ProductCommentApiImpl.java

@@ -1,8 +1,6 @@
 package cn.iocoder.yudao.module.product.api.comment;
 
 import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
-import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert;
-import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
 import cn.iocoder.yudao.module.product.service.comment.ProductCommentService;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
@@ -22,9 +20,8 @@ public class ProductCommentApiImpl implements ProductCommentApi {
     private ProductCommentService productCommentService;
 
     @Override
-    public Long createComment(ProductCommentCreateReqDTO createReqDTO, Long orderId) {
-        ProductCommentDO commentDO = ProductCommentConvert.INSTANCE.convert(createReqDTO, orderId);
-        return productCommentService.createComment(commentDO);
+    public Long createComment(ProductCommentCreateReqDTO createReqDTO) {
+        return productCommentService.createComment(createReqDTO);
     }
 
 }

+ 9 - 0
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java

@@ -42,6 +42,15 @@ public class ProductSkuApiImpl implements ProductSkuApi {
         return ProductSkuConvert.INSTANCE.convertList04(skus);
     }
 
+    @Override
+    public List<ProductSkuRespDTO> getSkuListBySpuId(List<Long> spuIds) {
+        if (CollUtil.isEmpty(spuIds)) {
+            return Collections.emptyList();
+        }
+        List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spuIds);
+        return ProductSkuConvert.INSTANCE.convertList04(skus);
+    }
+
     @Override
     public void updateSkuStock(ProductSkuUpdateStockReqDTO updateStockReqDTO) {
         productSkuService.updateSkuStock(updateStockReqDTO);

+ 5 - 4
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java

@@ -1,6 +1,6 @@
 package cn.iocoder.yudao.module.product.api.spu;
 
-import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.hutool.core.collection.CollectionUtil;
 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
 import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
@@ -14,7 +14,7 @@ import java.util.Collections;
 import java.util.List;
 
 /**
- * TODO LeeYan9: 类注释;
+ * 商品 SPU API 接口实现类
  *
  * @author LeeYan9
  * @since 2022-09-06
@@ -28,11 +28,12 @@ public class ProductSpuApiImpl implements ProductSpuApi {
 
     @Override
     public List<ProductSpuRespDTO> getSpuList(Collection<Long> spuIds) {
-        // TODO TODO LeeYan9: AllEmpty?
-        if (CollectionUtils.isAnyEmpty(spuIds)) {
+        // TODO 需不需要判断集合中是否有 null 值
+        if (CollectionUtil.isEmpty(spuIds)) {
             return Collections.emptyList();
         }
         List<ProductSpuDO> productSpuDOList = productSpuMapper.selectBatchIds(spuIds);
         return ProductSpuConvert.INSTANCE.convertList2(productSpuDOList);
     }
+
 }

+ 2 - 3
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandSimpleRespVO.java

@@ -5,17 +5,16 @@ import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
-// TODO @puhui999:class 类的开始和结束,都要有一个空行哈。
 @Schema(description = "管理后台 - 品牌精简信息 Response VO")
 @Data
 @NoArgsConstructor
 @AllArgsConstructor
 public class ProductBrandSimpleRespVO {
 
-    @Schema(description = "品牌编号", required = true, example = "1024")
+    @Schema(description = "品牌编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Long id;
 
-    @Schema(description = "品牌名称", required = true, example = "苹果")
+    @Schema(description = "品牌名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "苹果")
     private String name;
 
 }

+ 18 - 10
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentBaseVO.java

@@ -10,43 +10,51 @@ import java.util.List;
 @Data
 public class ProductCommentBaseVO {
 
-    @Schema(description = "评价人名称", required = true, example = "小姑凉")
+    @Schema(description = "评价人", requiredMode = Schema.RequiredMode.REQUIRED, example = "16868")
+    @NotNull(message = "评价人不能为空")
+    private Long userId;
+
+    @Schema(description = "评价订单项", requiredMode = Schema.RequiredMode.REQUIRED, example = "19292")
+    @NotNull(message = "评价订单项不能为空")
+    private Long orderItemId;
+
+    @Schema(description = "评价人名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小姑凉")
     @NotNull(message = "评价人名称不能为空")
     private String userNickname;
 
-    @Schema(description = "评价人头像", required = true, example = "https://www.iocoder.cn/xx.png")
+    @Schema(description = "评价人头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png")
     @NotNull(message = "评价人头像不能为空")
     private String userAvatar;
 
-    @Schema(description = "商品 SPU 编号", required = true, example = "清凉丝滑透气小短袖")
+    @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑透气小短袖")
     @NotNull(message = "商品 SPU 编号不能为空")
     private Long spuId;
 
-    @Schema(description = "商品 SPU 名称", required = true, example = "赵六")
+    @Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
     @NotNull(message = "商品 SPU 名称不能为空")
     private String spuName;
 
-    @Schema(description = "商品 SKU 编号", required = true, example = "1")
+    @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "商品 SKU 编号不能为空")
     private Long skuId;
 
-    @Schema(description = "评分星级 1-5 分", required = true, example = "5")
+    @Schema(description = "评分星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
     @NotNull(message = "评分星级不能为空")
     private Integer scores;
 
-    @Schema(description = "描述星级 1-5 分", required = true, example = "5")
+    @Schema(description = "描述星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
     @NotNull(message = "描述星级不能为空")
     private Integer descriptionScores;
 
-    @Schema(description = "服务星级 1-5 分", required = true, example = "5")
+    @Schema(description = "服务星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
     @NotNull(message = "服务星级分不能为空")
     private Integer benefitScores;
 
-    @Schema(description = "评论内容", required = true, example = "穿起来非常丝滑凉快")
+    @Schema(description = "评论内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "穿起来非常丝滑凉快")
     @NotNull(message = "评论内容不能为空")
     private String content;
 
-    @Schema(description = "评论图片地址数组,以逗号分隔最多上传 9 张", required = true, example = "[https://www.iocoder.cn/xx.png, https://www.iocoder.cn/xxx.png]")
+    @Schema(description = "评论图片地址数组,以逗号分隔最多上传 9 张", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/xx.png, https://www.iocoder.cn/xxx.png]")
     @Size(max = 9, message = "评论图片地址数组长度不能超过 9 张")
     private List<String> picUrls;
 

+ 0 - 11
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentCreateReqVO.java

@@ -5,21 +5,10 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.ToString;
 
-import javax.validation.constraints.NotNull;
-
 @Schema(description = "管理后台 - 商品评价创建 Request VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
 public class ProductCommentCreateReqVO extends ProductCommentBaseVO {
 
-    // TODO @puhui999:是不是也放到父类里?
-    @Schema(description = "评价人", required = true, example = "16868")
-    @NotNull(message = "评价人不能为空")
-    private Long userId;
-
-    @Schema(description = "评价订单项", required = true, example = "19292")
-    @NotNull(message = "评价订单项不能为空")
-    private Long orderItemId;
-
 }

+ 2 - 2
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentReplyReqVO.java

@@ -12,11 +12,11 @@ import javax.validation.constraints.NotNull;
 @ToString(callSuper = true)
 public class ProductCommentReplyReqVO {
 
-    @Schema(description = "评价编号", required = true, example = "15721")
+    @Schema(description = "评价编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15721")
     @NotNull(message = "评价编号不能为空")
     private Long id;
 
-    @Schema(description = "商家回复内容", required = true, example = "谢谢亲")
+    @Schema(description = "商家回复内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "谢谢亲")
     @NotEmpty(message = "商家回复内容不能为空")
     private String replyContent;
 

+ 9 - 15
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentRespVO.java

@@ -13,37 +13,31 @@ import java.time.LocalDateTime;
 @ToString(callSuper = true)
 public class ProductCommentRespVO extends ProductCommentBaseVO {
 
-    @Schema(description = "订单项编号", required = true, example = "24965")
+    @Schema(description = "订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24965")
     private Long id;
 
-    @Schema(description = "是否匿名", required = true, example = "false")
+    @Schema(description = "是否匿名", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
     private Boolean anonymous;
 
-    @Schema(description = "交易订单编号", required = true, example = "24428")
+    @Schema(description = "交易订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24428")
     private Long orderId;
 
-    @Schema(description = "评价人 用户编号", required = true, example = "15721")
-    private Long userId;
-
-    @Schema(description = "交易订单项编号", required = true, example = "8233")
-    private Long orderItemId;
-
-    @Schema(description = "是否可见:[true:显示 false:隐藏]", required = true)
+    @Schema(description = "是否可见:[true:显示 false:隐藏]", requiredMode = Schema.RequiredMode.REQUIRED)
     private Boolean visible;
 
-    @Schema(description = "商家是否回复:[1:回复 0:未回复]", required = true)
+    @Schema(description = "商家是否回复:[1:回复 0:未回复]", requiredMode = Schema.RequiredMode.REQUIRED)
     private Boolean replyStatus;
 
-    @Schema(description = "回复管理员编号", example = "22212")
+    @Schema(description = "回复管理员编号", example = "9527")
     private Long replyUserId;
 
-    @Schema(description = "商家回复内容")
+    @Schema(description = "商家回复内容", example = "感谢好评哦亲(づ ̄3 ̄)づ╭❤~")
     private String replyContent;
 
-    @Schema(description = "商家回复时间")
+    @Schema(description = "商家回复时间", example = "2023-08-08 12:20:55")
     private LocalDateTime replyTime;
 
-    @Schema(description = "创建时间", required = true)
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime createTime;
 
 }

+ 2 - 2
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentUpdateVisibleReqVO.java

@@ -11,11 +11,11 @@ import javax.validation.constraints.NotNull;
 @ToString(callSuper = true)
 public class ProductCommentUpdateVisibleReqVO {
 
-    @Schema(description = "评价编号", required = true, example = "15721")
+    @Schema(description = "评价编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15721")
     @NotNull(message = "评价编号不能为空")
     private Long id;
 
-    @Schema(description = "是否可见", required = true, example = "false")
+    @Schema(description = "是否可见", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
     @NotNull(message = "是否可见不能为空")
     private Boolean visible;
 

+ 4 - 4
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java

@@ -20,16 +20,16 @@ import java.util.List;
 @ToString(callSuper = true)
 public class ProductSpuDetailRespVO extends ProductSpuBaseVO {
 
-    @Schema(description = "商品 SPU 编号", required = true, example = "1212")
+    @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1212")
     private Long id;
 
-    @Schema(description = "商品销量", required = true, example = "10000")
+    @Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000")
     private Integer salesCount;
 
-    @Schema(description = "浏览量", required = true, example = "20000")
+    @Schema(description = "浏览量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20000")
     private Integer browseCount;
 
-    @Schema(description = "商品状态", required = true, example = "1")
+    @Schema(description = "商品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer status;
 
     // ========== SKU 相关字段 =========

+ 1 - 2
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java

@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
 
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
-import cn.iocoder.yudao.framework.common.validation.InEnum;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -51,7 +50,7 @@ public class ProductSpuPageReqVO extends PageParam {
     @Schema(description = "商品名称", example = "清凉小短袖")
     private String name;
 
-    @Schema(description = "前端请求的tab类型", required = true, example = "1")
+    @Schema(description = "前端请求的tab类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer tabType;
 
     @Schema(description = "商品分类编号", example = "1")

+ 2 - 7
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java

@@ -1,16 +1,11 @@
 package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
 
 import cn.iocoder.yudao.framework.common.validation.InEnum;
-import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
 
-import javax.validation.Valid;
 import javax.validation.constraints.NotNull;
-import java.util.List;
 
 /**
  * 商品 SPU Status 更新 Request VO
@@ -21,11 +16,11 @@ import java.util.List;
 @Data
 public class ProductSpuUpdateStatusReqVO{
 
-    @Schema(description = "商品编号", required = true, example = "1")
+    @Schema(description = "商品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "商品编号不能为空")
     private Long id;
 
-    @Schema(description = "商品状态", required = true, example = "1")
+    @Schema(description = "商品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "商品状态不能为空")
     @InEnum(ProductSpuStatusEnum.class)
     private Integer status;

+ 37 - 56
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java

@@ -1,16 +1,23 @@
 package cn.iocoder.yudao.module.product.controller.app.comment;
 
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO;
 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStatisticsRespVO;
 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO;
 import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
+import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert;
+import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
+import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
 import cn.iocoder.yudao.module.product.service.comment.ProductCommentService;
+import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.Parameters;
 import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -19,11 +26,11 @@ import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
 import javax.validation.Valid;
-import java.time.LocalDateTime;
-import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
-import java.util.Random;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 
@@ -36,7 +43,10 @@ public class AppProductCommentController {
     @Resource
     private ProductCommentService productCommentService;
 
-    // TODO @puhui999:可以实现下
+    @Resource
+    @Lazy
+    private ProductSkuService productSkuService;
+
     @GetMapping("/list")
     @Operation(summary = "获得最近的 n 条商品评价")
     @Parameters({
@@ -45,67 +55,38 @@ public class AppProductCommentController {
     })
     public CommonResult<List<AppProductCommentRespVO>> getCommentList(@RequestParam("spuId") Long spuId,
                                                                       @RequestParam(value = "count", defaultValue = "10") Integer count) {
-        List<AppProductPropertyValueDetailRespVO> list = new ArrayList<>();
-
-        AppProductPropertyValueDetailRespVO item1 = new AppProductPropertyValueDetailRespVO();
-        item1.setPropertyId(1L);
-        item1.setPropertyName("颜色");
-        item1.setValueId(1024L);
-        item1.setValueName("红色");
-        list.add(item1);
-
-        AppProductPropertyValueDetailRespVO item2 = new AppProductPropertyValueDetailRespVO();
-        item2.setPropertyId(2L);
-        item2.setPropertyName("尺寸");
-        item2.setValueId(2048L);
-        item2.setValueName("大号");
-        list.add(item2);
-
-        AppProductPropertyValueDetailRespVO item3 = new AppProductPropertyValueDetailRespVO();
-        item3.setPropertyId(3L);
-        item3.setPropertyName("重量");
-        item3.setValueId(3072L);
-        item3.setValueName("500克");
-        list.add(item3);
-
-        // TODO 生成 mock 的数据
-        AppProductCommentRespVO appCommentRespVO = new AppProductCommentRespVO();
-        appCommentRespVO.setUserId((long) (new Random().nextInt(100000) + 10000));
-        appCommentRespVO.setUserNickname("用户" + new Random().nextInt(100));
-        appCommentRespVO.setUserAvatar("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
-        appCommentRespVO.setId((long) (new Random().nextInt(100000) + 10000));
-        appCommentRespVO.setAnonymous(new Random().nextBoolean());
-        appCommentRespVO.setOrderId((long) (new Random().nextInt(100000) + 10000));
-        appCommentRespVO.setOrderItemId((long) (new Random().nextInt(100000) + 10000));
-        appCommentRespVO.setReplyStatus(new Random().nextBoolean());
-        appCommentRespVO.setReplyUserId((long) (new Random().nextInt(100000) + 10000));
-        appCommentRespVO.setReplyContent("回复内容" + new Random().nextInt(100));
-        appCommentRespVO.setReplyTime(LocalDateTime.now().minusDays(new Random().nextInt(30)));
-        appCommentRespVO.setCreateTime(LocalDateTime.now().minusDays(new Random().nextInt(30)));
-        appCommentRespVO.setSpuId((long) (new Random().nextInt(100000) + 10000));
-        appCommentRespVO.setSpuName("商品" + new Random().nextInt(100));
-        appCommentRespVO.setSkuId((long) (new Random().nextInt(100000) + 10000));
-        appCommentRespVO.setSkuProperties(list);
-        appCommentRespVO.setScores(new Random().nextInt(5) + 1);
-        appCommentRespVO.setDescriptionScores(new Random().nextInt(5) + 1);
-        appCommentRespVO.setBenefitScores(new Random().nextInt(5) + 1);
-        appCommentRespVO.setContent("评论内容" + new Random().nextInt(100));
-        appCommentRespVO.setPicUrls(Arrays.asList("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"));
+        return success(productCommentService.getCommentList(spuId, count));
 
-        return success(Arrays.asList(appCommentRespVO));
     }
 
     @GetMapping("/page")
     @Operation(summary = "获得商品评价分页")
     public CommonResult<PageResult<AppProductCommentRespVO>> getCommentPage(@Valid AppCommentPageReqVO pageVO) {
-        return success(productCommentService.getCommentPage(pageVO, Boolean.TRUE));
+        PageResult<AppProductCommentRespVO> page = productCommentService.getCommentPage(pageVO, Boolean.TRUE);
+        Set<Long> skuIds = page.getList().stream().map(AppProductCommentRespVO::getSkuId).collect(Collectors.toSet());
+        List<ProductSkuDO> skuList = productSkuService.getSkuList(skuIds);
+        Map<Long, ProductSkuDO> skuDOMap = new HashMap<>(skuIds.size());
+        if (CollUtil.isNotEmpty(skuList)) {
+            skuDOMap.putAll(skuList.stream().collect(Collectors.toMap(ProductSkuDO::getId, c -> c)));
+        }
+        page.getList().forEach(item -> {
+            // 判断用户是否选择匿名
+            if (ObjectUtil.equal(item.getAnonymous(), true)) {
+                item.setUserNickname(ProductCommentDO.NICKNAME_ANONYMOUS);
+            }
+            ProductSkuDO productSkuDO = skuDOMap.get(item.getSkuId());
+            if (productSkuDO != null) {
+                List<AppProductPropertyValueDetailRespVO> skuProperties = ProductCommentConvert.INSTANCE.convertList01(productSkuDO.getProperties());
+                item.setSkuProperties(skuProperties);
+            }
+        });
+        return success(page);
     }
 
-    // TODO @puhui:get-statistics;方法改成 getCommentStatistics;getCommentPageTabsCount 也改掉哈
     @GetMapping("/getCommentStatistics")
     @Operation(summary = "获得商品的评价统计")
-    public CommonResult<AppCommentStatisticsRespVO> getCommentPage(@Valid @RequestParam("spuId") Long spuId) {
-        return success(productCommentService.getCommentPageTabsCount(spuId, Boolean.TRUE));
+    public CommonResult<AppCommentStatisticsRespVO> getCommentStatistics(@Valid @RequestParam("spuId") Long spuId) {
+        return success(productCommentService.getCommentStatistics(spuId, Boolean.TRUE));
     }
 
 }

+ 4 - 4
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppCommentStatisticsRespVO.java

@@ -9,16 +9,16 @@ import lombok.ToString;
 @ToString(callSuper = true)
 public class AppCommentStatisticsRespVO {
 
-    @Schema(description = "所有评论数量", required = true, example = "15721")
+    @Schema(description = "所有评论数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15721")
     private Long allCount;
 
-    @Schema(description = "好评数量", required = true, example = "15721")
+    @Schema(description = "好评数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15721")
     private Long goodCount;
 
-    @Schema(description = "中评数量", required = true, example = "15721")
+    @Schema(description = "中评数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15721")
     private Long mediocreCount;
 
-    @Schema(description = "差评数量", required = true, example = "15721")
+    @Schema(description = "差评数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15721")
     private Long negativeCount;
 
 }

+ 10 - 10
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentCreateReqVO.java

@@ -13,43 +13,43 @@ import java.util.List;
 @ToString(callSuper = true)
 public class AppProductCommentCreateReqVO {
 
-    @Schema(description = "是否匿名", required = true, example = "true")
+    @Schema(description = "是否匿名", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
     @NotNull(message = "是否匿名不能为空")
     private Boolean anonymous;
 
-    @Schema(description = "交易订单项编号", required = true, example = "2312312")
+    @Schema(description = "交易订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2312312")
     @NotNull(message = "交易订单项编号不能为空")
     private Long orderItemId;
 
-    @Schema(description = "商品 SPU 编号", required = true, example = "91192")
+    @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "91192")
     @NotNull(message = "商品SPU编号不能为空")
     private Long spuId;
 
-    @Schema(description = "商品 SPU 名称", required = true, example = "清凉丝滑小短袖")
+    @Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑小短袖")
     @NotNull(message = "商品SPU名称不能为空")
     private String spuName;
 
-    @Schema(description = "商品 SKU 编号", required = true, example = "81192")
+    @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "81192")
     @NotNull(message = "商品SKU编号不能为空")
     private Long skuId;
 
-    @Schema(description = "评分星级 1-5 分", required = true, example = "5")
+    @Schema(description = "评分星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
     @NotNull(message = "评分星级 1-5 分不能为空")
     private Integer scores;
 
-    @Schema(description = "描述星级 1-5 分", required = true, example = "5")
+    @Schema(description = "描述星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
     @NotNull(message = "描述星级 1-5 分不能为空")
     private Integer descriptionScores;
 
-    @Schema(description = "服务星级 1-5 分", required = true, example = "5")
+    @Schema(description = "服务星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
     @NotNull(message = "服务星级 1-5 分不能为空")
     private Integer benefitScores;
 
-    @Schema(description = "评论内容", required = true, example = "哇,真的很丝滑凉快诶,好评")
+    @Schema(description = "评论内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "哇,真的很丝滑凉快诶,好评")
     @NotNull(message = "评论内容不能为空")
     private String content;
 
-    @Schema(description = "评论图片地址数组,以逗号分隔最多上传 9 张", required = true, example = "[https://www.iocoder.cn/xx.png, https://www.iocoder.cn/xxx.png]")
+    @Schema(description = "评论图片地址数组,以逗号分隔最多上传 9 张", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/xx.png, https://www.iocoder.cn/xxx.png]")
     @Size(max = 9, message = "评论图片地址数组长度不能超过 9 张")
     private List<String> picUrls;
 

+ 17 - 17
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentRespVO.java

@@ -23,28 +23,28 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
 @ToString(callSuper = true)
 public class AppProductCommentRespVO {
 
-    @Schema(description = "评价人的用户编号", required = true, example = "15721")
+    @Schema(description = "评价人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15721")
     private Long userId;
 
-    @Schema(description = "评价人名称", required = true, example = "张三")
+    @Schema(description = "评价人名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三")
     private String userNickname;
 
-    @Schema(description = "评价人头像", required = true, example = "https://www.iocoder.cn/xx.png")
+    @Schema(description = "评价人头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png")
     private String userAvatar;
 
-    @Schema(description = "订单项编号", required = true, example = "24965")
+    @Schema(description = "订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24965")
     private Long id;
 
-    @Schema(description = "是否匿名", required = true, example = "false")
+    @Schema(description = "是否匿名", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
     private Boolean anonymous;
 
-    @Schema(description = "交易订单编号", required = true, example = "24428")
+    @Schema(description = "交易订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24428")
     private Long orderId;
 
-    @Schema(description = "交易订单项编号", required = true, example = "8233")
+    @Schema(description = "交易订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8233")
     private Long orderItemId;
 
-    @Schema(description = "商家是否回复", required = true, example = "true")
+    @Schema(description = "商家是否回复", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
     private Boolean replyStatus;
 
     @Schema(description = "回复管理员编号", example = "22212")
@@ -71,38 +71,38 @@ public class AppProductCommentRespVO {
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime createTime;
 
-    @Schema(description = "商品SPU编号", required = true, example = "91192")
+    @Schema(description = "商品SPU编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "91192")
     @NotNull(message = "商品SPU编号不能为空")
     private Long spuId;
 
-    @Schema(description = "商品SPU名称", required = true, example = "清凉丝滑小短袖")
+    @Schema(description = "商品SPU名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑小短袖")
     @NotNull(message = "商品SPU名称不能为空")
     private String spuName;
 
-    @Schema(description = "商品SKU编号", required = true, example = "81192")
+    @Schema(description = "商品SKU编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "81192")
     @NotNull(message = "商品SKU编号不能为空")
     private Long skuId;
 
-    @Schema(description = "商品 SKU 属性", required = true)
+    @Schema(description = "商品 SKU 属性", requiredMode = Schema.RequiredMode.REQUIRED)
     private List<AppProductPropertyValueDetailRespVO> skuProperties;
 
-    @Schema(description = "评分星级 1-5 分", required = true, example = "5")
+    @Schema(description = "评分星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
     @NotNull(message = "评分星级 1-5 分不能为空")
     private Integer scores;
 
-    @Schema(description = "描述星级 1-5 分", required = true, example = "5")
+    @Schema(description = "描述星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
     @NotNull(message = "描述星级 1-5 分不能为空")
     private Integer descriptionScores;
 
-    @Schema(description = "服务星级 1-5 分", required = true, example = "5")
+    @Schema(description = "服务星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
     @NotNull(message = "服务星级 1-5 分不能为空")
     private Integer benefitScores;
 
-    @Schema(description = "评论内容", required = true, example = "哇,真的很丝滑凉快诶,好评")
+    @Schema(description = "评论内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "哇,真的很丝滑凉快诶,好评")
     @NotNull(message = "评论内容不能为空")
     private String content;
 
-    @Schema(description = "评论图片地址数组,以逗号分隔最多上传 9 张", required = true, example = "[https://www.iocoder.cn/xx.png, https://www.iocoder.cn/xxx.png]")
+    @Schema(description = "评论图片地址数组,以逗号分隔最多上传 9 张", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/xx.png, https://www.iocoder.cn/xxx.png]")
     @Size(max = 9, message = "评论图片地址数组长度不能超过 9 张")
     private List<String> picUrls;
 

+ 10 - 10
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageRespVO.java

@@ -9,40 +9,40 @@ import java.util.List;
 @Data
 public class AppProductSpuPageRespVO {
 
-    @Schema(description = "商品 SPU 编号", required = true, example = "1")
+    @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Long id;
 
-    @Schema(description = "商品名称", required = true, example = "芋道")
+    @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
     private String name;
 
-    @Schema(description = "分类编号", required = true)
+    @Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED)
     private Long categoryId;
 
-    @Schema(description = "商品封面图", required = true)
+    @Schema(description = "商品封面图", requiredMode = Schema.RequiredMode.REQUIRED)
     private String picUrl;
 
-    @Schema(description = "商品轮播图", required = true)
+    @Schema(description = "商品轮播图", requiredMode = Schema.RequiredMode.REQUIRED)
     private List<String> sliderPicUrls;
 
     // ========== SKU 相关字段 =========
 
-    @Schema(description = "规格类型", required = true, example = "true")
+    @Schema(description = "规格类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
     private Boolean specType;
 
-    @Schema(description = "商品价格,单位使用:分", required = true, example = "1024")
+    @Schema(description = "商品价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Integer price;
 
-    @Schema(description = "库存", required = true, example = "666")
+    @Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
     private Integer stock;
 
     // ========== 营销相关字段 =========
 
-    @Schema(description = "活动排序数组", required = true, example = "1024")
+    @Schema(description = "活动排序数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private List<Integer> activityOrders;
 
     // ========== 统计相关字段 =========
 
-    @Schema(description = "商品销量", required = true, example = "1024")
+    @Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Integer salesCount;
 
 }

+ 15 - 2
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.product.convert.comment;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
 import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentCreateReqVO;
 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentRespVO;
@@ -9,6 +10,7 @@ import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductComme
 import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
+import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
 import org.mapstruct.Named;
@@ -59,9 +61,18 @@ public interface ProductCommentConvert {
         return divide.intValue();
     }
 
-    @Mapping(target = "orderId", source = "orderId")
+    ProductCommentDO convert(ProductCommentCreateReqDTO createReqDTO);
+
     @Mapping(target = "scores", expression = "java(convertScores(createReqDTO.getDescriptionScores(), createReqDTO.getBenefitScores()))")
-    ProductCommentDO convert(ProductCommentCreateReqDTO createReqDTO, Long orderId);
+    default ProductCommentDO convert(ProductCommentCreateReqDTO createReqDTO, ProductSpuDO spuDO, MemberUserRespDTO user) {
+        ProductCommentDO commentDO = convert(createReqDTO);
+        commentDO.setUserId(user.getId());
+        commentDO.setUserNickname(user.getNickname());
+        commentDO.setUserAvatar(user.getAvatar());
+        commentDO.setSpuId(spuDO.getId());
+        commentDO.setSpuName(spuDO.getName());
+        return commentDO;
+    }
 
     @Mapping(target = "userId", constant = "0L")
     @Mapping(target = "orderId", constant = "0L")
@@ -70,4 +81,6 @@ public interface ProductCommentConvert {
     @Mapping(target = "scores", expression = "java(convertScores(createReq.getDescriptionScores(), createReq.getBenefitScores()))")
     ProductCommentDO convert(ProductCommentCreateReqVO createReq);
 
+    List<AppProductCommentRespVO> convertList02(List<ProductCommentDO> list);
+
 }

+ 17 - 9
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.product.dal.mysql.comment;
 
 
 import cn.hutool.core.util.ObjectUtil;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
@@ -25,19 +26,18 @@ public interface ProductCommentMapper extends BaseMapperX<ProductCommentDO> {
     }
 
     // TODO 芋艿:在看看这块
-    // TODO @puhui999:直接使用 scores 来算好评、中评、差评
     static void appendTabQuery(LambdaQueryWrapperX<ProductCommentDO> queryWrapper, Integer type) {
-        // 构建好评查询语句:好评计算 (商品评分星级+服务评分星级) >= 8
+        // 构建好评查询语句:好评计算 总评 >= 4
         if (ObjectUtil.equal(type, AppCommentPageReqVO.GOOD_COMMENT)) {
-            queryWrapper.apply("(scores + benefit_scores) >= 8");
+            queryWrapper.apply("scores >= 4");
         }
-        // 构建中评查询语句:中评计算 (商品评分星级+服务评分星级) > 4 且 (商品评分星级+服务评分星级) < 8
+        // 构建中评查询语句:中评计算 总评 >= 3 且 总评 < 4
         if (ObjectUtil.equal(type, AppCommentPageReqVO.MEDIOCRE_COMMENT)) {
-            queryWrapper.apply("(scores + benefit_scores) > 4 and (scores + benefit_scores) < 8");
+            queryWrapper.apply("scores >=3 and scores < 4");
         }
-        // 构建差评查询语句:差评计算 (商品评分星级+服务评分星级) <= 4
+        // 构建差评查询语句:差评计算 总评 < 3
         if (ObjectUtil.equal(type, AppCommentPageReqVO.NEGATIVE_COMMENT)) {
-            queryWrapper.apply("(scores + benefit_scores) <= 4");
+            queryWrapper.apply("scores < 3");
         }
     }
 
@@ -52,10 +52,10 @@ public interface ProductCommentMapper extends BaseMapperX<ProductCommentDO> {
         return selectPage(reqVO, queryWrapper);
     }
 
-    default ProductCommentDO selectByUserIdAndOrderIdAndSpuId(Long userId, Long orderId, Long spuId) {
+    default ProductCommentDO selectByUserIdAndOrderItemIdAndSpuId(Long userId, Long orderItemId, Long spuId) {
         return selectOne(new LambdaQueryWrapperX<ProductCommentDO>()
                 .eq(ProductCommentDO::getUserId, userId)
-                .eq(ProductCommentDO::getOrderId, orderId)
+                .eq(ProductCommentDO::getOrderItemId, orderItemId)
                 .eq(ProductCommentDO::getSpuId, spuId));
     }
 
@@ -68,4 +68,12 @@ public interface ProductCommentMapper extends BaseMapperX<ProductCommentDO> {
         return selectCount(queryWrapper);
     }
 
+    default PageResult<ProductCommentDO> selectCommentList(Long spuId, Integer count) {
+        // 构建分页查询条件
+        return selectPage(new PageParam().setPageSize(count), new LambdaQueryWrapperX<ProductCommentDO>()
+                .eqIfPresent(ProductCommentDO::getSpuId, spuId)
+                .orderByDesc(ProductCommentDO::getCreateTime)
+        );
+    }
+
 }

+ 15 - 3
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentService.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.product.service.comment;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentCreateReqVO;
 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentPageReqVO;
 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentReplyReqVO;
@@ -12,6 +13,8 @@ import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
+import java.util.List;
+
 /**
  * 商品评论 Service 接口
  *
@@ -65,10 +68,10 @@ public interface ProductCommentService {
      * 创建评论
      * 创建商品评论 APP 端创建商品评论使用
      *
-     * @param commentDO 评论对象
+     * @param createReqDTO 创建请求 dto
      * @return 返回评论 id
      */
-    Long createComment(ProductCommentDO commentDO);
+    Long createComment(ProductCommentCreateReqDTO createReqDTO);
 
     /**
      * 获得商品的评价统计
@@ -77,6 +80,15 @@ public interface ProductCommentService {
      * @param visible 是否可见
      * @return 评价统计
      */
-    AppCommentStatisticsRespVO getCommentPageTabsCount(Long spuId, Boolean visible);
+    AppCommentStatisticsRespVO getCommentStatistics(Long spuId, Boolean visible);
+
+    /**
+     * 得到评论列表
+     *
+     * @param spuId 商品 id
+     * @param count 数量
+     * @return {@link Object}
+     */
+    List<AppProductCommentRespVO> getCommentList(Long spuId, Integer count);
 
 }

+ 40 - 44
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java

@@ -1,8 +1,9 @@
 package cn.iocoder.yudao.module.product.service.comment;
 
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.ObjectUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
+import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
+import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentCreateReqVO;
 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentPageReqVO;
 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentReplyReqVO;
@@ -10,7 +11,6 @@ import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommen
 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO;
 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStatisticsRespVO;
 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO;
-import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
 import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert;
 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
@@ -18,7 +18,6 @@ import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
 import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper;
 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
 import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
-import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -26,11 +25,7 @@ import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
 import java.time.LocalDateTime;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*;
@@ -47,9 +42,6 @@ public class ProductCommentServiceImpl implements ProductCommentService {
     @Resource
     private ProductCommentMapper productCommentMapper;
 
-    @Resource
-    private TradeOrderApi tradeOrderApi;
-
     @Resource
     private ProductSpuService productSpuService;
 
@@ -57,6 +49,9 @@ public class ProductCommentServiceImpl implements ProductCommentService {
     @Lazy
     private ProductSkuService productSkuService;
 
+    @Resource
+    private MemberUserApi memberUserApi;
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void updateCommentVisible(ProductCommentUpdateVisibleReqVO updateReqVO) {
@@ -85,11 +80,8 @@ public class ProductCommentServiceImpl implements ProductCommentService {
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void createComment(ProductCommentCreateReqVO createReqVO) {
-        // 校验订单
-        // TODO @puhui999:不校验哈;尽可能解耦
-        Long orderId = tradeOrderApi.validateOrder(createReqVO.getUserId(), createReqVO.getOrderItemId());
         // 校验评论
-        validateComment(createReqVO.getSpuId(), createReqVO.getUserId(), orderId);
+        validateComment(createReqVO.getSpuId(), createReqVO.getUserId(), createReqVO.getOrderItemId());
 
         ProductCommentDO commentDO = ProductCommentConvert.INSTANCE.convert(createReqVO);
         productCommentMapper.insert(commentDO);
@@ -97,26 +89,41 @@ public class ProductCommentServiceImpl implements ProductCommentService {
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public Long createComment(ProductCommentDO commentDO) {
+    public Long createComment(ProductCommentCreateReqDTO createReqDTO) {
+        // 通过 sku ID 拿到 spu 相关信息
+        ProductSkuDO sku = productSkuService.getSku(createReqDTO.getSkuId());
+        if (sku == null) {
+            throw exception(SKU_NOT_EXISTS);
+        }
+        // 校验 spu 如果存在返回详情
+        ProductSpuDO spuDO = validateSpu(sku.getSpuId());
         // 校验评论
-        validateComment(commentDO.getSpuId(), commentDO.getUserId(), commentDO.getOrderId());
+        validateComment(spuDO.getId(), createReqDTO.getUserId(), createReqDTO.getOrderId());
+        // 获取用户详细信息
+        MemberUserRespDTO user = memberUserApi.getUser(createReqDTO.getUserId());
 
+        // 创建评论
+        ProductCommentDO commentDO = ProductCommentConvert.INSTANCE.convert(createReqDTO, spuDO, user);
         productCommentMapper.insert(commentDO);
         return commentDO.getId();
     }
 
-    private void validateComment(Long spuId, Long userId, Long orderId) {
-        ProductSpuDO spu = productSpuService.getSpu(spuId);
-        if (null == spu) {
-            throw exception(SPU_NOT_EXISTS);
-        }
+    private void validateComment(Long spuId, Long userId, Long orderItemId) {
         // 判断当前订单的当前商品用户是否评价过
-        ProductCommentDO exist = productCommentMapper.selectByUserIdAndOrderIdAndSpuId(userId, orderId, spuId);
+        ProductCommentDO exist = productCommentMapper.selectByUserIdAndOrderItemIdAndSpuId(userId, orderItemId, spuId);
         if (null != exist) {
             throw exception(ORDER_SPU_COMMENT_EXISTS);
         }
     }
 
+    private ProductSpuDO validateSpu(Long spuId) {
+        ProductSpuDO spu = productSpuService.getSpu(spuId);
+        if (null == spu) {
+            throw exception(SPU_NOT_EXISTS);
+        }
+        return spu;
+    }
+
     private ProductCommentDO validateCommentExists(Long id) {
         ProductCommentDO productComment = productCommentMapper.selectById(id);
         if (productComment == null) {
@@ -126,7 +133,7 @@ public class ProductCommentServiceImpl implements ProductCommentService {
     }
 
     @Override
-    public AppCommentStatisticsRespVO getCommentPageTabsCount(Long spuId, Boolean visible) {
+    public AppCommentStatisticsRespVO getCommentStatistics(Long spuId, Boolean visible) {
         return ProductCommentConvert.INSTANCE.convert(
                 // 查询商品 id = spuId 的所有评论数量
                 productCommentMapper.selectCountBySpuId(spuId, visible, null),
@@ -139,29 +146,18 @@ public class ProductCommentServiceImpl implements ProductCommentService {
         );
     }
 
+    @Override
+    public List<AppProductCommentRespVO> getCommentList(Long spuId, Integer count) {
+        // 校验商品 spu 是否存在
+        ProductSpuDO spuDO = validateSpu(spuId);
+
+        return ProductCommentConvert.INSTANCE.convertList02(productCommentMapper.selectCommentList(spuDO.getId(), count).getList());
+    }
+
     @Override
     public PageResult<AppProductCommentRespVO> getCommentPage(AppCommentPageReqVO pageVO, Boolean visible) {
-        PageResult<AppProductCommentRespVO> result = ProductCommentConvert.INSTANCE.convertPage02(
+        return ProductCommentConvert.INSTANCE.convertPage02(
                 productCommentMapper.selectPage(pageVO, visible));
-        // TODO @puhui999:要不这块放到 controller 里拼接?
-        Set<Long> skuIds = result.getList().stream().map(AppProductCommentRespVO::getSkuId).collect(Collectors.toSet());
-        List<ProductSkuDO> skuList = productSkuService.getSkuList(skuIds);
-        Map<Long, ProductSkuDO> skuDOMap = new HashMap<>(skuIds.size());
-        if (CollUtil.isNotEmpty(skuList)) {
-            skuDOMap.putAll(skuList.stream().collect(Collectors.toMap(ProductSkuDO::getId, c -> c)));
-        }
-        result.getList().forEach(item -> {
-            // 判断用户是否选择匿名
-            if (ObjectUtil.equal(item.getAnonymous(), true)) {
-                item.setUserNickname(ProductCommentDO.NICKNAME_ANONYMOUS);
-            }
-            ProductSkuDO productSkuDO = skuDOMap.get(item.getSkuId());
-            if (productSkuDO != null) {
-                List<AppProductPropertyValueDetailRespVO> skuProperties = ProductCommentConvert.INSTANCE.convertList01(productSkuDO.getProperties());
-                item.setSkuProperties(skuProperties);
-            }
-        });
-        return result;
     }
 
     @Override

+ 5 - 4
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java

@@ -55,7 +55,7 @@ public interface ProductSkuService {
      * 批量创建 SKU
      *
      * @param spuId 商品 SPU 编号
-     * @param list SKU 对象集合
+     * @param list  SKU 对象集合
      */
     void createSkuList(Long spuId, List<ProductSkuCreateOrUpdateReqVO> list);
 
@@ -63,13 +63,13 @@ public interface ProductSkuService {
      * 根据 SPU 编号,批量更新它的 SKU 信息
      *
      * @param spuId SPU 编码
-     * @param skus SKU 的集合
+     * @param skus  SKU 的集合
      */
     void updateSkuList(Long spuId, List<ProductSkuCreateOrUpdateReqVO> skus);
 
     /**
      * 更新 SKU 库存(增量)
-     *
+     * <p>
      * 如果更新的库存不足,会抛出异常
      *
      * @param updateStockReqDTO 更行请求
@@ -88,7 +88,7 @@ public interface ProductSkuService {
      * 获得 spu 对应的 SKU 集合
      *
      * @param spuIds spu 编码集合
-     * @return  商品 sku 集合
+     * @return 商品 sku 集合
      */
     List<ProductSkuDO> getSkuListBySpuId(List<Long> spuIds);
 
@@ -123,4 +123,5 @@ public interface ProductSkuService {
      * @return int 影响的行数
      */
     int updateSkuPropertyValue(Long propertyValueId, String propertyValueName);
+
 }

+ 1 - 1
yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java

@@ -150,7 +150,7 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest {
         assertEquals(2, result3.getTotal());
 
         // 测试分页 tab count
-        AppCommentStatisticsRespVO tabsCount = productCommentService.getCommentPageTabsCount(spuId, Boolean.TRUE);
+        AppCommentStatisticsRespVO tabsCount = productCommentService.getCommentStatistics(spuId, Boolean.TRUE);
         assertEquals(6, tabsCount.getAllCount());
         assertEquals(4, tabsCount.getGoodCount());
         assertEquals(2, tabsCount.getMediocreCount());

+ 19 - 69
yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/create_tables.sql

@@ -126,82 +126,32 @@ CREATE TABLE IF NOT EXISTS `product_property_value` (
     PRIMARY KEY("id")
 ) COMMENT '规格值';
 
--- TODO @puhui999:格式不太对哈
-CREATE TABLE IF NOT EXISTS `product_comment`
-(
-    `id`
-    bigint
-    NOT
-    NULL
-    AUTO_INCREMENT
-    COMMENT
-    '评论编号,主键自增',
-    `user_id`
-    bigint
-    DEFAULT
-    NULL
-    COMMENT
-    '评价人的用户编号关联 MemberUserDO 的 id 编号',
-    `user_nickname`
-    varchar
-(
-    255
-) DEFAULT NULL COMMENT '评价人名称',
-    `user_avatar` varchar
-(
-    1024
-) DEFAULT NULL COMMENT '评价人头像',
-    `anonymous` bit
-(
-    1
-) DEFAULT NULL COMMENT '是否匿名',
+DROP TABLE IF EXISTS `product_comment` (
+    `id` bigint NOT NULL AUTO_INCREMENT COMMENT '评论编号,主键自增',
+    `user_id` bigint DEFAULT NULL COMMENT '评价人的用户编号关联 MemberUserDO 的 id 编号',
+    `user_nickname` varchar(255) DEFAULT NULL COMMENT '评价人名称',
+    `user_avatar` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '评价人头像',
+    `anonymous` bit(1) DEFAULT NULL COMMENT '是否匿名',
     `order_id` bigint DEFAULT NULL COMMENT '交易订单编号关联 TradeOrderDO 的 id 编号',
     `order_item_id` bigint DEFAULT NULL COMMENT '交易订单项编号关联 TradeOrderItemDO 的 id 编号',
     `spu_id` bigint DEFAULT NULL COMMENT '商品 SPU 编号关联 ProductSpuDO 的 id',
-    `spu_name` varchar
-(
-    255
-) DEFAULT NULL COMMENT '商品 SPU 名称',
+    `spu_name` varchar(255) DEFAULT NULL COMMENT '商品 SPU 名称',
     `sku_id` bigint DEFAULT NULL COMMENT '商品 SKU 编号关联 ProductSkuDO 的 id 编号',
-    `visible` bit
-(
-    1
-) DEFAULT NULL COMMENT '是否可见true:显示false:隐藏',
-    `scores` tinyint DEFAULT NULL COMMENT '评分星级1-5 分',
+    `visible` bit(1) DEFAULT NULL COMMENT '是否可见true:显示false:隐藏',
+    `scores` tinyint DEFAULT NULL COMMENT '评分星级1-5分',
     `description_scores` tinyint DEFAULT NULL COMMENT '描述星级1-5 星',
     `benefit_scores` tinyint DEFAULT NULL COMMENT '服务星级1-5 星',
-    `content` varchar
-(
-    1024
-) DEFAULT NULL COMMENT '评论内容',
-    `pic_urls` varchar
-(
-    4096
-) DEFAULT NULL COMMENT '评论图片地址数组',
-    `reply_status` bit
-(
-    1
-) DEFAULT NULL COMMENT '商家是否回复',
+    `content` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '评论内容',
+    `pic_urls` varchar(4096) DEFAULT NULL COMMENT '评论图片地址数组',
+    `reply_status` bit(1) DEFAULT NULL COMMENT '商家是否回复',
     `reply_user_id` bigint DEFAULT NULL COMMENT '回复管理员编号关联 AdminUserDO 的 id 编号',
-    `reply_content` varchar
-(
-    1024
-) DEFAULT NULL COMMENT '商家回复内容',
+    `reply_content` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '商家回复内容',
     `reply_time` datetime DEFAULT NULL COMMENT '商家回复时间',
-    `creator` varchar
-(
-    64
-) DEFAULT '' COMMENT '创建者',
+    `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者',
     `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
-    `updater` varchar
-(
-    64
-) DEFAULT '' COMMENT '更新者',
+    `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者',
     `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
-    "deleted" bit NOT NULL DEFAULT FALSE,
-    "tenant_id" bigint not null default '0',
-    PRIMARY KEY
-(
-    `id`
-)
-    ) COMMENT '产品评论表';
+    `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
+    `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
+    PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 26 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '商品评论';

+ 2 - 0
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java

@@ -56,5 +56,7 @@ public interface ErrorCodeConstants {
     // ========== 秒杀时段 1013009000 ==========
     ErrorCode SECKILL_TIME_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在");
     ErrorCode SECKILL_TIME_CONFLICTS = new ErrorCode(1013009001, "秒杀时段冲突");
+    ErrorCode SECKILL_TIME_EQUAL = new ErrorCode(1013009002, "秒杀时段开始时间和结束时间不能相等");
+    ErrorCode SECKILL_START_TIME_BEFORE_END_TIME = new ErrorCode(1013009003, "秒杀时段开始时间不能在结束时间之后");
 
 }

+ 99 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java

@@ -0,0 +1,99 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.seckill;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.*;
+import cn.iocoder.yudao.module.promotion.convert.seckill.seckillconfig.SeckillConfigConvert;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
+import cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig.SeckillConfigService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+/**
+ * 管理后台 - 秒杀时段相关接口
+ *
+ * @author HUIHUI
+ */
+@Tag(name = "管理后台 - 秒杀时段")
+@RestController
+@RequestMapping("/promotion/seckill-config")
+@Validated
+public class SeckillConfigController {
+
+    @Resource
+    private SeckillConfigService seckillConfigService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建秒杀时段")
+    @PreAuthorize("@ss.hasPermission('promotion:seckill-config:create')")
+    public CommonResult<Long> createSeckillConfig(@Valid @RequestBody SeckillConfigCreateReqVO createReqVO) {
+        return success(seckillConfigService.createSeckillConfig(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新秒杀时段")
+    @PreAuthorize("@ss.hasPermission('promotion:seckill-config:update')")
+    public CommonResult<Boolean> updateSeckillConfig(@Valid @RequestBody SeckillConfigUpdateReqVO updateReqVO) {
+        seckillConfigService.updateSeckillConfig(updateReqVO);
+        return success(true);
+    }
+
+    @PutMapping("/update-status")
+    @Operation(summary = "修改时段配置状态")
+    @PreAuthorize("@ss.hasPermission('system:seckill-config:update')")
+    public CommonResult<Boolean> updateSeckillConfigStatus(@Valid @RequestBody SeckillConfigUpdateStatusReqVo reqVO) {
+        seckillConfigService.updateSeckillConfigStatus(reqVO.getId(), reqVO.getStatus());
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除秒杀时段")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('promotion:seckill-config:delete')")
+    public CommonResult<Boolean> deleteSeckillConfig(@RequestParam("id") Long id) {
+        seckillConfigService.deleteSeckillConfig(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得秒杀时段")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('promotion:seckill-config:query')")
+    public CommonResult<SeckillConfigRespVO> getSeckillConfig(@RequestParam("id") Long id) {
+        SeckillConfigDO seckillConfig = seckillConfigService.getSeckillConfig(id);
+        return success(SeckillConfigConvert.INSTANCE.convert(seckillConfig));
+    }
+
+    @GetMapping("/list")
+    @Operation(summary = "获得所有秒杀时段列表")
+    @PreAuthorize("@ss.hasPermission('promotion:seckill-config:query')")
+    public CommonResult<List<SeckillConfigRespVO>> getSeckillConfigList() {
+        List<SeckillConfigDO> list = seckillConfigService.getSeckillConfigList();
+        return success(SeckillConfigConvert.INSTANCE.convertList(list));
+    }
+
+    @GetMapping("/list-all-simple")
+    @Operation(summary = "获得所有开启状态的秒杀时段精简列表", description = "主要用于前端的下拉选项")
+    public CommonResult<List<SeckillConfigSimpleRespVO>> getListAllSimple() {
+        List<SeckillConfigDO> list = seckillConfigService.getListAllSimple();
+        return success(SeckillConfigConvert.INSTANCE.convertList1(list));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得秒杀活动分页")
+    @PreAuthorize("@ss.hasPermission('promotion:seckill-config:query')")
+    public CommonResult<PageResult<SeckillConfigRespVO>> getSeckillActivityPage(@Valid SeckillConfigPageReqVO pageVO) {
+        PageResult<SeckillConfigDO> pageResult = seckillConfigService.getSeckillConfigPage(pageVO);
+        return success(SeckillConfigConvert.INSTANCE.convertPage(pageResult));
+    }
+}

+ 0 - 72
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillTimeController.java

@@ -1,72 +0,0 @@
-package cn.iocoder.yudao.module.promotion.controller.admin.seckill;
-
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeCreateReqVO;
-import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeRespVO;
-import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeUpdateReqVO;
-import cn.iocoder.yudao.module.promotion.convert.seckill.seckilltime.SeckillTimeConvert;
-import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime.SeckillTimeDO;
-import cn.iocoder.yudao.module.promotion.service.seckill.seckilltime.SeckillTimeService;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import javax.annotation.Resource;
-import javax.validation.Valid;
-import java.util.List;
-
-import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-
-@Tag(name = "管理后台 - 秒杀时段")
-@RestController
-@RequestMapping("/promotion/seckill-time")
-@Validated
-public class SeckillTimeController {
-
-    @Resource
-    private SeckillTimeService seckillTimeService;
-
-    @PostMapping("/create")
-    @Operation(summary = "创建秒杀时段")
-    @PreAuthorize("@ss.hasPermission('promotion:seckill-time:create')")
-    public CommonResult<Long> createSeckillTime(@Valid @RequestBody SeckillTimeCreateReqVO createReqVO) {
-        return success(seckillTimeService.createSeckillTime(createReqVO));
-    }
-
-    @PutMapping("/update")
-    @Operation(summary = "更新秒杀时段")
-    @PreAuthorize("@ss.hasPermission('promotion:seckill-time:update')")
-    public CommonResult<Boolean> updateSeckillTime(@Valid @RequestBody SeckillTimeUpdateReqVO updateReqVO) {
-        seckillTimeService.updateSeckillTime(updateReqVO);
-        return success(true);
-    }
-
-    @DeleteMapping("/delete")
-    @Operation(summary = "删除秒杀时段")
-    @Parameter(name = "id", description = "编号", required = true)
-    @PreAuthorize("@ss.hasPermission('promotion:seckill-time:delete')")
-    public CommonResult<Boolean> deleteSeckillTime(@RequestParam("id") Long id) {
-        seckillTimeService.deleteSeckillTime(id);
-        return success(true);
-    }
-
-    @GetMapping("/get")
-    @Operation(summary = "获得秒杀时段")
-    @Parameter(name = "id", description = "编号", required = true, example = "1024")
-    @PreAuthorize("@ss.hasPermission('promotion:seckill-time:query')")
-    public CommonResult<SeckillTimeRespVO> getSeckillTime(@RequestParam("id") Long id) {
-        SeckillTimeDO seckillTime = seckillTimeService.getSeckillTime(id);
-        return success(SeckillTimeConvert.INSTANCE.convert(seckillTime));
-    }
-
-    @GetMapping("/list")
-    @Operation(summary = "获得所有秒杀时段列表")
-    @PreAuthorize("@ss.hasPermission('promotion:seckill-time:query')")
-    public CommonResult<List<SeckillTimeRespVO>> getSeckillTimeList() {
-        List<SeckillTimeDO> list = seckillTimeService.getSeckillTimeList();
-        return success(SeckillTimeConvert.INSTANCE.convertList(list));
-    }
-}

+ 24 - 28
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityBaseVO.java

@@ -1,65 +1,61 @@
 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity;
 
-import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
-import javax.validation.constraints.Min;
 import javax.validation.constraints.NotNull;
 import java.time.LocalDateTime;
+import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT;
 
 /**
+ * 秒杀活动基地签证官
  * 秒杀活动 Base VO,提供给添加、修改、详细的子 VO 使用
  * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
+ *
+ * @author HUIHUI
  */
 @Data
 public class SeckillActivityBaseVO {
 
-    @Schema(description = "秒杀活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "晚九点限时秒杀")
+    @Schema(description = "秒杀活动商品id", requiredMode = Schema.RequiredMode.REQUIRED, example = "[121,1212]")
+    @NotNull(message = "秒杀活动商品不能为空")
+    private List<Long> spuIds;
+
+    @Schema(description = "秒杀活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618大促")
     @NotNull(message = "秒杀活动名称不能为空")
     private String name;
 
+    @Schema(description = "备注", example = "清仓大甩卖割韭菜")
+    private String remark;
+
     @Schema(description = "活动开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
     @NotNull(message = "活动开始时间不能为空")
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
     private LocalDateTime startTime;
 
     @Schema(description = "活动结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
     @NotNull(message = "活动结束时间不能为空")
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
     private LocalDateTime endTime;
 
+    @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "排序不能为空")
+    private Integer sort;
 
-    @Schema(description = "商品")
-    @Data
-    public static class Product {
-
-        @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-        @NotNull(message = "商品 SPU 编号不能为空")
-        private Long spuId;
-
-        @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-        @NotNull(message = "商品 SKU 编号不能为空")
-        private Long skuId;
-
-        @Schema(description = "秒杀金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "12.00")
-        @NotNull(message = "秒杀金额不能为空")
-        private Integer seckillPrice;
+    @Schema(description = "秒杀时段id", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1,2,3]")
+    @NotNull(message = "秒杀时段不能为空")
+    private List<Long> configIds;
 
-        @Schema(description = "秒杀库存", example = "80")
-        @Min(value = 0, message = "秒杀库存需要大于等于 0")
-        private Integer stock;
+    @Schema(description = "总限购数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "12877")
+    private Integer totalLimitCount;
 
-        @Schema(description = "每人限购", example = "10") // 如果为 0 则不限购
-        @Min(value = 0, message = "每人限购需要大于等于 0")
-        private Integer limitCount;
+    @Schema(description = "单次限够数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "31683")
+    private Integer singleLimitCount;
 
-    }
+    @Schema(description = "秒杀总库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
+    private Integer totalStock;
 
 }

+ 9 - 20
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityCreateReqVO.java

@@ -1,37 +1,26 @@
 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity;
 
+
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductCreateReqVO;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.ToString;
 
-import javax.validation.Valid;
-import javax.validation.constraints.NotEmpty;
-import javax.validation.constraints.NotNull;
 import java.util.List;
 
+/**
+ * 管理后台 - 秒杀活动创建 Request VO
+ *
+ * @author HUIHUI
+ */
 @Schema(description = "管理后台 - 秒杀活动创建 Request VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
 public class SeckillActivityCreateReqVO extends SeckillActivityBaseVO {
 
-    @Schema(description = "备注", example = "限时秒杀活动")
-    private String remark;
-
-    @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @NotNull(message = "排序不能为空")
-    private Integer sort;
-
-    @Schema(description = "秒杀时段id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1,3")
-    @NotEmpty(message = "参与场次不能为空")
-    private List<Long> timeIds;
-
-    /**
-     * 商品列表
-     */
-    @NotEmpty(message = "商品列表不能为空")
-    @Valid
-    private List<Product> products;
+    @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED)
+    private List<SeckillProductCreateReqVO> products;
 
 }

+ 12 - 7
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityDetailRespVO.java

@@ -1,21 +1,26 @@
 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity;
 
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductRespVO;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
-import lombok.EqualsAndHashCode;
 import lombok.ToString;
 
 import java.util.List;
 
+/**
+ * 管理后台 - 秒杀活动的详细 Response VO
+ *
+ * @author HUIHUI
+ */
 @Schema(description = "管理后台 - 秒杀活动的详细 Response VO")
 @Data
-@EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
-public class SeckillActivityDetailRespVO extends SeckillActivityRespVO {
+public class SeckillActivityDetailRespVO extends SeckillActivityBaseVO{
 
-    /**
-     * 商品列表
-     */
-    private List<Product> products;
+    @Schema(description = "秒杀活动id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    private Long id;
+
+    @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED)
+    private List<SeckillProductRespVO> products;
 
 }

+ 1 - 1
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityPageReqVO.java

@@ -26,7 +26,7 @@ public class SeckillActivityPageReqVO extends PageParam {
     private Integer status;
 
     @Schema(description = "秒杀时段id", example = "1")
-    private Long timeId;
+    private Long configId;
 
     @Schema(description = "创建时间")
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)

+ 10 - 19
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java

@@ -1,13 +1,18 @@
 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity;
 
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductRespVO;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.ToString;
 
-import java.time.LocalDateTime;
 import java.util.List;
 
+/**
+ * 管理后台 - 秒杀活动 Response VO
+ *
+ * @author HUIHUI
+ */
 @Schema(description = "管理后台 - 秒杀活动 Response VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
@@ -17,25 +22,11 @@ public class SeckillActivityRespVO extends SeckillActivityBaseVO {
     @Schema(description = "秒杀活动id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Long id;
 
-    @Schema(description = "付款订单数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    private Integer orderCount;
+    @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED)
+    private List<SeckillProductRespVO> products; // TODO puhui: 考虑是否去除
 
-    @Schema(description = "付款人数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    private Integer userCount;
-
-    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
-    private LocalDateTime createTime;
-
-    @Schema(description = "秒杀时段id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1,3")
-    private List<Long> timeIds;
-
-    @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    private Integer sort;
-
-    @Schema(description = "备注", example = "限时秒杀活动")
-    private String remark;
-
-    @Schema(description = "活动状态", example = "进行中")
+    @Schema(description = "活动状态 开启:0 禁用:1", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
     private Integer status;
 
+
 }

+ 10 - 18
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityUpdateReqVO.java

@@ -1,5 +1,7 @@
 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity;
 
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductRespVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductUpdateReqVO;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -10,32 +12,22 @@ import javax.validation.constraints.NotEmpty;
 import javax.validation.constraints.NotNull;
 import java.util.List;
 
+/**
+ * 管理后台 - 秒杀活动更新 Request VO
+ *
+ * @author HUIHUI
+ */
 @Schema(description = "管理后台 - 秒杀活动更新 Request VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
 public class SeckillActivityUpdateReqVO extends SeckillActivityBaseVO {
 
-    @Schema(description = "秒杀活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "224")
-    @NotNull(message = "秒杀活动编号不能为空")
+    @Schema(description = "秒杀活动id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Long id;
 
-    @Schema(description = "备注", example = "限时秒杀活动")
-    private String remark;
+    @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED)
+    private List<SeckillProductUpdateReqVO> products;
 
-    @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @NotNull(message = "排序不能为空")
-    private Integer sort;
-
-    @Schema(description = "秒杀时段id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1,3")
-    @NotEmpty(message = "秒杀时段id不能为空")
-    private List<Long> timeIds;
-
-    /**
-     * 商品列表
-     */
-    @NotEmpty(message = "商品列表不能为空")
-    @Valid
-    private List<Product> products;
 
 }

+ 17 - 8
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/time/SeckillTimeBaseVO.java → yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigBaseVO.java

@@ -1,28 +1,37 @@
-package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time;
+package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import javax.validation.constraints.NotNull;
-import java.time.LocalTime;
 
 /**
  * 秒杀时段 Base VO,提供给添加、修改、详细的子 VO 使用
  * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
+ *
+ * @author HUIHUI
  */
 @Data
-public class SeckillTimeBaseVO {
+public class SeckillConfigBaseVO {
 
-    @Schema(description = "秒杀时段名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "上场")
+    @Schema(description = "秒杀时段名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "上场")
     @NotNull(message = "秒杀时段名称不能为空")
     private String name;
 
-    @Schema(description = "开始时间点", requiredMode = Schema.RequiredMode.REQUIRED, example = "16:30:40")
+    @Schema(description = "开始时间点", requiredMode = Schema.RequiredMode.REQUIRED, example = "09:00:00")
     @NotNull(message = "开始时间点不能为空")
-    private LocalTime startTime;
+    private String startTime;
 
-    @Schema(description = "结束时间点", requiredMode = Schema.RequiredMode.REQUIRED, example = "16:30:40")
+    @Schema(description = "结束时间点", requiredMode = Schema.RequiredMode.REQUIRED, example = "16:00:00")
     @NotNull(message = "结束时间点不能为空")
-    private LocalTime endTime;
+    private String endTime;
+
+    @Schema(description = "秒杀主图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn")
+    @NotNull(message = "秒杀主图不能为空")
+    private String picUrl;
+
+    @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
+    @NotNull(message = "状态不能为空")
+    private Integer status;
 
 }

+ 7 - 2
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/time/SeckillTimeCreateReqVO.java → yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigCreateReqVO.java

@@ -1,14 +1,19 @@
-package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time;
+package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.ToString;
 
+/**
+ * 管理后台 秒杀时段创建 Request VO
+ *
+ * @author HUIHUI
+ */
 @Schema(description = "管理后台 - 秒杀时段创建 Request VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
-public class SeckillTimeCreateReqVO extends SeckillTimeBaseVO {
+public class SeckillConfigCreateReqVO extends SeckillConfigBaseVO {
 
 }

+ 9 - 12
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/time/SeckillTimePageReqVO.java → yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigPageReqVO.java

@@ -1,29 +1,26 @@
-package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time;
+package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config;
 
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.ToString;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.time.LocalTime;
 
+/**
+ * 管理后台 - 秒杀时段分页 Request VO
+ *
+ * @author HUIHUI
+ */
 @Schema(description = "管理后台 - 秒杀时段分页 Request VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
-public class SeckillTimePageReqVO extends PageParam {
+public class SeckillConfigPageReqVO extends PageParam {
 
     @Schema(description = "秒杀时段名称", example = "上午场")
     private String name;
 
-    @Schema(description = "开始时间点", example = "16:30:40")
-    @DateTimeFormat(pattern = "HH:mm:ss")
-    private LocalTime startTime;
-
-    @Schema(description = "结束时间点", example = "16:30:40")
-    @DateTimeFormat(pattern = "HH:mm:ss")
-    private LocalTime endTime;
+    @Schema(description = "状态", example = "0")
+    private Integer status;
 
 }

+ 12 - 3
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/time/SeckillTimeRespVO.java → yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigRespVO.java

@@ -1,25 +1,34 @@
-package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time;
+package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
 
 import java.time.LocalDateTime;
 
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+/**
+ * 管理后台 - 秒杀时段 Response VO
+ *
+ * @author HUIHUI
+ */
 @Schema(description = "管理后台 - 秒杀时段 Response VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
-public class SeckillTimeRespVO extends SeckillTimeBaseVO {
+public class SeckillConfigRespVO extends SeckillConfigBaseVO {
 
     @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Long id;
 
-    @Schema(description = "秒杀活动数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "秒杀活动数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
     private Integer seckillActivityCount;
 
     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime createTime;
 
 }

+ 29 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigSimpleRespVO.java

@@ -0,0 +1,29 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * 管理后台 - 秒杀时段配置精简信息 Response VO
+ *
+ * @author HUIHUI
+ */
+@Schema(description = "管理后台 - 秒杀时段配置精简信息 Response VO")
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class SeckillConfigSimpleRespVO {
+
+    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @NotNull(message = "编号不能为空")
+    private Long id;
+
+    @Schema(description = "秒杀时段名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "早上场")
+    @NotNull(message = "秒杀时段名称不能为空")
+    private String name;
+
+}

+ 7 - 2
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/time/SeckillTimeUpdateReqVO.java → yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigUpdateReqVO.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time;
+package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
@@ -7,11 +7,16 @@ import lombok.ToString;
 
 import javax.validation.constraints.NotNull;
 
+/**
+ * 管理后台 - 秒杀时段更新 Request VO
+ *
+ * @author HUIHUI
+ */
 @Schema(description = "管理后台 - 秒杀时段更新 Request VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
-public class SeckillTimeUpdateReqVO extends SeckillTimeBaseVO {
+public class SeckillConfigUpdateReqVO extends SeckillConfigBaseVO {
 
     @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "编号不能为空")

+ 28 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigUpdateStatusReqVo.java

@@ -0,0 +1,28 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config;
+
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.common.validation.InEnum;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * 管理后台 - 修改时段配置状态 Request VO
+ *
+ * @author HUIHUI
+ */
+@Schema(description = "管理后台 - 修改时段配置状态 Request VO")
+@Data
+public class SeckillConfigUpdateStatusReqVo {
+
+    @Schema(description = "时段配置编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+    @NotNull(message = "时段配置编号不能为空")
+    private Long id;
+
+    @Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @NotNull(message = "状态不能为空")
+    @InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}")
+    private Integer status;
+
+}

+ 34 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductBaseVO.java

@@ -0,0 +1,34 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * 秒杀参与商品 Base VO,提供给添加、修改、详细的子 VO 使用
+ * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
+ *
+ * @author HUIHUI
+ */
+@Data
+public class SeckillProductBaseVO {
+
+    @Schema(description = "商品spu_id", requiredMode = Schema.RequiredMode.REQUIRED, example = "30563")
+    @NotNull(message = "商品spu_id不能为空")
+    private Long spuId;
+
+    @Schema(description = "商品sku_id", requiredMode = Schema.RequiredMode.REQUIRED, example = "30563")
+    @NotNull(message = "商品sku_id不能为空")
+    private Long skuId;
+
+    @Schema(description = "秒杀金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "6689")
+    @NotNull(message = "秒杀金额,单位:分不能为空")
+    private Integer seckillPrice;
+
+    @Schema(description = "秒杀库存", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "秒杀库存不能为空")
+    private Integer stock;
+
+
+}

+ 20 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductCreateReqVO.java

@@ -0,0 +1,20 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product;
+
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO;
+import lombok.*;
+import java.util.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import javax.validation.constraints.*;
+
+/**
+ * 管理后台 - 秒杀参与商品创建 Request VO
+ *
+ * @author HUIHUI
+ */
+@Schema(description = "管理后台 - 秒杀参与商品创建 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class SeckillProductCreateReqVO extends SeckillProductBaseVO {
+
+}

+ 24 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductRespVO.java

@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.time.LocalDateTime;
+
+/**
+ * 管理后台 - 秒杀参与商品 Response VO
+ *
+ * @author HUIHUI
+ */
+@Schema(description = "管理后台 - 秒杀参与商品 Response VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class SeckillProductRespVO extends SeckillProductBaseVO {
+
+    @Schema(description = "秒杀参与商品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "256")
+    private Long id;
+
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    private LocalDateTime createTime;
+
+}

+ 22 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductUpdateReqVO.java

@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import javax.validation.constraints.*;
+
+/**
+ * 管理后台 - 秒杀参与商品更新 Request VO
+ *
+ * @author HUIHUI
+ */
+@Schema(description = "管理后台 - 秒杀参与商品更新 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class SeckillProductUpdateReqVO extends SeckillProductBaseVO {
+
+    @Schema(description = "秒杀参与商品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "256")
+    @NotNull(message = "秒杀参与商品编号不能为空")
+    private Long id;
+
+}

+ 6 - 5
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/vo/AppActivityRespVO.java

@@ -9,19 +9,20 @@ import java.time.LocalDateTime;
 @Data
 public class AppActivityRespVO {
 
-    @Schema(description = "活动编号", required = true, example = "1024")
+    @Schema(description = "活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Long id;
 
-    @Schema(description = "活动类型", required = true, example = "1") // 对应 PromotionTypeEnum 枚举
+    @Schema(description = "活动类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    // 对应 PromotionTypeEnum 枚举
     private Integer type;
 
-    @Schema(description = "活动名称", required = true, example = "618 大促")
+    @Schema(description = "活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618 大促")
     private String name;
 
-    @Schema(description = "活动开始时间", required = true)
+    @Schema(description = "活动开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime startTime;
 
-    @Schema(description = "活动结束时间", required = true)
+    @Schema(description = "活动结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime endTime;
 
 }

+ 11 - 11
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/activity/AppCombinationActivityDetailRespVO.java

@@ -10,28 +10,28 @@ import java.util.List;
 @Data
 public class AppCombinationActivityDetailRespVO {
 
-    @Schema(description = "拼团活动编号", required = true, example = "1024")
+    @Schema(description = "拼团活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Long id;
 
-    @Schema(description = "拼团活动名称", required = true, example = "618 大拼团")
+    @Schema(description = "拼团活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618 大拼团")
     private String name;
 
-    @Schema(description = "活动状态", required = true, example = "1")
+    @Schema(description = "活动状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer status;
 
-    @Schema(description = "活动开始时间", required = true)
+    @Schema(description = "活动开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime startTime;
 
-    @Schema(description = "活动结束时间", required = true)
+    @Schema(description = "活动结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime endTime;
 
-    @Schema(description = "拼团人数", required = true, example = "3")
+    @Schema(description = "拼团人数", requiredMode = Schema.RequiredMode.REQUIRED, example = "3")
     private Integer userSize;
 
-    @Schema(description = "成功的拼团数量", required = true, example = "100")
+    @Schema(description = "成功的拼团数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
     private Integer successCount;
 
-    @Schema(description = "商品 SPU 编号", required = true, example = "2048")
+    @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
     private Long spuId;
 
     @Schema(description = "总共限购数量", example = "10")
@@ -40,17 +40,17 @@ public class AppCombinationActivityDetailRespVO {
     @Schema(description = "单次限购数量", example = "5")
     private Integer singleLimitCount;
 
-    @Schema(description = "商品信息数组", required = true)
+    @Schema(description = "商品信息数组", requiredMode = Schema.RequiredMode.REQUIRED)
     private List<Product> products;
 
     @Schema(description = "商品信息")
     @Data
     public static class Product {
 
-        @Schema(description = "商品 SKU 编号", required = true, example = "4096")
+        @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4096")
         private Long skuId;
 
-        @Schema(description = "拼团金额,单位:分", required = true, example = "100")
+        @Schema(description = "拼团金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
         private Integer combinationPrice;
 
     }

+ 10 - 7
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/activity/AppCombinationActivityRespVO.java

@@ -7,25 +7,28 @@ import lombok.Data;
 @Data
 public class AppCombinationActivityRespVO {
 
-    @Schema(description = "拼团活动编号", required = true, example = "1024")
+    @Schema(description = "拼团活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Long id;
 
-    @Schema(description = "拼团活动名称", required = true, example = "618 大拼团")
+    @Schema(description = "拼团活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618 大拼团")
     private String name;
 
-    @Schema(description = "拼团人数", required = true, example = "3")
+    @Schema(description = "拼团人数", requiredMode = Schema.RequiredMode.REQUIRED, example = "3")
     private Integer userSize;
 
-    @Schema(description = "商品 SPU 编号", required = true, example = "2048")
+    @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
     private Long spuId;
 
-    @Schema(description = "商品图片", required = true, example = "4096") // 从 SPU 的 picUrl 读取
+    @Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "4096")
+    // 从 SPU 的 picUrl 读取
     private String picUrl;
 
-    @Schema(description = "商品市场价,单位:分", required = true, example = "50") // 从 SPU 的 marketPrice 读取
+    @Schema(description = "商品市场价,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "50")
+    // 从 SPU 的 marketPrice 读取
     private Integer marketPrice;
 
-    @Schema(description = "拼团金额,单位:分", required = true, example = "100") // 从拼团商品里取最低价
+    @Schema(description = "拼团金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
+    // 从拼团商品里取最低价
     private Integer combinationPrice;
 
 }

+ 4 - 3
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/record/AppCombinationRecordDetailRespVO.java

@@ -9,13 +9,14 @@ import java.util.List;
 @Data
 public class AppCombinationRecordDetailRespVO {
 
-    @Schema(description = "团长的拼团记录", required = true)
+    @Schema(description = "团长的拼团记录", requiredMode = Schema.RequiredMode.REQUIRED)
     private AppCombinationRecordRespVO headRecord;
 
-    @Schema(description = "成员的拼团记录", required = true)
+    @Schema(description = "成员的拼团记录", requiredMode = Schema.RequiredMode.REQUIRED)
     private List<AppCombinationRecordRespVO> memberRecords;
 
-    @Schema(description = "当前用户参团记录对应的订单编号", required = true, example = "1024") // 如果没参团,返回 null
+    @Schema(description = "当前用户参团记录对应的订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+    // 如果没参团,返回 null
     private Long orderId;
 
 }

+ 11 - 11
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/record/AppCombinationRecordRespVO.java

@@ -9,37 +9,37 @@ import java.util.Date;
 @Data
 public class AppCombinationRecordRespVO {
 
-    @Schema(description = "拼团记录编号", required = true, example = "1024")
+    @Schema(description = "拼团记录编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Long id;
 
-    @Schema(description = "拼团活动编号", required = true, example = "1024")
+    @Schema(description = "拼团活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Long activityId;
 
-    @Schema(description = "用户昵称", required = true, example = "1024")
+    @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private String nickname;
 
-    @Schema(description = "用户头像", required = true, example = "1024")
+    @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private String avatar;
 
-    @Schema(description = "过期时间", required = true)
+    @Schema(description = "过期时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private Date expireTime;
 
-    @Schema(description = "可参团人数", required = true, example = "10")
+    @Schema(description = "可参团人数", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
     private Integer userSize;
 
-    @Schema(description = "已参团人数", required = true, example = "5")
+    @Schema(description = "已参团人数", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
     private Integer userCount;
 
-    @Schema(description = "拼团状态", required = true, example = "1")
+    @Schema(description = "拼团状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer status;
 
-    @Schema(description = "商品名字", required = true, example = "我是大黄豆")
+    @Schema(description = "商品名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是大黄豆")
     private String spuName;
 
-    @Schema(description = "商品图片", required = true, example = "https://www.iocoder.cn/1.png")
+    @Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
     private String picUrl;
 
-    @Schema(description = "拼团金额,单位:分", required = true, example = "100")
+    @Schema(description = "拼团金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
     private Integer combinationPrice;
 
 }

+ 2 - 2
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/record/AppCombinationRecordSummaryRespVO.java

@@ -9,10 +9,10 @@ import java.util.List;
 @Data
 public class AppCombinationRecordSummaryRespVO {
 
-    @Schema(description = "拼团用户数量", required = true, example = "1024")
+    @Schema(description = "拼团用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Integer userCount;
 
-    @Schema(description = "拼团用户头像列表", required = true) // 只返回最近的 7 个
+    @Schema(description = "拼团用户头像列表", requiredMode = Schema.RequiredMode.REQUIRED) // 只返回最近的 7 个
     private List<String> avatars;
 
 }

+ 9 - 8
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/template/AppCouponTemplateRespVO.java

@@ -10,27 +10,28 @@ import java.time.LocalDateTime;
 @Data
 public class AppCouponTemplateRespVO {
 
-    @Schema(description = "优惠劵模板编号", required = true, example = "1")
+    @Schema(description = "优惠劵模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Long id;
 
-    @Schema(description = "优惠劵名", required = true, example = "春节送送送")
+    @Schema(description = "优惠劵名", requiredMode = Schema.RequiredMode.REQUIRED, example = "春节送送送")
     private String name;
 
-    @Schema(description = "每人限领个数", required = true, example = "66") // -1 - 则表示不限制
+    @Schema(description = "每人限领个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "66") // -1 - 则表示不限制
     private Integer takeLimitCount;
 
-    @Schema(description = "是否设置满多少金额可用", required = true, example = "100") // 单位:分;0 - 不限制
+    @Schema(description = "是否设置满多少金额可用", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
+    // 单位:分;0 - 不限制
     private Integer usePrice;
 
     // TODO 芋艿:这两要改的
-//    @Schema(description = "商品范围", required = true, example = "1")
+//    @Schema(description = "商品范围", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
 //    @InEnum(PromotionProductScopeEnum.class)
 //    private Integer productScope;
 //
 //    @Schema(description = "商品 SPU 编号的数组", example = "1,3")
 //    private List<Long> productSpuIds;
 
-    @Schema(description = "生效日期类型", required = true, example = "1")
+    @Schema(description = "生效日期类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer validityType;
 
     @Schema(description = "固定日期 - 生效开始时间")
@@ -47,7 +48,7 @@ public class AppCouponTemplateRespVO {
     @Min(value = 1L, message = "开始天数必须大于 1")
     private Integer fixedEndTerm;
 
-    @Schema(description = "优惠类型", required = true, example = "1")
+    @Schema(description = "优惠类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer discountType;
 
     @Schema(description = "折扣百分比", example = "80") //  例如说,80% 为 80
@@ -62,7 +63,7 @@ public class AppCouponTemplateRespVO {
 
     // ========== 用户相关字段 ==========
 
-    @Schema(description = "是否已领取", required = true, example = "true")
+    @Schema(description = "是否已领取", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
     private Boolean takeStatus;
 
 }

+ 12 - 12
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillActivityDetailRespVO.java

@@ -10,24 +10,24 @@ import java.util.List;
 @Data
 public class AppSeckillActivityDetailRespVO {
 
-    @Schema(description = "秒杀活动编号", required = true, example = "1024")
+    @Schema(description = "秒杀活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Long id;
 
-    @Schema(description = "秒杀活动名称", required = true, example = "晚九点限时秒杀")
+    @Schema(description = "秒杀活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "晚九点限时秒杀")
     private String name;
 
-    @Schema(description = "活动状态", required = true, example = "1")
+    @Schema(description = "活动状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer status;
 
     // TODO @芋艿:开始时间、结束时间,要和场次结合起来;就是要算到当前场次,是几点哈;
 
-    @Schema(description = "活动开始时间", required = true)
+    @Schema(description = "活动开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime startTime;
 
-    @Schema(description = "活动结束时间", required = true)
+    @Schema(description = "活动结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime endTime;
 
-    @Schema(description = "商品 SPU 编号", required = true, example = "2048")
+    @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
     private Long spuId;
 
     @Schema(description = "总共限购数量", example = "10")
@@ -36,26 +36,26 @@ public class AppSeckillActivityDetailRespVO {
     @Schema(description = "单次限购数量", example = "5")
     private Integer singleLimitCount;
 
-    @Schema(description = "秒杀库存(剩余)", required = true, example = "50")
+    @Schema(description = "秒杀库存(剩余)", requiredMode = Schema.RequiredMode.REQUIRED, example = "50")
     private Integer stock;
 
-    @Schema(description = "秒杀库存(总计)", required = true, example = "100")
+    @Schema(description = "秒杀库存(总计)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
     private Integer totalStock;
 
-    @Schema(description = "商品信息数组", required = true)
+    @Schema(description = "商品信息数组", requiredMode = Schema.RequiredMode.REQUIRED)
     private List<Product> products;
 
     @Schema(description = "商品信息")
     @Data
     public static class Product {
 
-        @Schema(description = "商品 SKU 编号", required = true, example = "4096")
+        @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4096")
         private Long skuId;
 
-        @Schema(description = "秒杀金额,单位:分", required = true, example = "100")
+        @Schema(description = "秒杀金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
         private Integer seckillPrice;
 
-        @Schema(description = "秒杀限量库存", required = true, example = "50")
+        @Schema(description = "秒杀限量库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "50")
         private Integer stock;
 
     }

+ 2 - 2
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillActivityNowRespVO.java

@@ -10,10 +10,10 @@ import java.util.List;
 @Data
 public class AppSeckillActivityNowRespVO {
 
-    @Schema(description = "秒杀时间段", required = true)
+    @Schema(description = "秒杀时间段", requiredMode = Schema.RequiredMode.REQUIRED)
     private AppSeckillConfigRespVO config;
 
-    @Schema(description = "秒杀活动数组", required = true)
+    @Schema(description = "秒杀活动数组", requiredMode = Schema.RequiredMode.REQUIRED)
     private List<AppSeckillActivityRespVO> activities;
 
 }

+ 11 - 8
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillActivityRespVO.java

@@ -7,28 +7,31 @@ import lombok.Data;
 @Data
 public class AppSeckillActivityRespVO {
 
-    @Schema(description = "秒杀活动编号", required = true, example = "1024")
+    @Schema(description = "秒杀活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Long id;
 
-    @Schema(description = "秒杀活动名称", required = true, example = "晚九点限时秒杀")
+    @Schema(description = "秒杀活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "晚九点限时秒杀")
     private String name;
 
-    @Schema(description = "商品 SPU 编号", required = true, example = "2048")
+    @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
     private Long spuId;
 
-    @Schema(description = "商品图片", required = true, example = "4096") // 从 SPU 的 picUrl 读取
+    @Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "4096")
+    // 从 SPU 的 picUrl 读取
     private String picUrl;
     @Schema(description = "单位名", requiredMode = Schema.RequiredMode.REQUIRED, example = "个")
     private String unitName;
-    @Schema(description = "商品市场价,单位:分", required = true, example = "50") // 从 SPU 的 marketPrice 读取
+    @Schema(description = "商品市场价,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "50")
+    // 从 SPU 的 marketPrice 读取
     private Integer marketPrice;
 
-    @Schema(description = "秒杀库存(剩余)", required = true, example = "100")
+    @Schema(description = "秒杀库存(剩余)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
     private Integer stock;
-    @Schema(description = "秒杀库存(总共)", required = true, example = "200")
+    @Schema(description = "秒杀库存(总共)", requiredMode = Schema.RequiredMode.REQUIRED, example = "200")
     private Integer totalStock;
 
-    @Schema(description = "秒杀金额,单位:分", required = true, example = "100") // 从秒杀商品里取最低价
+    @Schema(description = "秒杀金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
+    // 从秒杀商品里取最低价
     private Integer seckillPrice;
 
 }

+ 4 - 4
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/config/AppSeckillConfigRespVO.java

@@ -9,15 +9,15 @@ import java.util.List;
 @Data
 public class AppSeckillConfigRespVO {
 
-    @Schema(description = "秒杀时间段编号", required = true, example = "1024")
+    @Schema(description = "秒杀时间段编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Long id;
 
-    @Schema(description = "开始时间点", required = true, example = "09:00")
+    @Schema(description = "开始时间点", requiredMode = Schema.RequiredMode.REQUIRED, example = "09:00")
     private String startTime;
-    @Schema(description = "结束时间点", required = true, example = "09:59")
+    @Schema(description = "结束时间点", requiredMode = Schema.RequiredMode.REQUIRED, example = "09:59")
     private String endTime;
 
-    @Schema(description = "轮播图", required = true)
+    @Schema(description = "轮播图", requiredMode = Schema.RequiredMode.REQUIRED)
     private List<String> sliderPicUrls;
 
 }

+ 31 - 23
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java

@@ -1,16 +1,19 @@
 package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity;
 
 import cn.hutool.core.util.ObjectUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
-import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.*;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityDetailRespVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityRespVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductCreateReqVO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
 import org.mapstruct.Mapper;
-import org.mapstruct.Mapping;
-import org.mapstruct.Mappings;
 import org.mapstruct.factory.Mappers;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -23,15 +26,10 @@ public interface SeckillActivityConvert {
 
     SeckillActivityConvert INSTANCE = Mappers.getMapper(SeckillActivityConvert.class);
 
-    SeckillProductDO convert(SeckillActivityBaseVO.Product product);
-
+    SeckillProductDO convert(SeckillProductCreateReqVO product);
 
     SeckillActivityDO convert(SeckillActivityCreateReqVO bean);
 
-    default String map(Long[] value) {
-        return value.toString();
-    }
-
     SeckillActivityDO convert(SeckillActivityUpdateReqVO bean);
 
     SeckillActivityRespVO convert(SeckillActivityDO bean);
@@ -40,7 +38,6 @@ public interface SeckillActivityConvert {
 
     PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page);
 
-    @Mappings({@Mapping(target = "products", source = "seckillProducts")})
     SeckillActivityDetailRespVO convert(SeckillActivityDO seckillActivity, List<SeckillProductDO> seckillProducts);
 
 
@@ -51,12 +48,12 @@ public interface SeckillActivityConvert {
      * @param productVO 前端传入的商品
      * @return 是否匹配
      */
-    default boolean isEquals(SeckillProductDO productDO, SeckillActivityBaseVO.Product productVO) {
-        return ObjectUtil.equals(productDO.getSpuId(), productVO.getSpuId())
+    default boolean isEquals(SeckillProductDO productDO, SeckillProductCreateReqVO productVO) {
+        return ObjectUtil.equals(productDO.getSpuId(), 1) // TODO puhui:再看看
                 && ObjectUtil.equals(productDO.getSkuId(), productVO.getSkuId())
-                && ObjectUtil.equals(productDO.getSeckillPrice(), productVO.getSeckillPrice())
-                && ObjectUtil.equals(productDO.getStock(), productVO.getStock())
-                && ObjectUtil.equals(productDO.getLimitCount(), productVO.getLimitCount());
+                && ObjectUtil.equals(productDO.getSeckillPrice(), productVO.getSeckillPrice());
+        //&& ObjectUtil.equals(productDO.getQuota(), productVO.getQuota())
+        //&& ObjectUtil.equals(productDO.getLimitCount(), productVO.getLimitCount());
     }
 
     /**
@@ -69,15 +66,26 @@ public interface SeckillActivityConvert {
     default boolean isEquals(SeckillProductDO productDO, SeckillProductDO productVO) {
         return ObjectUtil.equals(productDO.getSpuId(), productVO.getSpuId())
                 && ObjectUtil.equals(productDO.getSkuId(), productVO.getSkuId())
-                && ObjectUtil.equals(productDO.getSeckillPrice(), productVO.getSeckillPrice())
-                && ObjectUtil.equals(productDO.getStock(), productVO.getStock())
-                && ObjectUtil.equals(productDO.getLimitCount(), productVO.getLimitCount());
+                && ObjectUtil.equals(productDO.getSeckillPrice(), productVO.getSeckillPrice());
+        //&& ObjectUtil.equals(productDO.getQuota(), productVO.getQuota())
+        //&& ObjectUtil.equals(productDO.getLimitCount(), productVO.getLimitCount());
 
     }
 
-    default List<SeckillProductDO> convertList(List<SeckillActivityBaseVO.Product> products, SeckillActivityDO seckillActivity) {
-        return CollectionUtils.convertList(products, product -> convert(product)
-                .setActivityId(seckillActivity.getId()).setTimeIds(seckillActivity.getTimeIds()));
+    default List<SeckillProductDO> convertList(SeckillActivityDO seckillActivity, List<SeckillProductCreateReqVO> products) {
+        List<SeckillProductDO> list = new ArrayList<>();
+        products.forEach(sku -> {
+            SeckillProductDO productDO = new SeckillProductDO();
+            productDO.setActivityId(seckillActivity.getId());
+            productDO.setConfigIds(seckillActivity.getConfigIds());
+            productDO.setSpuId(sku.getSpuId());
+            productDO.setSkuId(sku.getSkuId());
+            productDO.setSeckillPrice(sku.getSeckillPrice());
+            productDO.setStock(sku.getStock());
+            productDO.setActivityStatus(CommonStatusEnum.ENABLE.getStatus());
+            productDO.setActivityStartTime(seckillActivity.getStartTime());
+            productDO.setActivityEndTime(seckillActivity.getEndTime());
+        });
+        return list;
     }
-
 }

+ 36 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillconfig/SeckillConfigConvert.java

@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.module.promotion.convert.seckill.seckillconfig;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigCreateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigRespVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigSimpleRespVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+
+/**
+ * 秒杀时段 Convert
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface SeckillConfigConvert {
+
+    SeckillConfigConvert INSTANCE = Mappers.getMapper(SeckillConfigConvert.class);
+
+    SeckillConfigDO convert(SeckillConfigCreateReqVO bean);
+
+    SeckillConfigDO convert(SeckillConfigUpdateReqVO bean);
+
+    SeckillConfigRespVO convert(SeckillConfigDO bean);
+
+    List<SeckillConfigRespVO> convertList(List<SeckillConfigDO> list);
+
+    List<SeckillConfigSimpleRespVO> convertList1(List<SeckillConfigDO> list);
+
+    PageResult<SeckillConfigRespVO> convertPage(PageResult<SeckillConfigDO> page);
+
+}

+ 0 - 34
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckilltime/SeckillTimeConvert.java

@@ -1,34 +0,0 @@
-package cn.iocoder.yudao.module.promotion.convert.seckill.seckilltime;
-
-import java.util.*;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-
-import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeCreateReqVO;
-import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeRespVO;
-import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeUpdateReqVO;
-import org.mapstruct.Mapper;
-import org.mapstruct.factory.Mappers;
-import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime.SeckillTimeDO;
-
-/**
- * 秒杀时段 Convert
- *
- * @author 芋道源码
- */
-@Mapper
-public interface SeckillTimeConvert {
-
-    SeckillTimeConvert INSTANCE = Mappers.getMapper(SeckillTimeConvert.class);
-
-    SeckillTimeDO convert(SeckillTimeCreateReqVO bean);
-
-    SeckillTimeDO convert(SeckillTimeUpdateReqVO bean);
-
-    SeckillTimeRespVO convert(SeckillTimeDO bean);
-
-    List<SeckillTimeRespVO> convertList(List<SeckillTimeDO> list);
-
-    PageResult<SeckillTimeRespVO> convertPage(PageResult<SeckillTimeDO> page);
-
-}

+ 25 - 4
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillActivityDO.java

@@ -1,8 +1,8 @@
 package cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity;
 
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
-import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum;
 import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
@@ -31,6 +31,11 @@ public class SeckillActivityDO extends BaseDO {
      */
     @TableId
     private Long id;
+    /**
+     * 秒杀活动商品
+     */
+    @TableField(typeHandler = LongListTypeHandler.class)
+    private List<Long> spuIds;
     /**
      * 秒杀活动名称
      */
@@ -38,7 +43,7 @@ public class SeckillActivityDO extends BaseDO {
     /**
      * 活动状态
      *
-     * 枚举 {@link PromotionActivityStatusEnum 对应的类}
+     * 枚举 {@link CommonStatusEnum 对应的类}
      */
     private Integer status;
     /**
@@ -61,9 +66,9 @@ public class SeckillActivityDO extends BaseDO {
      * 秒杀时段 id
      */
     @TableField(typeHandler = LongListTypeHandler.class)
-    private List<Long> timeIds;
+    private List<Long> configIds;
     /**
-     * 付款订单数
+     * 新增订单数
      */
     private Integer orderCount;
     /**
@@ -74,5 +79,21 @@ public class SeckillActivityDO extends BaseDO {
      * 订单实付金额,单位:分
      */
     private Long totalPrice;
+    /**
+     * 总限购数量
+     */
+    private Integer totalLimitCount;
+    /**
+     * 单次限够数量
+     */
+    private Integer singleLimitCount;
+    /**
+     * 秒杀库存
+     */
+    private Integer stock;
+    /**
+     * 秒杀总库存
+     */
+    private Integer totalStock;
 
 }

+ 32 - 25
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillProductDO.java

@@ -1,67 +1,74 @@
 package cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity;
 
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
-import com.baomidou.mybatisplus.annotation.*;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
 
+import java.time.LocalDateTime;
 import java.util.List;
 
 /**
- * 秒杀参与商品
+ * 秒杀参与商品 DO
  *
- * @author halfninety
- * @TableName promotion_seckill_product
+ * @author HUIHUI
  */
-@TableName(value = "promotion_seckill_product", autoResultMap = true)
+@TableName("promotion_seckill_product")
 @KeySequence("promotion_seckill_product_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
 public class SeckillProductDO extends BaseDO {
+
     /**
      * 秒杀参与商品编号
      */
-    @TableId(type = IdType.AUTO)
+    @TableId
     private Long id;
-
     /**
-     * 秒杀活动id
+     * 秒杀活动 id
      */
     private Long activityId;
-
     /**
-     * 秒杀时段id
+     * 秒杀时段 id
      */
     @TableField(typeHandler = LongListTypeHandler.class)
-    private List<Long> timeIds;
-
+    private List<Long> configIds;
     /**
-     * 商品id
+     * 商品 spu_id
      */
     private Long spuId;
-
     /**
-     * 商品sku_id
+     * 商品 sku_id
      */
     private Long skuId;
-
     /**
-     * 秒杀金额
+     * 秒杀金额,单位:分
      */
     private Integer seckillPrice;
-
-    // TODO @芋艿:改成 quota 限量库存;每次购买时,需要减小;
     /**
      * 秒杀库存
      */
     private Integer stock;
-
     /**
-     * 每人限购
+     * 秒杀商品状态
+     * 枚举 {@link CommonStatusEnum 对应的类}
+     */
+    private Integer activityStatus;
+    /**
+     * 活动开始时间点
+     */
+    private LocalDateTime activityStartTime;
+    /**
+     * 活动结束时间点
      */
-    private Integer limitCount;
+    private LocalDateTime activityEndTime;
 
 }

+ 15 - 10
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckilltime/SeckillTimeDO.java → yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillconfig/SeckillConfigDO.java

@@ -1,5 +1,6 @@
-package cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime;
+package cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig;
 
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.annotation.TableId;
@@ -8,19 +9,17 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.ToString;
 
-import java.time.LocalTime;
-
 /**
  * 秒杀时段 DO
  *
  * @author 芋道源码
  */
-@TableName("promotion_seckill_time")
-@KeySequence("promotion_seckill_time_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@TableName("promotion_seckill_config")
+@KeySequence("promotion_seckill_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
-public class SeckillTimeDO extends BaseDO {
+public class SeckillConfigDO extends BaseDO {
 
     /**
      * 编号
@@ -34,14 +33,20 @@ public class SeckillTimeDO extends BaseDO {
     /**
      * 开始时间点
      */
-    private LocalTime startTime;
+    private String startTime;
     /**
      * 结束时间点
      */
-    private LocalTime endTime;
+    private String endTime;
+    /**
+     * 秒杀主图
+     */
+    private String picUrl;
     /**
-     * 秒杀活动数量
+     * 状态 开启:0 禁用:1
+     * <p>
+     * 枚举 {@link CommonStatusEnum 对应的类}
      */
-    private Integer seckillActivityCount;
+    private Integer status;
 
 }

+ 8 - 1
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java

@@ -8,6 +8,8 @@ import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.Se
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
 import org.apache.ibatis.annotations.Mapper;
 
+import java.util.List;
+
 /**
  * 秒杀活动 Mapper
  *
@@ -20,7 +22,12 @@ public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> {
                 .likeIfPresent(SeckillActivityDO::getName, reqVO.getName())
                 .eqIfPresent(SeckillActivityDO::getStatus, reqVO.getStatus())
                 .betweenIfPresent(SeckillActivityDO::getCreateTime, reqVO.getCreateTime())
-                .apply(ObjectUtil.isNotNull(reqVO.getTimeId()),"FIND_IN_SET(" + reqVO.getTimeId() + ",time_ids) > 0")
+                .apply(ObjectUtil.isNotNull(reqVO.getConfigId()), "FIND_IN_SET(" + reqVO.getConfigId() + ",time_ids) > 0")
                 .orderByDesc(SeckillActivityDO::getId));
     }
+
+    default List<SeckillActivityDO> selectListByStatus(Integer status) {
+        return selectList(new LambdaQueryWrapperX<SeckillActivityDO>()
+                .eqIfPresent(SeckillActivityDO::getStatus, status));
+    }
 }

+ 1 - 1
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java

@@ -27,7 +27,7 @@ public interface SeckillProductMapper extends BaseMapperX<SeckillProductDO> {
 
     default void updateTimeIdsByActivityId(Long id, List<Long> timeIds) {
         new LambdaUpdateChainWrapper<>(this)
-                .set(SeckillProductDO::getTimeIds, CollUtil.join(timeIds, ","))
+                .set(SeckillProductDO::getConfigIds, CollUtil.join(timeIds, ","))
                 .eq(SeckillProductDO::getActivityId, id)
                 .update();
     }

+ 20 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillconfig/SeckillConfigMapper.java

@@ -0,0 +1,20 @@
+package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillconfig;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigPageReqVO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface SeckillConfigMapper extends BaseMapperX<SeckillConfigDO> {
+
+    default PageResult<SeckillConfigDO> selectPage(SeckillConfigPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<SeckillConfigDO>()
+                .likeIfPresent(SeckillConfigDO::getName, reqVO.getName())
+                .eqIfPresent(SeckillConfigDO::getStatus, reqVO.getStatus())
+                .orderByDesc(SeckillConfigDO::getId));
+    }
+
+}

+ 0 - 32
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckilltime/SeckillTimeMapper.java

@@ -1,32 +0,0 @@
-package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckilltime;
-
-import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
-import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime.SeckillTimeDO;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
-import org.apache.ibatis.annotations.Mapper;
-
-import java.time.LocalTime;
-import java.util.Collection;
-import java.util.List;
-
-@Mapper
-public interface SeckillTimeMapper extends BaseMapperX<SeckillTimeDO> {
-
-    default List<SeckillTimeDO> selectListByTime(LocalTime time) {
-        return selectList(SeckillTimeDO::getStartTime, SeckillTimeDO::getEndTime, time);
-    }
-
-    default List<SeckillTimeDO> selectListByTime(LocalTime startTime, LocalTime endTime) {
-        return selectList(new LambdaQueryWrapper<SeckillTimeDO>()
-                .ge(SeckillTimeDO::getStartTime, startTime)
-                .le(SeckillTimeDO::getEndTime, endTime));
-    }
-
-    default void updateActivityCount(Collection<Long> ids, String type, Integer count) {
-        new LambdaUpdateChainWrapper<>(this)
-                .in(SeckillTimeDO::getId, ids)
-                .setSql("`seckill_activity_count` = `seckill_activity_count` " + type + count)
-                .update();
-    }
-}

+ 2 - 2
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java

@@ -52,7 +52,7 @@ public class DiscountActivityServiceImpl implements DiscountActivityService {
 
         // 插入活动
         DiscountActivityDO discountActivity = DiscountActivityConvert.INSTANCE.convert(createReqVO)
-                .setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getStartTime(), createReqVO.getEndTime()));
+                .setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getEndTime()));
         discountActivityMapper.insert(discountActivity);
         // 插入商品
         List<DiscountProductDO> discountProducts = convertList(createReqVO.getProducts(),
@@ -74,7 +74,7 @@ public class DiscountActivityServiceImpl implements DiscountActivityService {
 
         // 更新活动
         DiscountActivityDO updateObj = DiscountActivityConvert.INSTANCE.convert(updateReqVO)
-                .setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getStartTime(), updateReqVO.getEndTime()));
+                .setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getEndTime()));
         discountActivityMapper.updateById(updateObj);
         // 更新商品
         updateDiscountProduct(updateReqVO);

+ 2 - 2
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java

@@ -41,7 +41,7 @@ public class RewardActivityServiceImpl implements RewardActivityService {
 
         // 插入
         RewardActivityDO rewardActivity = RewardActivityConvert.INSTANCE.convert(createReqVO)
-                .setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getStartTime(), createReqVO.getEndTime()));
+                .setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getEndTime()));
         rewardActivityMapper.insert(rewardActivity);
         // 返回
         return rewardActivity.getId();
@@ -59,7 +59,7 @@ public class RewardActivityServiceImpl implements RewardActivityService {
 
         // 更新
         RewardActivityDO updateObj = RewardActivityConvert.INSTANCE.convert(updateReqVO)
-                .setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getStartTime(), updateReqVO.getEndTime()));
+                .setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getEndTime()));
         rewardActivityMapper.updateById(updateObj);
     }
 

+ 6 - 4
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityService.java

@@ -1,15 +1,16 @@
 package cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity;
 
-import java.util.*;
-import javax.validation.*;
-
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
 
+import javax.validation.Valid;
+import java.util.Collection;
+import java.util.List;
+
 /**
  * 秒杀活动 Service 接口
  *
@@ -77,4 +78,5 @@ public interface SeckillActivityService {
      * @return 活动商品列表
      */
     List<SeckillProductDO> getSeckillProductListByActivityId(Long id);
+
 }

+ 102 - 91
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java

@@ -1,19 +1,26 @@
 package cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
-import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityBaseVO;
+import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
+import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
+import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
+import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO;
 import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
 import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillActivityMapper;
 import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillProductMapper;
 import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum;
-import cn.iocoder.yudao.module.promotion.service.seckill.seckilltime.SeckillTimeService;
+import cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig.SeckillConfigService;
 import cn.iocoder.yudao.module.promotion.util.PromotionUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
@@ -21,8 +28,12 @@ import org.springframework.validation.annotation.Validated;
 import javax.annotation.Resource;
 import java.util.Collection;
 import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS;
+import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
 import static java.util.Arrays.asList;
 
@@ -34,75 +45,104 @@ import static java.util.Arrays.asList;
 @Service
 @Validated
 public class SeckillActivityServiceImpl implements SeckillActivityService {
+
     @Resource
     private SeckillActivityMapper seckillActivityMapper;
     @Resource
     private SeckillProductMapper seckillProductMapper;
     @Resource
-    private SeckillTimeService seckillTimeService;
+    private SeckillConfigService seckillConfigService;
+    @Resource
+    private ProductSpuApi productSpuApi;
+    @Resource
+    private ProductSkuApi productSkuApi;
 
     @Override
     public Long createSeckillActivity(SeckillActivityCreateReqVO createReqVO) {
-        // 校验商品是否冲突
-        validateSeckillActivityProductConflicts(null, createReqVO.getProducts());
-        // 校验秒杀时段是否存在
-        seckillTimeService.validateSeckillTimeExists(createReqVO.getTimeIds());
+        // 校验商品秒秒杀时段是否冲突
+        validateProductSpuSeckillConflict(createReqVO.getConfigIds(), createReqVO.getSpuIds());
+        // 校验商品 sku 是否存在
+        validateProductSkuExistence(createReqVO.getSpuIds(), createReqVO.getProducts());
 
         // 插入秒杀活动
         SeckillActivityDO seckillActivity = SeckillActivityConvert.INSTANCE.convert(createReqVO)
-                .setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getStartTime(), createReqVO.getEndTime()));
+                .setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getEndTime()));
         seckillActivityMapper.insert(seckillActivity);
         // 插入商品
-        List<SeckillProductDO> productDOS = SeckillActivityConvert.INSTANCE.convertList(createReqVO.getProducts(), seckillActivity);
-        seckillProductMapper.insertBatch(productDOS);
-        // 更新秒杀时段的秒杀活动数量
-        seckillTimeService.sekillActivityCountIncr(createReqVO.getTimeIds());
+        List<SeckillProductDO> productDOs = SeckillActivityConvert.INSTANCE.convertList(seckillActivity, createReqVO.getProducts());
+        seckillProductMapper.insertBatch(productDOs);
         return seckillActivity.getId();
     }
 
+    private <T extends SeckillProductBaseVO> void validateProductSkuExistence(List<Long> spuIds, List<T> products) {
+        Set<Long> convertedSpuIds = CollectionUtils.convertSet(products, T::getSpuId);
+        // 校验 spu 个数是否相等
+        if (ObjectUtil.notEqual(spuIds.size(), convertedSpuIds.size())) {
+            throw exception(SKU_NOT_EXISTS);
+        }
+        // 获取所选 spu下的所有 sku
+        List<ProductSkuRespDTO> skuRespDTOs = productSkuApi.getSkuListBySpuId(spuIds);
+        // 校验 sku 个数是否一致
+        Set<Long> skuIdsSet = CollectionUtils.convertSet(products, T::getSkuId);
+        Set<Long> skuIdsSet1 = CollectionUtils.convertSet(skuRespDTOs, ProductSkuRespDTO::getId);
+        if (ObjectUtil.notEqual(skuIdsSet.size(), skuIdsSet1.size())) {
+            throw exception(SKU_NOT_EXISTS);
+        }
+        // 校验 skuId 是否存在
+        if (!skuIdsSet1.containsAll(skuIdsSet) || !skuIdsSet.containsAll(skuIdsSet1)) {
+            throw exception(SKU_NOT_EXISTS);
+        }
+    }
+
+    private void validateProductSpuSeckillConflict(List<Long> configIds, List<Long> spuIds) {
+        // 校验秒杀时段是否存在
+        seckillConfigService.validateSeckillConfigExists(configIds);
+        // 校验商品 spu 是否存在
+        List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(spuIds);
+        if (ObjectUtil.notEqual(spuIds.size(), spuList.size())) {
+            throw exception(SPU_NOT_EXISTS);
+        }
+        // 查询所有开启的秒杀活动
+        List<SeckillActivityDO> activityDOs = seckillActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());
+        // 过滤出所有 spuIds 有交集的活动
+        List<SeckillActivityDO> doList = activityDOs.stream().filter(s -> {
+            // 判断 spu 是否有交集
+            List<Long> spuIdsClone = ArrayUtil.clone(s.getSpuIds());
+            spuIdsClone.retainAll(spuIds);
+            if (CollUtil.isEmpty(spuIdsClone)) {
+                return false;
+            }
+            // 判断秒杀时段是否有交集
+            List<Long> configIdsClone = ArrayUtil.clone(s.getConfigIds());
+            configIdsClone.retainAll(configIds);
+            return CollUtil.isNotEmpty(configIdsClone);
+        }).collect(Collectors.toList());
+        if (CollUtil.isNotEmpty(doList)) {
+            throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS);
+        }
+    }
+
     @Override
     public void updateSeckillActivity(SeckillActivityUpdateReqVO updateReqVO) {
         // 校验存在
         SeckillActivityDO seckillActivity = validateSeckillActivityExists(updateReqVO.getId());
-        if (PromotionActivityStatusEnum.CLOSE.getStatus().equals(seckillActivity.getStatus())) {
+        if (CommonStatusEnum.ENABLE.getStatus().equals(seckillActivity.getStatus())) {
             throw exception(SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED);
         }
         // 校验商品是否冲突
-        validateSeckillActivityProductConflicts(updateReqVO.getId(), updateReqVO.getProducts());
+        validateProductSpuSeckillConflict(updateReqVO.getConfigIds(), updateReqVO.getSpuIds());
+        // 校验商品 sku 是否存在
+        validateProductSkuExistence(updateReqVO.getSpuIds(), updateReqVO.getProducts());
 
         // 更新活动
         SeckillActivityDO updateObj = SeckillActivityConvert.INSTANCE.convert(updateReqVO)
-                .setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getStartTime(), updateReqVO.getEndTime()));
+                .setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getEndTime()));
         seckillActivityMapper.updateById(updateObj);
         // 更新商品
-        updateSeckillProduct(updateReqVO);
-        // 更新秒杀时段的秒杀活动数量
-        updateSeckillTimeActivityCount(seckillActivity, updateReqVO.getTimeIds());
+        //updateSeckillProduct(updateReqVO);
     }
 
 
-    /**
-     * 更新秒杀时段的秒杀活动数量
-     *
-     * @param seckillActivity 查询出的秒杀活动
-     * @param updateTimeIds   更新后的秒杀时段id列表
-     */
-    private void updateSeckillTimeActivityCount(SeckillActivityDO seckillActivity, List<Long> updateTimeIds) {
-        // 查询出 timeIds
-        List<Long> existsTimeIds = seckillActivity.getTimeIds();
-        // 需要减少的时间段
-        Collection<Long> reduceIds = CollUtil.filterNew(existsTimeIds, existsTimeId -> !updateTimeIds.contains(existsTimeId));
-        // 需要添加的时间段
-        updateTimeIds.removeIf(existsTimeIds::contains);
-        // 更新减少时间段和增加时间段
-        if (CollUtil.isNotEmpty(updateTimeIds)) {
-            seckillTimeService.sekillActivityCountIncr(updateTimeIds);
-        }
-        if (CollUtil.isNotEmpty(reduceIds)) {
-            seckillTimeService.sekillActivityCountDecr(reduceIds);
-        }
-    }
-
     /**
      * 更新秒杀商品
      * 后台查出的数据和前台查出的数据进行遍历,
@@ -113,57 +153,29 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
      * @param updateReqVO 更新的请求VO
      */
     private void updateSeckillProduct(SeckillActivityUpdateReqVO updateReqVO) {
-        List<SeckillProductDO> seckillProductDOS = seckillProductMapper.selectListByActivityId(updateReqVO.getId());
-        List<SeckillActivityBaseVO.Product> products = updateReqVO.getProducts();
-
-        // 计算需要删除的数据
-        List<Long> deleteIds = CollectionUtils.convertList(seckillProductDOS, SeckillProductDO::getId,
-                seckillProductDO -> products.stream()
-                        .noneMatch(product -> SeckillActivityConvert.INSTANCE.isEquals(seckillProductDO, product)));
-        if (CollUtil.isNotEmpty(deleteIds)) {
-            seckillProductMapper.deleteBatchIds(deleteIds);
-        }
-
-        // 计算需要新增的数据
-        List<SeckillProductDO> newSeckillProductDOs = CollectionUtils.convertList(products,
-                product -> SeckillActivityConvert.INSTANCE.convert(product).setActivityId(updateReqVO.getId()));
-        newSeckillProductDOs.removeIf(product -> seckillProductDOS.stream()
-                .anyMatch(seckillProduct -> SeckillActivityConvert.INSTANCE.isEquals(seckillProduct, product)));
-        if (CollUtil.isNotEmpty(newSeckillProductDOs)) {
-            seckillProductMapper.insertBatch(newSeckillProductDOs);
-        }
+        // TODO puhui999:后续完善
+        //List<SeckillProductDO> seckillProductDOs = seckillProductMapper.selectListByActivityId(updateReqVO.getId());
+        //List<SeckillProductUpdateReqVO> products = updateReqVO.getProducts();
+
+        ////计算需要删除的数据
+        //List<Long> deleteIds = CollectionUtils.convertList(seckillProductDOs, SeckillProductDO::getId,
+        //        seckillProductDO -> products.stream()
+        //                .noneMatch(product -> SeckillActivityConvert.INSTANCE.isEquals(seckillProductDO, product)));
+        //if (CollUtil.isNotEmpty(deleteIds)) {
+        //    seckillProductMapper.deleteBatchIds(deleteIds);
+        //}
+        //
+        //// 计算需要新增的数据
+        //List<SeckillProductDO> newSeckillProductDOs = CollectionUtils.convertList(products,
+        //        product -> SeckillActivityConvert.INSTANCE.convert(product).setActivityId(updateReqVO.getId()));
+        //newSeckillProductDOs.removeIf(product -> seckillProductDOs.stream()
+        //        .anyMatch(seckillProduct -> SeckillActivityConvert.INSTANCE.isEquals(seckillProduct, product)));
+        //if (CollUtil.isNotEmpty(newSeckillProductDOs)) {
+        //    seckillProductMapper.insertBatch(newSeckillProductDOs);
+        //}
 
         //全量更新当前活动商品的秒杀时段id列表(timeIds)
-        seckillProductMapper.updateTimeIdsByActivityId(updateReqVO.getId(), updateReqVO.getTimeIds());
-    }
-
-    /**
-     * 校验商品是否冲突
-     *
-     * @param id       秒杀活动编号
-     * @param products 商品列表
-     */
-    private void validateSeckillActivityProductConflicts(Long id, List<SeckillActivityBaseVO.Product> products) {
-        if (CollUtil.isEmpty(products)) {
-            return;
-        }
-        List<SeckillProductDO> seckillProductDOS = seckillProductMapper
-                .selectListBySkuIds(CollectionUtils.convertSet(products, SeckillActivityBaseVO.Product::getSkuId));
-        if (CollUtil.isEmpty(seckillProductDOS)) {
-            return;
-        }
-        List<SeckillActivityDO> seckillActivityDOS = seckillActivityMapper
-                .selectBatchIds(CollectionUtils.convertSet(seckillProductDOS, SeckillProductDO::getActivityId));
-        if (id != null) { // 排除自己这个活动
-            seckillActivityDOS.removeIf(item -> id.equals(item.getId()));
-        }
-        // 排除不满足 status 的活动
-        List<Integer> statuses = asList(PromotionActivityStatusEnum.WAIT.getStatus(), PromotionActivityStatusEnum.RUN.getStatus());
-        seckillActivityDOS.removeIf(item -> !statuses.contains(item.getStatus()));
-        // 如果非空,则说明冲突
-        if (CollUtil.isNotEmpty(seckillActivityDOS)) {
-            throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS);
-        }
+        seckillProductMapper.updateTimeIdsByActivityId(updateReqVO.getId(), updateReqVO.getConfigIds());
     }
 
     @Override
@@ -189,8 +201,7 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
         if (!statuses.contains(seckillActivity.getStatus())) {
             throw exception(SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END);
         }
-        // 更新秒杀时段的秒杀活动数量
-        seckillTimeService.sekillActivityCountDecr(seckillActivity.getTimeIds());
+
         // 删除
         seckillActivityMapper.deleteById(id);
     }

+ 87 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigService.java

@@ -0,0 +1,87 @@
+package cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigCreateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigPageReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
+
+import javax.validation.Valid;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 秒杀时段 Service 接口
+ *
+ * @author halfninety
+ */
+public interface SeckillConfigService {
+
+    /**
+     * 创建秒杀时段
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createSeckillConfig(@Valid SeckillConfigCreateReqVO createReqVO);
+
+    /**
+     * 更新秒杀时段
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateSeckillConfig(@Valid SeckillConfigUpdateReqVO updateReqVO);
+
+    /**
+     * 删除秒杀时段
+     *
+     * @param id 编号
+     */
+    void deleteSeckillConfig(Long id);
+
+    /**
+     * 获得秒杀时段
+     *
+     * @param id 编号
+     * @return 秒杀时段
+     */
+    SeckillConfigDO getSeckillConfig(Long id);
+
+    /**
+     * 获得所有秒杀时段列表
+     *
+     * @return 所有秒杀时段列表
+     */
+    List<SeckillConfigDO> getSeckillConfigList();
+
+    /**
+     * 校验秒杀时段是否存在
+     *
+     * @param timeIds 秒杀时段id集合
+     */
+    void validateSeckillConfigExists(Collection<Long> timeIds);
+
+
+    /**
+     * 获得秒杀时间段配置分页数据
+     *
+     * @param pageVO 分页请求参数
+     * @return 秒杀时段分页列表
+     */
+    PageResult<SeckillConfigDO> getSeckillConfigPage(SeckillConfigPageReqVO pageVO);
+
+    /**
+     * 获得所有正常状态的时段配置列表
+     *
+     * @return 秒杀时段列表
+     */
+    List<SeckillConfigDO> getListAllSimple();
+
+    /**
+     * 更新秒杀时段配置状态
+     *
+     * @param id     id
+     * @param status 状态
+     */
+    void updateSeckillConfigStatus(Long id, Integer status);
+}

+ 154 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigServiceImpl.java

@@ -0,0 +1,154 @@
+package cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigCreateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigPageReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.convert.seckill.seckillconfig.SeckillConfigConvert;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
+import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillconfig.SeckillConfigMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.time.LocalTime;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
+
+/**
+ * 秒杀时段 Service 实现类
+ *
+ * @author halfninety
+ */
+@Service
+@Validated
+public class SeckillConfigServiceImpl implements SeckillConfigService {
+
+    @Resource
+    private SeckillConfigMapper seckillConfigMapper;
+
+    @Override
+    public Long createSeckillConfig(SeckillConfigCreateReqVO createReqVO) {
+        // 校验时间段是否冲突
+        validateSeckillConfigConflict(createReqVO.getStartTime(), createReqVO.getEndTime());
+
+        // 插入
+        SeckillConfigDO seckillConfig = SeckillConfigConvert.INSTANCE.convert(createReqVO);
+        seckillConfigMapper.insert(seckillConfig);
+        // 返回
+        return seckillConfig.getId();
+    }
+
+    @Override
+    public void updateSeckillConfig(SeckillConfigUpdateReqVO updateReqVO) {
+        // 校验存在
+        validateSeckillConfigExists(updateReqVO.getId());
+        // 校验时间段是否冲突
+        validateSeckillConfigConflict(updateReqVO.getStartTime(), updateReqVO.getEndTime());
+
+        // 更新
+        SeckillConfigDO updateObj = SeckillConfigConvert.INSTANCE.convert(updateReqVO);
+        seckillConfigMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteSeckillConfig(Long id) {
+        // 校验存在
+        validateSeckillConfigExists(id);
+
+        // 删除
+        seckillConfigMapper.deleteById(id);
+    }
+
+    private void validateSeckillConfigExists(Long id) {
+        if (seckillConfigMapper.selectById(id) == null) {
+            throw exception(SECKILL_TIME_NOT_EXISTS);
+        }
+    }
+
+    /**
+     * 校验时间是否存在冲突
+     *
+     * @param startTime 开始时间
+     * @param endTime   结束时间
+     */
+    private void validateSeckillConfigConflict(String startTime, String endTime) {
+        LocalTime startTime1 = LocalTime.parse(startTime);
+        LocalTime endTime1 = LocalTime.parse(endTime);
+        // 检查选择的时间是否相等
+        if (startTime1.equals(endTime1)) {
+            throw exception(SECKILL_TIME_EQUAL);
+        }
+        // 检查开始时间是否在结束时间之前
+        if (startTime1.isAfter(endTime1)) {
+            throw exception(SECKILL_START_TIME_BEFORE_END_TIME);
+        }
+        // 查询出所有的时段配置
+        List<SeckillConfigDO> configDOs = seckillConfigMapper.selectList();
+        // 过滤出重叠的时段 ids
+        Set<Long> ids = configDOs.stream().filter((config) -> {
+            LocalTime startTime2 = LocalTime.parse(config.getStartTime());
+            LocalTime endTime2 = LocalTime.parse(config.getEndTime());
+            // 判断时间是否重叠
+            // 开始时间在已配置时段的结束时间之前 且 结束时间在已配置时段的开始时间之后 []
+            return startTime1.isBefore(endTime2) && endTime1.isAfter(startTime2)
+                    // 开始时间在已配置时段的开始时间之前 且 结束时间在已配置时段的开始时间之后 (] 或 ()
+                    || startTime1.isBefore(startTime2) && endTime1.isAfter(startTime2)
+                    // 开始时间在已配置时段的结束时间之前 且 结束时间在已配值时段的结束时间之后 [) 或 ()
+                    || startTime1.isBefore(endTime2) && endTime1.isAfter(endTime2);
+        }).map(SeckillConfigDO::getId).collect(Collectors.toSet());
+        if (CollUtil.isNotEmpty(ids)) {
+            throw exception(SECKILL_TIME_CONFLICTS);
+        }
+    }
+
+    @Override
+    public SeckillConfigDO getSeckillConfig(Long id) {
+        return seckillConfigMapper.selectById(id);
+    }
+
+    @Override
+    public List<SeckillConfigDO> getSeckillConfigList() {
+        return seckillConfigMapper.selectList();
+    }
+
+    @Override
+    public void validateSeckillConfigExists(Collection<Long> configIds) {
+        if (CollUtil.isEmpty(configIds)) {
+            throw exception(SECKILL_TIME_NOT_EXISTS);
+        }
+        if (seckillConfigMapper.selectBatchIds(configIds).size() != configIds.size()) {
+            throw exception(SECKILL_TIME_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public PageResult<SeckillConfigDO> getSeckillConfigPage(SeckillConfigPageReqVO pageVO) {
+        return seckillConfigMapper.selectPage(pageVO);
+    }
+
+    @Override
+    public List<SeckillConfigDO> getListAllSimple() {
+        return seckillConfigMapper.selectList(SeckillConfigDO::getStatus, CommonStatusEnum.ENABLE.getStatus());
+    }
+
+    @Override
+    public void updateSeckillConfigStatus(Long id, Integer status) {
+        // 校验秒杀时段是否存在
+        validateSeckillConfigExists(id);
+
+        SeckillConfigDO seckillConfigDO = new SeckillConfigDO();
+        seckillConfigDO.setId(id);
+        seckillConfigDO.setStatus(status);
+        // 更新状态
+        seckillConfigMapper.updateById(seckillConfigDO);
+    }
+
+}

+ 0 - 76
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckilltime/SeckillTimeService.java

@@ -1,76 +0,0 @@
-package cn.iocoder.yudao.module.promotion.service.seckill.seckilltime;
-
-import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeCreateReqVO;
-import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeUpdateReqVO;
-import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime.SeckillTimeDO;
-
-import javax.validation.Valid;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * 秒杀时段 Service 接口
- *
- * @author halfninety
- */
-public interface SeckillTimeService {
-
-    /**
-     * 创建秒杀时段
-     *
-     * @param createReqVO 创建信息
-     * @return 编号
-     */
-    Long createSeckillTime(@Valid SeckillTimeCreateReqVO createReqVO);
-
-    /**
-     * 更新秒杀时段
-     *
-     * @param updateReqVO 更新信息
-     */
-    void updateSeckillTime(@Valid SeckillTimeUpdateReqVO updateReqVO);
-
-    /**
-     * 删除秒杀时段
-     *
-     * @param id 编号
-     */
-    void deleteSeckillTime(Long id);
-
-    /**
-     * 获得秒杀时段
-     *
-     * @param id 编号
-     * @return 秒杀时段
-     */
-    SeckillTimeDO getSeckillTime(Long id);
-
-    /**
-     * 获得所有秒杀时段列表
-     *
-     * @return 所有秒杀时段列表
-     */
-    List<SeckillTimeDO> getSeckillTimeList();
-
-    /**
-     * 校验秒杀时段是否存在
-     *
-     * @param timeIds 秒杀时段id集合
-     */
-    void validateSeckillTimeExists(Collection<Long> timeIds);
-
-    /**
-     * 秒杀时段列表的秒杀活动数量加 1
-     *
-     * @param ids 秒杀时段id列表
-     */
-    void sekillActivityCountIncr(Collection<Long> ids);
-
-
-    /**
-     * 秒杀时段列表的秒杀活动数量减 1
-     *
-     * @param ids 秒杀时段id列表
-     */
-    void sekillActivityCountDecr(Collection<Long> ids);
-}

+ 0 - 124
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckilltime/SeckillTimeServiceImpl.java

@@ -1,124 +0,0 @@
-package cn.iocoder.yudao.module.promotion.service.seckill.seckilltime;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeCreateReqVO;
-import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeUpdateReqVO;
-import cn.iocoder.yudao.module.promotion.convert.seckill.seckilltime.SeckillTimeConvert;
-import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime.SeckillTimeDO;
-import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckilltime.SeckillTimeMapper;
-import org.springframework.stereotype.Service;
-import org.springframework.validation.annotation.Validated;
-
-import javax.annotation.Resource;
-import java.time.LocalTime;
-import java.util.Collection;
-import java.util.List;
-import java.util.Objects;
-
-import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_TIME_CONFLICTS;
-import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_TIME_NOT_EXISTS;
-
-/**
- * 秒杀时段 Service 实现类
- *
- * @author halfninety
- */
-@Service
-@Validated
-public class SeckillTimeServiceImpl implements SeckillTimeService {
-
-    @Resource
-    private SeckillTimeMapper seckillTimeMapper;
-
-    @Override
-    public Long createSeckillTime(SeckillTimeCreateReqVO createReqVO) {
-        // 校验时间段是否冲突
-        validateSeckillTimeConflict(null, createReqVO.getStartTime(), createReqVO.getEndTime());
-        // 插入
-        SeckillTimeDO seckillTime = SeckillTimeConvert.INSTANCE.convert(createReqVO);
-        seckillTimeMapper.insert(seckillTime);
-        // 返回
-        return seckillTime.getId();
-    }
-
-    @Override
-    public void updateSeckillTime(SeckillTimeUpdateReqVO updateReqVO) {
-        // 校验存在
-        this.validateSeckillTimeExists(updateReqVO.getId());
-        // 校验时间段是否冲突
-        validateSeckillTimeConflict(updateReqVO.getId(), updateReqVO.getStartTime(), updateReqVO.getEndTime());
-        // 更新
-        SeckillTimeDO updateObj = SeckillTimeConvert.INSTANCE.convert(updateReqVO);
-        seckillTimeMapper.updateById(updateObj);
-    }
-
-    @Override
-    public void deleteSeckillTime(Long id) {
-        // 校验存在
-        this.validateSeckillTimeExists(id);
-        // 删除
-        seckillTimeMapper.deleteById(id);
-    }
-
-    private void validateSeckillTimeExists(Long id) {
-        if (seckillTimeMapper.selectById(id) == null) {
-            throw exception(SECKILL_TIME_NOT_EXISTS);
-        }
-    }
-
-    /**
-     * 校验时间是否存在冲突
-     *
-     * @param startTime 开始时间
-     * @param endTime   结束时间
-     */
-    private void validateSeckillTimeConflict(Long id, LocalTime startTime, LocalTime endTime) {
-        //查询开始时间,结束时间,是否在别人的时间段内
-        List<SeckillTimeDO> startTimeList = seckillTimeMapper.selectListByTime(startTime);
-        List<SeckillTimeDO> endTimeList = seckillTimeMapper.selectListByTime(endTime);
-        //查询自己时间段内是否有时间段
-        List<SeckillTimeDO> startEndTimeList = seckillTimeMapper.selectListByTime(startTime, endTime);
-        if (id != null) {
-            //移除自己
-            startTimeList.removeIf(seckillTime -> Objects.equals(seckillTime.getId(), id));
-            endTimeList.removeIf(seckillTime -> Objects.equals(seckillTime.getId(), id));
-            startEndTimeList.removeIf(seckillTime -> Objects.equals(seckillTime.getId(), id));
-        }
-        if (CollUtil.isNotEmpty(startTimeList) || CollUtil.isNotEmpty(endTimeList)
-                || CollUtil.isNotEmpty(startEndTimeList)) {
-            throw exception(SECKILL_TIME_CONFLICTS);
-        }
-    }
-
-    @Override
-    public SeckillTimeDO getSeckillTime(Long id) {
-        return seckillTimeMapper.selectById(id);
-    }
-
-    @Override
-    public List<SeckillTimeDO> getSeckillTimeList() {
-        return seckillTimeMapper.selectList();
-    }
-
-    @Override
-    public void validateSeckillTimeExists(Collection<Long> timeIds) {
-        if (CollUtil.isEmpty(timeIds)) {
-            throw exception(SECKILL_TIME_NOT_EXISTS);
-        }
-        if (seckillTimeMapper.selectBatchIds(timeIds).size() != timeIds.size()) {
-            throw exception(SECKILL_TIME_NOT_EXISTS);
-        }
-    }
-
-    @Override
-    public void sekillActivityCountIncr(Collection<Long> ids) {
-        seckillTimeMapper.updateActivityCount(ids, "+", 1);
-    }
-
-    @Override
-    public void sekillActivityCountDecr(Collection<Long> ids) {
-        seckillTimeMapper.updateActivityCount(ids, "-", 1);
-    }
-
-}

+ 3 - 10
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/util/PromotionUtils.java

@@ -1,7 +1,7 @@
 package cn.iocoder.yudao.module.promotion.util;
 
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
-import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum;
 
 import java.time.LocalDateTime;
 
@@ -15,18 +15,11 @@ public class PromotionUtils {
     /**
      * 根据时间,计算活动状态
      *
-     * @param startTime 开始时间
      * @param endTime 结束时间
      * @return 活动状态
      */
-    public static Integer calculateActivityStatus(LocalDateTime startTime, LocalDateTime endTime) {
-        if (LocalDateTimeUtils.beforeNow(endTime)) {
-            return PromotionActivityStatusEnum.END.getStatus();
-        }
-        if (LocalDateTimeUtils.afterNow(startTime)) {
-            return PromotionActivityStatusEnum.WAIT.getStatus();
-        }
-        return PromotionActivityStatusEnum.RUN.getStatus();
+    public static Integer calculateActivityStatus(LocalDateTime endTime) {
+        return LocalDateTimeUtils.beforeNow(endTime) ? CommonStatusEnum.DISABLE.getStatus() : CommonStatusEnum.ENABLE.getStatus();
     }
 
 }

+ 23 - 23
yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckillactivity/SeckillActivityServiceImplTest.java

@@ -108,31 +108,31 @@ public class SeckillActivityServiceImplTest extends BaseDbUnitTest {
        SeckillActivityDO dbSeckillActivity = randomPojo(SeckillActivityDO.class, o -> { // 等会查询到
            o.setName(null);
            o.setStatus(null);
-           o.setTimeIds(null);
+           o.setConfigIds(null);
            o.setCreateTime(null);
        });
        seckillActivityMapper.insert(dbSeckillActivity);
        // 测试 name 不匹配
-       seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setName(null)));
-       // 测试 status 不匹配
-       seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setStatus(null)));
-       // 测试 timeId 不匹配
-       seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setTimeIds(null)));
-       // 测试 createTime 不匹配
-       seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setCreateTime(null)));
-       // 准备参数
-       SeckillActivityPageReqVO reqVO = new SeckillActivityPageReqVO();
-       reqVO.setName(null);
-       reqVO.setStatus(null);
-       reqVO.setTimeId(null);
-       reqVO.setCreateTime((new LocalDateTime[]{}));
-
-       // 调用
-       PageResult<SeckillActivityDO> pageResult = seckillActivityService.getSeckillActivityPage(reqVO);
-       // 断言
-       assertEquals(1, pageResult.getTotal());
-       assertEquals(1, pageResult.getList().size());
-       assertPojoEquals(dbSeckillActivity, pageResult.getList().get(0));
+        seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setName(null)));
+        // 测试 status 不匹配
+        seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setStatus(null)));
+        // 测试 timeId 不匹配
+        seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setConfigIds(null)));
+        // 测试 createTime 不匹配
+        seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setCreateTime(null)));
+        // 准备参数
+        SeckillActivityPageReqVO reqVO = new SeckillActivityPageReqVO();
+        reqVO.setName(null);
+        reqVO.setStatus(null);
+        reqVO.setConfigId(null);
+        reqVO.setCreateTime((new LocalDateTime[]{}));
+
+        // 调用
+        PageResult<SeckillActivityDO> pageResult = seckillActivityService.getSeckillActivityPage(reqVO);
+        // 断言
+        assertEquals(1, pageResult.getTotal());
+        assertEquals(1, pageResult.getList().size());
+        assertPojoEquals(dbSeckillActivity, pageResult.getList().get(0));
     }
 
     @Test
@@ -142,7 +142,7 @@ public class SeckillActivityServiceImplTest extends BaseDbUnitTest {
        SeckillActivityDO dbSeckillActivity = randomPojo(SeckillActivityDO.class, o -> { // 等会查询到
            o.setName(null);
            o.setStatus(null);
-           o.setTimeIds(null);
+           o.setConfigIds(null);
            o.setCreateTime(null);
        });
        seckillActivityMapper.insert(dbSeckillActivity);
@@ -151,7 +151,7 @@ public class SeckillActivityServiceImplTest extends BaseDbUnitTest {
        // 测试 status 不匹配
        seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setStatus(null)));
        // 测试 timeId 不匹配
-       seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setTimeIds(null)));
+        seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setConfigIds(null)));
        // 测试 createTime 不匹配
        seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setCreateTime(null)));
        // 准备参数

+ 190 - 0
yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckillconfig/SeckillConfigServiceImplTest.java

@@ -0,0 +1,190 @@
+package cn.iocoder.yudao.module.promotion.service.seckillconfig;
+
+import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigCreateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
+import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillconfig.SeckillConfigMapper;
+import cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig.SeckillConfigServiceImpl;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.annotation.Import;
+
+import javax.annotation.Resource;
+
+import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
+import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_TIME_NOT_EXISTS;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+/**
+ * {@link SeckillConfigServiceImpl} 的单元测试类
+ *
+ * @author 芋道源码
+ */
+@Import(SeckillConfigServiceImpl.class)
+@Disabled // TODO 芋艿:未来开启
+public class SeckillConfigServiceImplTest extends BaseDbUnitTest {
+
+    @Resource
+    private SeckillConfigServiceImpl SeckillConfigService;
+
+    @Resource
+    private SeckillConfigMapper seckillConfigMapper;
+
+    @Resource
+    private ObjectMapper objectMapper;
+
+    @Test
+    public void testJacksonSerializ() {
+
+        // 准备参数
+        SeckillConfigCreateReqVO reqVO = randomPojo(SeckillConfigCreateReqVO.class);
+//        ObjectMapper objectMapper = new ObjectMapper();
+        try {
+            String string = objectMapper.writeValueAsString(reqVO);
+            System.out.println(string);
+        } catch (JsonProcessingException e) {
+            e.printStackTrace();
+        }
+
+
+    }
+
+    @Test
+    public void testCreateSeckillConfig_success() {
+        // 准备参数
+        SeckillConfigCreateReqVO reqVO = randomPojo(SeckillConfigCreateReqVO.class);
+
+        // 调用
+        Long SeckillConfigId = SeckillConfigService.createSeckillConfig(reqVO);
+        // 断言
+        assertNotNull(SeckillConfigId);
+        // 校验记录的属性是否正确
+        SeckillConfigDO SeckillConfig = seckillConfigMapper.selectById(SeckillConfigId);
+        assertPojoEquals(reqVO, SeckillConfig);
+    }
+
+    @Test
+    public void testUpdateSeckillConfig_success() {
+        // mock 数据
+        SeckillConfigDO dbSeckillConfig = randomPojo(SeckillConfigDO.class);
+        seckillConfigMapper.insert(dbSeckillConfig);// @Sql: 先插入出一条存在的数据
+        // 准备参数
+        SeckillConfigUpdateReqVO reqVO = randomPojo(SeckillConfigUpdateReqVO.class, o -> {
+            o.setId(dbSeckillConfig.getId()); // 设置更新的 ID
+        });
+
+        // 调用
+        SeckillConfigService.updateSeckillConfig(reqVO);
+        // 校验是否更新正确
+        SeckillConfigDO SeckillConfig = seckillConfigMapper.selectById(reqVO.getId()); // 获取最新的
+        assertPojoEquals(reqVO, SeckillConfig);
+    }
+
+    @Test
+    public void testUpdateSeckillConfig_notExists() {
+        // 准备参数
+        SeckillConfigUpdateReqVO reqVO = randomPojo(SeckillConfigUpdateReqVO.class);
+
+        // 调用, 并断言异常
+        assertServiceException(() -> SeckillConfigService.updateSeckillConfig(reqVO), SECKILL_TIME_NOT_EXISTS);
+    }
+
+    @Test
+    public void testDeleteSeckillConfig_success() {
+        // mock 数据
+        SeckillConfigDO dbSeckillConfig = randomPojo(SeckillConfigDO.class);
+        seckillConfigMapper.insert(dbSeckillConfig);// @Sql: 先插入出一条存在的数据
+        // 准备参数
+        Long id = dbSeckillConfig.getId();
+
+        // 调用
+        SeckillConfigService.deleteSeckillConfig(id);
+        // 校验数据不存在了
+        assertNull(seckillConfigMapper.selectById(id));
+    }
+
+    @Test
+    public void testDeleteSeckillConfig_notExists() {
+        // 准备参数
+        Long id = randomLongId();
+
+        // 调用, 并断言异常
+        assertServiceException(() -> SeckillConfigService.deleteSeckillConfig(id), SECKILL_TIME_NOT_EXISTS);
+    }
+
+    @Test
+    @Disabled  // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
+    public void testGetSeckillConfigPage() {
+        // mock 数据
+//       SeckillConfigDO dbSeckillConfig = randomPojo(SeckillConfigDO.class, o -> { // 等会查询到
+//           o.setName(null);
+//           o.setStartTime(null);
+//           o.setEndTime(null);
+//           o.setCreateTime(null);
+//       });
+//       seckillConfigMapper.insert(dbSeckillConfig);
+//       // 测试 name 不匹配
+//       seckillConfigMapper.insert(cloneIgnoreId(dbSeckillConfig, o -> o.setName(null)));
+//       // 测试 startTime 不匹配
+//       seckillConfigMapper.insert(cloneIgnoreId(dbSeckillConfig, o -> o.setStartTime(null)));
+//       // 测试 endTime 不匹配
+//       seckillConfigMapper.insert(cloneIgnoreId(dbSeckillConfig, o -> o.setEndTime(null)));
+//       // 测试 createTime 不匹配
+//       seckillConfigMapper.insert(cloneIgnoreId(dbSeckillConfig, o -> o.setCreateTime(null)));
+//       // 准备参数
+//       SeckillConfigPageReqVO reqVO = new SeckillConfigPageReqVO();
+//       reqVO.setName(null);
+////       reqVO.setStartTime((new LocalTime()));
+////       reqVO.setEndTime((new LocalTime[]{}));
+////       reqVO.setCreateTime((new Date[]{}));
+//
+//       // 调用
+//       PageResult<SeckillConfigDO> pageResult = SeckillConfigService.getSeckillConfigPage(reqVO);
+//       // 断言
+//       assertEquals(1, pageResult.getTotal());
+//       assertEquals(1, pageResult.getList().size());
+//       assertPojoEquals(dbSeckillConfig, pageResult.getList().get(0));
+    }
+
+    @Test
+    @Disabled  // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
+    public void testGetSeckillConfigList() {
+        // mock 数据
+        SeckillConfigDO dbSeckillConfig = randomPojo(SeckillConfigDO.class, o -> { // 等会查询到
+            o.setName(null);
+            o.setStartTime(null);
+            o.setEndTime(null);
+            o.setCreateTime(null);
+        });
+        seckillConfigMapper.insert(dbSeckillConfig);
+        // 测试 name 不匹配
+        seckillConfigMapper.insert(cloneIgnoreId(dbSeckillConfig, o -> o.setName(null)));
+        // 测试 startTime 不匹配
+        seckillConfigMapper.insert(cloneIgnoreId(dbSeckillConfig, o -> o.setStartTime(null)));
+        // 测试 endTime 不匹配
+        seckillConfigMapper.insert(cloneIgnoreId(dbSeckillConfig, o -> o.setEndTime(null)));
+        // 测试 createTime 不匹配
+        seckillConfigMapper.insert(cloneIgnoreId(dbSeckillConfig, o -> o.setCreateTime(null)));
+        // 准备参数
+//       SeckillConfigExportReqVO reqVO = new SeckillConfigExportReqVO();
+//       reqVO.setName(null);
+//       reqVO.setStartTime((new LocalTime[]{}));
+//       reqVO.setEndTime((new LocalTime[]{}));
+//       reqVO.setCreateTime((new Date[]{}));
+//
+//       // 调用
+//       List<SeckillConfigDO> list = SeckillConfigService.getSeckillConfigList(reqVO);
+//       // 断言
+//       assertEquals(1, list.size());
+//       assertPojoEquals(dbSeckillConfig, list.get(0));
+    }
+
+}

+ 0 - 190
yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckilltime/SeckillTimeServiceImplTest.java

@@ -1,190 +0,0 @@
-package cn.iocoder.yudao.module.promotion.service.seckilltime;
-
-import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeCreateReqVO;
-import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeUpdateReqVO;
-import cn.iocoder.yudao.module.promotion.service.seckill.seckilltime.SeckillTimeServiceImpl;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-
-import javax.annotation.Resource;
-
-import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
-
-import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime.SeckillTimeDO;
-import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckilltime.SeckillTimeMapper;
-
-import org.springframework.context.annotation.Import;
-
-import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
-import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
-import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
-import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
-* {@link SeckillTimeServiceImpl} 的单元测试类
-*
-* @author 芋道源码
-*/
-@Import(SeckillTimeServiceImpl.class)
-@Disabled // TODO 芋艿:未来开启
-public class SeckillTimeServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private SeckillTimeServiceImpl seckillTimeService;
-
-    @Resource
-    private SeckillTimeMapper seckillTimeMapper;
-
-    @Resource
-    private ObjectMapper objectMapper;
-
-    @Test
-    public void testJacksonSerializ(){
-
-        // 准备参数
-        SeckillTimeCreateReqVO reqVO = randomPojo(SeckillTimeCreateReqVO.class);
-//        ObjectMapper objectMapper = new ObjectMapper();
-        try {
-            String string = objectMapper.writeValueAsString(reqVO);
-            System.out.println(string);
-        } catch (JsonProcessingException e) {
-            e.printStackTrace();
-        }
-
-
-    }
-
-    @Test
-    public void testCreateSeckillTime_success() {
-        // 准备参数
-        SeckillTimeCreateReqVO reqVO = randomPojo(SeckillTimeCreateReqVO.class);
-
-        // 调用
-        Long seckillTimeId = seckillTimeService.createSeckillTime(reqVO);
-        // 断言
-        assertNotNull(seckillTimeId);
-        // 校验记录的属性是否正确
-        SeckillTimeDO seckillTime = seckillTimeMapper.selectById(seckillTimeId);
-        assertPojoEquals(reqVO, seckillTime);
-    }
-
-    @Test
-    public void testUpdateSeckillTime_success() {
-        // mock 数据
-        SeckillTimeDO dbSeckillTime = randomPojo(SeckillTimeDO.class);
-        seckillTimeMapper.insert(dbSeckillTime);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        SeckillTimeUpdateReqVO reqVO = randomPojo(SeckillTimeUpdateReqVO.class, o -> {
-            o.setId(dbSeckillTime.getId()); // 设置更新的 ID
-        });
-
-        // 调用
-        seckillTimeService.updateSeckillTime(reqVO);
-        // 校验是否更新正确
-        SeckillTimeDO seckillTime = seckillTimeMapper.selectById(reqVO.getId()); // 获取最新的
-        assertPojoEquals(reqVO, seckillTime);
-    }
-
-    @Test
-    public void testUpdateSeckillTime_notExists() {
-        // 准备参数
-        SeckillTimeUpdateReqVO reqVO = randomPojo(SeckillTimeUpdateReqVO.class);
-
-        // 调用, 并断言异常
-        assertServiceException(() -> seckillTimeService.updateSeckillTime(reqVO), SECKILL_TIME_NOT_EXISTS);
-    }
-
-    @Test
-    public void testDeleteSeckillTime_success() {
-        // mock 数据
-        SeckillTimeDO dbSeckillTime = randomPojo(SeckillTimeDO.class);
-        seckillTimeMapper.insert(dbSeckillTime);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbSeckillTime.getId();
-
-        // 调用
-        seckillTimeService.deleteSeckillTime(id);
-       // 校验数据不存在了
-       assertNull(seckillTimeMapper.selectById(id));
-    }
-
-    @Test
-    public void testDeleteSeckillTime_notExists() {
-        // 准备参数
-        Long id = randomLongId();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> seckillTimeService.deleteSeckillTime(id), SECKILL_TIME_NOT_EXISTS);
-    }
-
-    @Test
-    @Disabled  // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
-    public void testGetSeckillTimePage() {
-       // mock 数据
-//       SeckillTimeDO dbSeckillTime = randomPojo(SeckillTimeDO.class, o -> { // 等会查询到
-//           o.setName(null);
-//           o.setStartTime(null);
-//           o.setEndTime(null);
-//           o.setCreateTime(null);
-//       });
-//       seckillTimeMapper.insert(dbSeckillTime);
-//       // 测试 name 不匹配
-//       seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setName(null)));
-//       // 测试 startTime 不匹配
-//       seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setStartTime(null)));
-//       // 测试 endTime 不匹配
-//       seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setEndTime(null)));
-//       // 测试 createTime 不匹配
-//       seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setCreateTime(null)));
-//       // 准备参数
-//       SeckillTimePageReqVO reqVO = new SeckillTimePageReqVO();
-//       reqVO.setName(null);
-////       reqVO.setStartTime((new LocalTime()));
-////       reqVO.setEndTime((new LocalTime[]{}));
-////       reqVO.setCreateTime((new Date[]{}));
-//
-//       // 调用
-//       PageResult<SeckillTimeDO> pageResult = seckillTimeService.getSeckillTimePage(reqVO);
-//       // 断言
-//       assertEquals(1, pageResult.getTotal());
-//       assertEquals(1, pageResult.getList().size());
-//       assertPojoEquals(dbSeckillTime, pageResult.getList().get(0));
-    }
-
-    @Test
-    @Disabled  // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
-    public void testGetSeckillTimeList() {
-       // mock 数据
-       SeckillTimeDO dbSeckillTime = randomPojo(SeckillTimeDO.class, o -> { // 等会查询到
-           o.setName(null);
-           o.setStartTime(null);
-           o.setEndTime(null);
-           o.setCreateTime(null);
-       });
-       seckillTimeMapper.insert(dbSeckillTime);
-       // 测试 name 不匹配
-       seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setName(null)));
-       // 测试 startTime 不匹配
-       seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setStartTime(null)));
-       // 测试 endTime 不匹配
-       seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setEndTime(null)));
-       // 测试 createTime 不匹配
-       seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setCreateTime(null)));
-       // 准备参数
-//       SeckillTimeExportReqVO reqVO = new SeckillTimeExportReqVO();
-//       reqVO.setName(null);
-//       reqVO.setStartTime((new LocalTime[]{}));
-//       reqVO.setEndTime((new LocalTime[]{}));
-//       reqVO.setCreateTime((new Date[]{}));
-//
-//       // 调用
-//       List<SeckillTimeDO> list = seckillTimeService.getSeckillTimeList(reqVO);
-//       // 断言
-//       assertEquals(1, list.size());
-//       assertPojoEquals(dbSeckillTime, list.get(0));
-    }
-
-}

+ 1 - 0
yudao-module-mall/yudao-module-promotion-biz/src/test/resources/sql/clean.sql

@@ -4,3 +4,4 @@ DELETE FROM "promotion_coupon";
 DELETE FROM "promotion_reward_activity";
 DELETE FROM "promotion_discount_activity";
 DELETE FROM "promotion_discount_product";
+DELETE FROM "promotion_seckill_config";

+ 42 - 15
yudao-module-mall/yudao-module-promotion-biz/src/test/resources/sql/create_tables.sql

@@ -107,18 +107,45 @@ CREATE TABLE IF NOT EXISTS "promotion_discount_activity" (
      PRIMARY KEY ("id")
 ) COMMENT '限时折扣活动';
 
-CREATE TABLE IF NOT EXISTS "promotion_discount_product" (
-     "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
-     "activity_id" bigint NOT NULL,
-     "spu_id" bigint NOT NULL,
-     "sku_id" bigint NOT NULL,
-     "discount_type" int NOT NULL,
-     "discount_percent" int,
-     "discount_price" int,
-     "creator" varchar DEFAULT '',
-     "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
-     "updater" varchar DEFAULT '',
-     "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-     "deleted" bit NOT NULL DEFAULT FALSE,
-     PRIMARY KEY ("id")
-) COMMENT '限时折扣活动';
+-- 将该建表 SQL 语句,添加到 yudao-module-promotion-biz 模块的 test/resources/sql/create_tables.sql 文件里
+CREATE TABLE IF NOT EXISTS "promotion_seckill_activity" (
+    "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+    "spu_id" bigint NOT NULL,
+    "name" varchar NOT NULL,
+    "status" int NOT NULL,
+    "remark" varchar,
+    "start_time" varchar NOT NULL,
+    "end_time" varchar NOT NULL,
+    "sort" int NOT NULL,
+    "config_ids" varchar NOT NULL,
+    "order_count" int NOT NULL,
+    "user_count" int NOT NULL,
+    "total_price" int NOT NULL,
+    "total_limit_count" int,
+    "single_limit_count" int,
+    "stock" int,
+    "total_stock" int,
+    "creator" varchar DEFAULT '',
+    "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updater" varchar DEFAULT '',
+    "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+    "deleted" bit NOT NULL DEFAULT FALSE,
+    "tenant_id" bigint NOT NULL,
+    PRIMARY KEY ("id")
+) COMMENT '秒杀活动';
+
+CREATE TABLE IF NOT EXISTS "promotion_seckill_config" (
+    "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+    "name" varchar NOT NULL,
+    "start_time" varchar NOT NULL,
+    "end_time" varchar NOT NULL,
+    "pic_url" varchar NOT NULL,
+    "status" int NOT NULL,
+    "creator" varchar DEFAULT '',
+    "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updater" varchar DEFAULT '',
+    "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+    "deleted" bit NOT NULL DEFAULT FALSE,
+    "tenant_id" bigint NOT NULL,
+    PRIMARY KEY ("id")
+) COMMENT '秒杀时段配置';

+ 4 - 4
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressBaseVO.java

@@ -12,22 +12,22 @@ import javax.validation.constraints.NotNull;
 @Data
 public class DeliveryExpressBaseVO {
 
-    @Schema(description = "快递公司编码", required = true)
+    @Schema(description = "快递公司编码", requiredMode = Schema.RequiredMode.REQUIRED)
     @NotNull(message = "快递公司编码不能为空")
     private String code;
 
-    @Schema(description = "快递公司名称", required = true, example = "李四")
+    @Schema(description = "快递公司名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
     @NotNull(message = "快递公司名称不能为空")
     private String name;
 
     @Schema(description = "快递公司logo")
     private String logo;
 
-    @Schema(description = "排序", required = true)
+    @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED)
     @NotNull(message = "排序不能为空")
     private Integer sort;
 
-    @Schema(description = "状态", required = true, example = "1")
+    @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "状态不能为空")
     private Integer status;
 

+ 6 - 3
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressRespVO.java

@@ -1,7 +1,10 @@
 package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express;
 
 import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
 import java.time.LocalDateTime;
 
 @Schema(description = "管理后台 - 快递公司 Response VO")
@@ -10,10 +13,10 @@ import java.time.LocalDateTime;
 @ToString(callSuper = true)
 public class DeliveryExpressRespVO extends DeliveryExpressBaseVO {
 
-    @Schema(description = "编号", required = true, example = "6592")
+    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6592")
     private Long id;
 
-    @Schema(description = "创建时间", required = true)
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime createTime;
 
 }

+ 1 - 1
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressUpdateReqVO.java

@@ -13,7 +13,7 @@ import javax.validation.constraints.NotNull;
 @ToString(callSuper = true)
 public class DeliveryExpressUpdateReqVO extends DeliveryExpressBaseVO {
 
-    @Schema(description = "编号", required = true, example = "6592")
+    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6592")
     @NotNull(message = "编号不能为空")
     private Long id;
 

+ 3 - 3
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateBaseVO.java

@@ -12,15 +12,15 @@ import javax.validation.constraints.NotNull;
 @Data
 public class DeliveryExpressTemplateBaseVO {
 
-    @Schema(description = "模板名称", required = true, example = "王五")
+    @Schema(description = "模板名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
     @NotNull(message = "模板名称不能为空")
     private String name;
 
-    @Schema(description = "配送计费方式 1:按件 2:按重量 3:按体积", required = true)
+    @Schema(description = "配送计费方式 1:按件 2:按重量 3:按体积", requiredMode = Schema.RequiredMode.REQUIRED)
     @NotNull(message = "配送计费方式 1:按件 2:按重量 3:按体积不能为空")
     private Integer chargeMode;
 
-    @Schema(description = "排序", required = true)
+    @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED)
     @NotNull(message = "排序不能为空")
     private Integer sort;
 

+ 6 - 3
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateRespVO.java

@@ -1,7 +1,10 @@
 package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate;
 
 import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
 import java.time.LocalDateTime;
 
 @Schema(description = "管理后台 - 快递运费模板 Response VO")
@@ -10,10 +13,10 @@ import java.time.LocalDateTime;
 @ToString(callSuper = true)
 public class DeliveryExpressTemplateRespVO extends DeliveryExpressTemplateBaseVO {
 
-    @Schema(description = "编号,自增", required = true, example = "371")
+    @Schema(description = "编号,自增", requiredMode = Schema.RequiredMode.REQUIRED, example = "371")
     private Long id;
 
-    @Schema(description = "创建时间", required = true)
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime createTime;
 
 }

+ 2 - 2
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateSimpleRespVO.java

@@ -12,10 +12,10 @@ import lombok.NoArgsConstructor;
 @AllArgsConstructor
 public class DeliveryExpressTemplateSimpleRespVO {
 
-    @Schema(description = "模版编号", required = true, example = "1024")
+    @Schema(description = "模版编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Long id;
 
-    @Schema(description = "模板名称", required = true, example = "测试模版")
+    @Schema(description = "模板名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试模版")
     private String name;
 
 }

+ 1 - 1
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateUpdateReqVO.java

@@ -15,7 +15,7 @@ import java.util.List;
 @ToString(callSuper = true)
 public class DeliveryExpressTemplateUpdateReqVO extends DeliveryExpressTemplateBaseVO {
 
-    @Schema(description = "编号", required = true, example = "371")
+    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "371")
     @NotNull(message = "编号不能为空")
     private Long id;
 

+ 10 - 10
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/pickup/DeliveryPickUpStoreBaseVO.java

@@ -18,49 +18,49 @@ import java.time.LocalTime;
 @Data
 public class DeliveryPickUpStoreBaseVO {
 
-    @Schema(description = "门店名称", required = true, example = "李四")
+    @Schema(description = "门店名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
     @NotBlank(message = "门店名称不能为空")
     private String name;
 
     @Schema(description = "门店简介", example = "我是门店简介")
     private String introduction;
 
-    @Schema(description = "门店手机", required = true, example = "15601892312")
+    @Schema(description = "门店手机", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601892312")
     @NotBlank(message = "门店手机不能为空")
     @Mobile
     private String phone;
 
-    @Schema(description = "区域编号", required = true, example = "18733")
+    @Schema(description = "区域编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18733")
     @NotNull(message = "区域编号不能为空")
     private Integer areaId;
 
-    @Schema(description = "门店详细地址", required = true, example = "复旦大学路 188 号")
+    @Schema(description = "门店详细地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "复旦大学路 188 号")
     @NotBlank(message = "门店详细地址不能为空")
     private String detailAddress;
 
-    @Schema(description = "门店 logo", required = true, example = "https://www.iocoder.cn/1.png")
+    @Schema(description = "门店 logo", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
     @NotBlank(message = "门店 logo 不能为空")
     private String logo;
 
-    @Schema(description = "营业开始时间", required = true)
+    @Schema(description = "营业开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
     @NotNull(message = "营业开始时间不能为空")
     @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm")
     private LocalTime openingTime;
 
-    @Schema(description = "营业结束时间", required = true)
+    @Schema(description = "营业结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
     @NotNull(message = "营业结束时间不能为空")
     @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm")
     private LocalTime closingTime;
 
-    @Schema(description = "纬度", required = true, example = "5.88")
+    @Schema(description = "纬度", requiredMode = Schema.RequiredMode.REQUIRED, example = "5.88")
     @NotNull(message = "纬度不能为空")
     private Double latitude;
 
-    @Schema(description = "经度", required = true, example = "6.99")
+    @Schema(description = "经度", requiredMode = Schema.RequiredMode.REQUIRED, example = "6.99")
     @NotNull(message = "经度不能为空")
     private Double longitude;
 
-    @Schema(description = "门店状态", required = true, example = "1")
+    @Schema(description = "门店状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "门店状态不能为空")
     @InEnum(CommonStatusEnum.class)
     private Integer status;

+ 6 - 3
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/pickup/DeliveryPickUpStoreRespVO.java

@@ -1,7 +1,10 @@
 package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup;
 
 import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
 import java.time.LocalDateTime;
 
 @Schema(description = "管理后台 - 自提门店 Response VO")
@@ -10,10 +13,10 @@ import java.time.LocalDateTime;
 @ToString(callSuper = true)
 public class DeliveryPickUpStoreRespVO extends DeliveryPickUpStoreBaseVO {
 
-    @Schema(description = "编号", required = true, example = "23128")
+    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23128")
     private Long id;
 
-    @Schema(description = "创建时间", required = true)
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime createTime;
 
 }

+ 6 - 4
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/pickup/DeliveryPickUpStoreUpdateReqVO.java

@@ -1,9 +1,11 @@
 package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup;
 
 import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.*;
-import java.util.*;
-import javax.validation.constraints.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import javax.validation.constraints.NotNull;
 
 @Schema(description = "管理后台 - 自提门店更新 Request VO")
 @Data
@@ -11,7 +13,7 @@ import javax.validation.constraints.*;
 @ToString(callSuper = true)
 public class DeliveryPickUpStoreUpdateReqVO extends DeliveryPickUpStoreBaseVO {
 
-    @Schema(description = "编号", required = true, example = "23128")
+    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23128")
     @NotNull(message = "编号不能为空")
     private Long id;
 

+ 1 - 1
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleCreateReqVO.java

@@ -36,7 +36,7 @@ public class AppTradeAfterSaleCreateReqVO {
     /**
      * @see AfterSaleStatusEnum
      */
-    @Schema(description = "操作类型", required = true, example = "1")
+    @Schema(description = "操作类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "操作类型不能为空")
     private String operateType;
 

+ 16 - 16
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSalePageItemRespVO.java

@@ -11,48 +11,48 @@ import java.util.List;
 @Data
 public class AppTradeAfterSalePageItemRespVO {
 
-    @Schema(description = "售后编号", required = true, example = "1024")
+    @Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Long id;
 
-    @Schema(description = "售后流水号", required = true, example = "1146347329394184195")
+    @Schema(description = "售后流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1146347329394184195")
     private String no;
 
-    @Schema(description = "售后状态", required = true, example = "1")
+    @Schema(description = "售后状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer status;
 
-    @Schema(description = "售后方式", required = true, example = "1")
+    @Schema(description = "售后方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer way;
 
-    @Schema(description = "售后类型", required = true, example = "1")
+    @Schema(description = "售后类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer type;
 
-    @Schema(description = "申请原因", required = true, example = "1")
+    @Schema(description = "申请原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private String applyReason;
 
-    @Schema(description = "补充描述", required = true, example = "1")
+    @Schema(description = "补充描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private String applyDescription;
 
-    @Schema(description = "补充凭证图片", required = true, example = "1")
+    @Schema(description = "补充凭证图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private List<String> applyPicUrls;
 
     // ========== 交易订单相关 ==========
 
-    @Schema(description = "交易订单编号", required = true, example = "1")
+    @Schema(description = "交易订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Long orderId;
 
-    @Schema(description = "交易订单流水号", required = true, example = "1")
+    @Schema(description = "交易订单流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private String orderNo;
 
-    @Schema(description = "交易订单项编号", required = true, example = "1")
+    @Schema(description = "交易订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Long orderItemId;
 
-    @Schema(description = "商品 SPU 编号", required = true, example = "1")
+    @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Long spuId;
 
-    @Schema(description = "商品 SPU 名称", required = true, example = "1")
+    @Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private String spuName;
 
-    @Schema(description = "商品 SKU 编号", required = true, example = "1")
+    @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Long skuId;
 
     /**
@@ -60,10 +60,10 @@ public class AppTradeAfterSalePageItemRespVO {
      */
     private List<AppProductPropertyValueDetailRespVO> properties;
 
-    @Schema(description = "商品图片", required = true, example = "https://www.iocoder.cn/01.jpg")
+    @Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/01.jpg")
     private String picUrl;
 
-    @Schema(description = "退货商品数量", required = true, example = "1")
+    @Schema(description = "退货商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer count;
 
     // ========== 审批相关 ==========

+ 1 - 1
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartAddReqVO.java

@@ -17,7 +17,7 @@ public class AppTradeCartAddReqVO {
     @NotNull(message = "数量不能为空")
     private Integer count;
 
-    @Schema(description = "是否添加到购物车", required = true, example = "true")
+    @Schema(description = "是否添加到购物车", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
     @NotNull(message = "是否添加购物车不能为空")
     private Boolean addStatus;
 

+ 2 - 2
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartListRespVO.java

@@ -25,10 +25,10 @@ public class AppTradeCartListRespVO {
     @Data
     public static class Cart {
 
-        @Schema(description = "购物项的编号", required = true, example = "1024")
+        @Schema(description = "购物项的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
         private Long id;
 
-        @Schema(description = "商品数量", required = true, example = "1")
+        @Schema(description = "商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
         private Integer count;
 
         /**

+ 2 - 2
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartUpdateReqVO.java

@@ -10,11 +10,11 @@ import javax.validation.constraints.NotNull;
 @Data
 public class AppTradeCartUpdateReqVO {
 
-    @Schema(description = "编号", required = true, example = "1024")
+    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     @NotNull(message = "编号不能为空")
     private Long id;
 
-    @Schema(description = "商品数量", required = true, example = "1")
+    @Schema(description = "商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "数量不能为空")
     @Min(message = "数量必须大于 0", value = 1L)
     private Integer count;

+ 13 - 7
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java

@@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
 import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO;
 import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi;
+import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
 import cn.iocoder.yudao.module.product.api.property.ProductPropertyValueApi;
 import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
 import cn.iocoder.yudao.module.trade.controller.app.order.vo.*;
@@ -35,6 +36,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_ITEM_NOT_FOUND;
+import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_NOT_FOUND;
 
 @Tag(name = "用户 App - 交易订单")
 @RestController
@@ -138,16 +140,20 @@ public class AppTradeOrderController {
     @PostMapping("/item/create-comment")
     @Operation(summary = "创建交易订单项的评价")
     public CommonResult<Long> createOrderItemComment(@RequestBody AppTradeOrderItemCommentCreateReqVO createReqVO) {
-        // 校验订单项,订单项存在订单就存在
-        // TODO @puhui999:要去查询订单是不是自己的;不然别人模拟请求哈;
-        TradeOrderItemDO item = tradeOrderService.getOrderItem(createReqVO.getUserId(), createReqVO.getOrderItemId());
-        if (item == null) {
+        Long loginUserId = getLoginUserId();
+        // 先通过订单项 ID 查询订单项是否存在
+        TradeOrderItemDO orderItemDO = tradeOrderService.getOrderItemByIdAndUserId(createReqVO.getOrderItemId(), loginUserId);
+        if (orderItemDO == null) {
             throw exception(ORDER_ITEM_NOT_FOUND);
         }
+        // 校验订单
+        TradeOrderDO orderDO = tradeOrderService.getOrderByIdAndUserId(orderItemDO.getOrderId(), loginUserId);
+        if (orderDO == null) {
+            throw exception(ORDER_NOT_FOUND);
+        }
 
-        return success(productCommentApi.createComment(TradeOrderConvert.INSTANCE.convert04(createReqVO), item.getOrderId()));
+        ProductCommentCreateReqDTO productCommentCreateReqDTO = TradeOrderConvert.INSTANCE.convert04(createReqVO, orderItemDO);
+        return success(productCommentApi.createComment(productCommentCreateReqDTO));
     }
 
-    // TODO 合并代码后发现只有商家回复功能 用户追评不要了吗?不要了哈;
-
 }

Деякі файли не було показано, через те що забагато файлів було змінено