118 次代碼提交 3dfc1862ed ... f6e3cea511

作者 SHA1 備註 提交日期
  zjy f6e3cea511 fix(job): 修复消息内容设置错误问题 1 周之前
  zjy 031a7250ba feat(job): 优化举报结果通知消息结构 1 周之前
  zjy 1c7ca76e74 feat(job): 优化AI自动审核任务处理逻辑 1 周之前
  lutong d450ba813f test 1 周之前
  wxd cfde5b3a61 Merge branch 'sit-aiAudit' of alien/alien_cloud into sit 1 周之前
  wxd 2a42480fac fix(video): correct task status update on moderation failure 1 周之前
  lyx 95ae3bd7d5 bugfix:上传文件,支持xml,隐私协议 1 周之前
  qrs b3ca457125 二手用户举报ai接口完善 1 周之前
  zjy 528e35062e feat(job): 引入第三方接口配置并替换硬编码URL 1 周之前
  zjy 99c227f5d9 feat(job): 实现AI自动审核任务功能 1 周之前
  zhangchen 1dd4b46e07 上传文件,新增支持语音功能 1 周之前
  wxd 522a858e22 Merge branch 'sit-aiAudit' of alien/alien_cloud into sit 1 周之前
  wxd 3c9b2754ea feat(second-goods): implement video moderation result processing and approval handling 1 周之前
  wxd f914bd83f0 Merge branch 'sit-aiAudit' of alien/alien_cloud into sit 1 周之前
  wxd 97a9af171a feat(second): implement AI goods audit result processing 1 周之前
  panzhilin 1c3c5ae084 BUG:修改类型字段数值不一致问题 1 周之前
  Lhaibo ace57488e5 feat(job): 实现AI内容审核任务及结果处理功能 1 周之前
  penghao 9d38c0cb3f 门店入驻添加门店过期时间 1 周之前
  panzhilin 539bfefb11 酒单优化餐食和酒水 1 周之前
  qrs d4112a83c2 商家pc端-酒水管理 1 周之前
  zjy df89061f42 feat(violation): 移除AI审核任务创建逻辑 1 周之前
  ldz fb8c8e065d 八大类放开校验,增加模糊查询,注释合并一个接口 1 周之前
  panzhilin 50025348a7 Merge remote-tracking branch 'origin/sit' into sit 1 周之前
  panzhilin 34fa822d75 酒水餐食管理curd(删除原来的酒水表现在是基于store_menu的表,沿用原接口改原来代码的逻辑) 1 周之前
  penghao dc927befdf feat:新增运动设施保存图片接口 1 周之前
  lyx 8cc5b4b504 bugfix:运营活动表修改,直接自关联三级结构 1 周之前
  jyc fd8f2cb98c feat(coupon): 添加优惠券ID字段以支持查询 1 周之前
  ldz 0358efdcfe 修改用户端的营销活动部分逻辑,只有已审核通过的才显示的问题 1 周之前
  fcw d3bb673411 fix(second-goods): 调整商品审核流程逻辑 1 周之前
  fcw 2b5ea01d6b Merge remote-tracking branch 'origin/sit' into sit 1 周之前
  ldz 04c8c0a981 临时协助测试提出的问题,帮忙解决代金券列表的问题 1 周之前
  lyx 44c11deffa Merge remote-tracking branch 'origin/sit' into sit 1 周之前
  lyx 536c9f1e2b bugfix:首页增加字段展示 1 周之前
  qrs 3a8b46ba85 商家pc端-酒水管理 1 周之前
  fcw 91c10010ca Merge remote-tracking branch 'origin/sit' into sit 1 周之前
  penghao 6b7fefc47b 合并解决 1 周之前
  penghao 87cd39686d Merge remote-tracking branch 'origin/sit' into sit 1 周之前
  penghao 09a6f8b516 优化入驻保存-许可证存入相应信息 1 周之前
  zhangchen 5853bfe85d 解决退款空指针 1 周之前
  zhangchen eb2123b05f 解决退款空指针 1 周之前
  panzhilin c298bd419e 酒水餐食管理curd 1 周之前
  zhangchen a76717de87 审批状态去掉 1 周之前
  ldz 5d33e9151a 协助修改用户端bug,特色美食部分显示其他店铺问题 1 周之前
  zhangchen bb8a6386d0 通知标题修改 1 周之前
  LuTong b76b322f69 开发 根据活动ID获取详情 1 周之前
  zhangchen aacfb98076 描述修改 1 周之前
  zhangchen 711496e50f 描述修改 1 周之前
  penghao 891cb966c5 修复保存bug 1 周之前
  zhangchen 4c89743b2e 实体修改 1 周之前
  zhangchen 11c2489c0a 超时加入退款时间 1 周之前
  zhangchen 3ff7728da9 加入退款时间 1 周之前
  LuTong 05ad0183d1 处理BUG 1 周之前
  qrs a9bd3ff312 商家pc端-酒水管理 1 周之前
  panzhilin 9d810c69b7 合并 1 周之前
  panzhilin 535a5b366a Merge remote-tracking branch 'origin/sit' into sit 1 周之前
  panzhilin 26abe700bf 获取店铺分类信息(根据business_classify字段获取字典表数据实现UI图中的功能)调试 2 周之前
  penghao 333f800d88 Merge remote-tracking branch 'origin/sit' into sit 1 周之前
  penghao a8f051a9d1 feat:添加娱乐经营许可证上传 1 周之前
  penghao 09bd340415 bugfix:解决json序列化问题 1 周之前
  penghao 35463f21d9 feat:新增商铺入驻获取三级分类数据接口 2 周之前
  panzhilin b92ffa09bb 获取店铺分类信息提交 1 周之前
  panzhilin dcf7ba1b3b Merge remote-tracking branch 'origin/sit' into sit 1 周之前
  penghao d699c25594 bugfix:首页信息报错500修复 2 周之前
  penghao 7945c134e1 新增商户端员工置顶接口,修改列表排序逻辑 2 周之前
  panzhilin 046d5bfd67 (JSON序列化依赖) 1 周之前
  panzhilin 0bea206e8c 获取店铺分类信息提交 1 周之前
  ldz fc508df8d0 领导要求去掉 过期的经营许可证娱乐许可证校验 1 周之前
  panzhilin 3166793242 Revert "获取店铺分类信息(根据business_classify字段获取字典表数据实现UI图中的功能)" 2 周之前
  panzhilin 4f21c0bc0a 获取店铺分类信息(根据business_classify字段获取字典表数据实现UI图中的功能) 2 周之前
  penghao 136468ad6a 新增商户端人员配置删除接口,修改优化新增或修改人员配置接口逻辑 2 周之前
  penghao 013fad200a Revert "合并代码到sit" 1 周之前
  zhangchen 4d056249a4 引用方式修改 1 周之前
  fcw 77c5b11339 feat(store): 新增洗浴设施及服务的商户端查询功能 1 周之前
  zhangchen 1cf7fc8bed 修复bug 1 周之前
  fcw 6dee6d7b67 Merge remote-tracking branch 'origin/sit' into sit 1 周之前
  zhangchen 24ae277ad8 Merge remote-tracking branch 'origin/sit' into sit 1 周之前
  zhangchen 1ba58a863c 修复bug 1 周之前
  yindp 0f6e8cfa86 feat(store): 添加用户ID字段到AiApproveStoreInfo类 1 周之前
  lyx aaa90aeaeb Merge remote-tracking branch 'origin/sit' into sit 1 周之前
  lyx 6ca6e55c88 fix:修改错误上传 1 周之前
  zhangchen c11521fa5e 修复bug 1 周之前
  lyx 1eeb13f6c6 Merge remote-tracking branch 'origin/sit' into sit 1 周之前
  lyx b77d3c947e fix:中台查询店铺增加ocr识别数据 1 周之前
  qxy cde22fb9b4 标签列表 1 周之前
  Lhaibo fd49ae760a Merge remote-tracking branch 'origin/sit' into sit 1 周之前
  qrs 9c29b69a5c 回滚代码字段 1 周之前
  Lhaibo 4e1554db39 feat(store): 更新门店OCR识别接口参数 1 周之前
  lyx 69f40cd66b fix:中台查询店铺增加ocr识别数据 1 周之前
  zhangchen f8341653c9 菜品mapper代码回滚 1 周之前
  Lhaibo 7fa4e9359d Merge remote-tracking branch 'origin/sit' into sit 1 周之前
  qxy 8ce6726e8f 合并代码到sit 1 周之前
  penghao 51f6b00374 Merge remote-tracking branch 'origin/sit' into sit 1 周之前
  penghao 7fa4e4dd3e 合并代码到sit 1 周之前
  lyx 264ebb9936 Merge remote-tracking branch 'origin/sit' into sit 1 周之前
  lyx 8d4f65c69b bugfix:微信支付流程完成 1 周之前
  ldz ac20448392 八大类代码上sit全部 增加bannner图 增加实体 1 周之前
  qxy eb709cad80 合并代码到sit 2 周之前
  qxy ffc928c207 Merge remote-tracking branch 'origin/sit' into sit 1 周之前
  ldz d89f3dd752 八大类代码上sit全部 增加被冲掉的代码 1 周之前
  zhangchen 11cdecbadd 代码合并 1 周之前
  zhangchen 47df63433e 代码合并 1 周之前
  ldz 7e08b04c33 八大类代码上sit全部 增加实体 1 周之前
  zhangchen 68f7b08c1e 代码合并 1 周之前
  zhangchen 877022d923 Merge remote-tracking branch 'origin/sit' into sit 1 周之前
  zhangchen 02ab4e9405 代码合并 1 周之前
  ldz 1bb41122fa 八大类代码上sit全部 增加注解 1 周之前
  qxy f613db6f2a 三级分类Vo 2 周之前
  ldz 2c71d7b209 八大类代码上sit全部 1 周之前
  lyx f0b1377546 fix:修改ocr配置为公司配置 1 周之前
  lyx 6ae33d2a18 fix:自动退款修改 1 周之前
  lyx f8164c10fa bugfix:ocr功能完善 1 周之前
  zhangchen 9e4646662b 八大类代码上sit全部 2 周之前
  827079570 5df05c1bb6 440BUG,1155BUG 1 月之前
  LuTong dbeb29c712 申诉更改订单申诉状态为2 修改bug 提交评价后 提示词评论改为提交 2 周之前
  LuTong 686f1638c7 更改昵称,更改评分 2 周之前
  LuTong adceb90556 评分计算保留一位小数 2 周之前
  fcw 28d3935780 feat(sms): 发送短信时永久存储验证码 1 周之前
  Lhaibo 22eba43ee2 feat(job): 新增AI自动审核与风控任务 1 周之前
共有 100 個文件被更改,包括 5400 次插入450 次删除
  1. 6 0
      alien-entity/pom.xml
  2. 86 0
      alien-entity/src/main/java/shop/alien/entity/store/BathFacilityService.java
  3. 81 0
      alien-entity/src/main/java/shop/alien/entity/store/DrinkInfo.java
  4. 82 0
      alien-entity/src/main/java/shop/alien/entity/store/SportsEquipmentFacility.java
  5. 1 1
      alien-entity/src/main/java/shop/alien/entity/store/StoreImg.java
  6. 8 5
      alien-entity/src/main/java/shop/alien/entity/store/StoreInfo.java
  7. 19 3
      alien-entity/src/main/java/shop/alien/entity/store/StoreMenu.java
  8. 75 0
      alien-entity/src/main/java/shop/alien/entity/store/StorePersonnel.java
  9. 21 0
      alien-entity/src/main/java/shop/alien/entity/store/StoreStaffConfig.java
  10. 16 12
      alien-entity/src/main/java/shop/alien/entity/store/UserActionRewardRule.java
  11. 29 8
      alien-entity/src/main/java/shop/alien/entity/store/dto/StoreInfoDto.java
  12. 66 0
      alien-entity/src/main/java/shop/alien/entity/store/dto/deserializer/StringToListDeserializer.java
  13. 4 0
      alien-entity/src/main/java/shop/alien/entity/store/excelVo/StoreInfoExcelVo.java
  14. 1 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/AiApproveStoreInfo.java
  15. 39 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/BathFacilityServiceCategoryVo.java
  16. 66 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/BathFacilityServiceVo.java
  17. 24 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/CouponAndEventVo.java
  18. 82 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/DrinkInfoVo.java
  19. 0 1
      alien-entity/src/main/java/shop/alien/entity/store/vo/LawyerConsultationOrderVO.java
  20. 3 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/LifeDiscountCouponFriendRuleVo.java
  21. 3 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/LifeDiscountCouponVo.java
  22. 42 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/SportsEquipmentFacilityCategoryVo.java
  23. 61 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/SportsEquipmentFacilityVo.java
  24. 53 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreAlbumDetailVo.java
  25. 25 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreAlbumNameVo.java
  26. 4 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreCommentVo.java
  27. 30 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreInfoVo.java
  28. 6 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreMainInfoVo.java
  29. 29 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreOfficialAlbumImgVo.java
  30. 34 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StorePersonnelVo.java
  31. 32 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreThreeLevelStructureVo.java
  32. 3 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreUserVo.java
  33. 1 1
      alien-entity/src/main/java/shop/alien/entity/storePlatform/StoreOperationalActivity.java
  34. 17 0
      alien-entity/src/main/java/shop/alien/mapper/BathFacilityServiceMapper.java
  35. 177 0
      alien-entity/src/main/java/shop/alien/mapper/LifeCouponMapper.java
  36. 2 0
      alien-entity/src/main/java/shop/alien/mapper/LifeDiscountCouponStoreFriendMapper.java
  37. 9 5
      alien-entity/src/main/java/shop/alien/mapper/LifeFansMapper.java
  38. 17 0
      alien-entity/src/main/java/shop/alien/mapper/SportsEquipmentFacilityMapper.java
  39. 13 0
      alien-entity/src/main/java/shop/alien/mapper/StoreCommentMapper.java
  40. 26 0
      alien-entity/src/main/java/shop/alien/mapper/StoreInfoMapper.java
  41. 54 0
      alien-entity/src/main/java/shop/alien/mapper/StoreMenuMapper.java
  42. 44 0
      alien-entity/src/main/java/shop/alien/mapper/StorePersonnelMapper.java
  43. 40 13
      alien-entity/src/main/java/shop/alien/mapper/TagsMainMapper.java
  44. 13 0
      alien-job/src/main/java/shop/alien/job/feign/AlienStoreFeign.java
  45. 14 0
      alien-job/src/main/java/shop/alien/job/feign/SecondGoodsFeign.java
  46. 5 41
      alien-job/src/main/java/shop/alien/job/jobhandler/VideoModerationJobHandler.java
  47. 173 17
      alien-job/src/main/java/shop/alien/job/second/AiCheckXxlJob.java
  48. 25 3
      alien-job/src/main/java/shop/alien/job/second/AiUserViolationJob.java
  49. 13 167
      alien-job/src/main/java/shop/alien/job/second/goodsCheckJob.java
  50. 0 1
      alien-job/src/main/java/shop/alien/job/store/AiTagJob.java
  51. 18 2
      alien-job/src/main/java/shop/alien/job/store/BadReviewAppealJob.java
  52. 30 7
      alien-job/src/main/java/shop/alien/job/store/LifeUserOrderJob.java
  53. 1 0
      alien-lawyer/src/main/java/shop/alien/lawyer/controller/LawyerUserController.java
  54. 1 0
      alien-lawyer/src/main/java/shop/alien/lawyer/controller/OrderReviewController.java
  55. 1 0
      alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/LawyerClientConsultationOrderServiceImpl.java
  56. 1 1
      alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/LawyerConsultationOrderServiceImpl.java
  57. 4 1
      alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/OrderExpirationServiceImpl.java
  58. 2 2
      alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/OrderReviewServiceImpl.java
  59. 16 0
      alien-lawyer/src/main/java/shop/alien/lawyer/util/AliSms.java
  60. 40 0
      alien-second/src/main/java/shop/alien/second/controller/SecondGoodsController.java
  61. 13 1
      alien-second/src/main/java/shop/alien/second/service/SecondGoodsAuditService.java
  62. 6 0
      alien-second/src/main/java/shop/alien/second/service/SecondGoodsService.java
  63. 6 0
      alien-second/src/main/java/shop/alien/second/service/VideoModerationService.java
  64. 218 1
      alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsAuditServiceImpl.java
  65. 18 0
      alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsReportingServiceImpl.java
  66. 79 41
      alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsServiceImpl.java
  67. 72 1
      alien-second/src/main/java/shop/alien/second/service/impl/VideoModerationServiceImpl.java
  68. 271 0
      alien-second/src/main/java/shop/alien/second/util/AiUserViolationUtils.java
  69. 12 10
      alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StorePlatformBarMenuServiceImpl.java
  70. 3 2
      alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StorePlatformLoginServiceImpl.java
  71. 4 2
      alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StorePlatformRenovationServiceImpl.java
  72. 214 0
      alien-store/src/main/java/shop/alien/store/controller/BathFacilityServiceController.java
  73. 191 0
      alien-store/src/main/java/shop/alien/store/controller/DrinkInfoController.java
  74. 17 0
      alien-store/src/main/java/shop/alien/store/controller/LifeCouponController.java
  75. 99 0
      alien-store/src/main/java/shop/alien/store/controller/OperationalActivityController.java
  76. 212 0
      alien-store/src/main/java/shop/alien/store/controller/SportsEquipmentFacilityController.java
  77. 412 18
      alien-store/src/main/java/shop/alien/store/controller/StoreInfoController.java
  78. 84 5
      alien-store/src/main/java/shop/alien/store/controller/StoreMenuController.java
  79. 90 4
      alien-store/src/main/java/shop/alien/store/controller/StoreOfficialAlbumController.java
  80. 87 0
      alien-store/src/main/java/shop/alien/store/controller/StorePersonnelController.java
  81. 68 0
      alien-store/src/main/java/shop/alien/store/controller/StoreStaffConfigController.java
  82. 88 0
      alien-store/src/main/java/shop/alien/store/service/BathFacilityServiceService.java
  83. 116 0
      alien-store/src/main/java/shop/alien/store/service/DrinkInfoService.java
  84. 49 44
      alien-store/src/main/java/shop/alien/store/service/LifeCommentService.java
  85. 7 0
      alien-store/src/main/java/shop/alien/store/service/LifeCouponService.java
  86. 1 1
      alien-store/src/main/java/shop/alien/store/service/LifeUserDynamicsService.java
  87. 5 0
      alien-store/src/main/java/shop/alien/store/service/LifeUserStoreService.java
  88. 44 0
      alien-store/src/main/java/shop/alien/store/service/OperationalActivityService.java
  89. 97 0
      alien-store/src/main/java/shop/alien/store/service/SportsEquipmentFacilityService.java
  90. 149 6
      alien-store/src/main/java/shop/alien/store/service/StoreInfoService.java
  91. 32 4
      alien-store/src/main/java/shop/alien/store/service/StoreMenuService.java
  92. 27 1
      alien-store/src/main/java/shop/alien/store/service/StoreOfficialAlbumService.java
  93. 58 0
      alien-store/src/main/java/shop/alien/store/service/StorePersonnelService.java
  94. 37 0
      alien-store/src/main/java/shop/alien/store/service/StoreStaffConfigService.java
  95. 333 0
      alien-store/src/main/java/shop/alien/store/service/impl/BathFacilityServiceServiceImpl.java
  96. 367 0
      alien-store/src/main/java/shop/alien/store/service/impl/DrinkInfoServiceImpl.java
  97. 7 7
      alien-store/src/main/java/shop/alien/store/service/impl/LifeBlacklistServiceImpl.java
  98. 5 0
      alien-store/src/main/java/shop/alien/store/service/impl/LifeCouponServiceImpl.java
  99. 5 2
      alien-store/src/main/java/shop/alien/store/service/impl/LifeDiscountCouponServiceImpl.java
  100. 9 9
      alien-store/src/main/java/shop/alien/store/service/impl/LifeUserViolationServiceImpl.java

+ 6 - 0
alien-entity/pom.xml

@@ -83,6 +83,12 @@
             <scope>compile</scope>
         </dependency>
 
+        <!-- Jackson for JSON deserialization -->
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+
     </dependencies>
 
     <build>

+ 86 - 0
alien-entity/src/main/java/shop/alien/entity/store/BathFacilityService.java

@@ -0,0 +1,86 @@
+package shop.alien.entity.store;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 洗浴设施及服务表
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Data
+@JsonInclude
+@TableName("bath_facility_service")
+@ApiModel(value = "BathFacilityService对象", description = "洗浴设施及服务表")
+public class BathFacilityService implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "主键")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty(value = "门店ID")
+    @TableField("store_id")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "设施分类(1:洗浴区, 2:汗蒸区, 3:休闲区, 4:餐饮区)")
+    @TableField("facility_category")
+    private Integer facilityCategory;
+
+    @ApiModelProperty(value = "名称")
+    @TableField("facility_name")
+    private String facilityName;
+
+    @ApiModelProperty(value = "收费标准")
+    @TableField("charging_standard")
+    private String chargingStandard;
+
+    @ApiModelProperty(value = "使用时间类型(0:全天, 1:选择时间)")
+    @TableField("usage_time_type")
+    private Integer usageTimeType;
+
+    @ApiModelProperty(value = "使用开始时间(HH:mm格式)")
+    @TableField("usage_start_time")
+    private String usageStartTime;
+
+    @ApiModelProperty(value = "使用结束时间(HH:mm格式)")
+    @TableField("usage_end_time")
+    private String usageEndTime;
+
+    @ApiModelProperty(value = "是否显示在店铺详情(0:隐藏, 1:显示)")
+    @TableField("display_in_store_detail")
+    private Integer displayInStoreDetail;
+
+    @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
+    @TableField("delete_flag")
+    @TableLogic
+    private Integer deleteFlag;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(value = "created_time", fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createdTime;
+
+    @ApiModelProperty(value = "创建人ID")
+    @TableField(value = "created_user_id", fill = FieldFill.INSERT)
+    private Integer createdUserId;
+
+    @ApiModelProperty(value = "修改时间")
+    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updatedTime;
+
+    @ApiModelProperty(value = "修改人ID")
+    @TableField(value = "updated_user_id", fill = FieldFill.INSERT_UPDATE)
+    private Integer updatedUserId;
+}
+

+ 81 - 0
alien-entity/src/main/java/shop/alien/entity/store/DrinkInfo.java

@@ -0,0 +1,81 @@
+package shop.alien.entity.store;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 酒水餐食信息 DTO
+ * 用于接口参数传输,实际数据存储在 store_menu 表
+ * type: 1=餐食,2=酒水
+ *
+ * @author ssk
+ * @since 2025-05-14
+ */
+@Data
+@ApiModel(value = "DrinkInfo", description = "酒水餐食信息DTO")
+public class DrinkInfo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "主键ID")
+    private Integer id;
+
+    @ApiModelProperty(value = "类型(1:餐食,2:酒水)")
+    private Integer type;
+
+    @ApiModelProperty(value = "名称")
+    private String name;
+
+    @ApiModelProperty(value = "售价")
+    private BigDecimal price;
+
+    @ApiModelProperty(value = "成本价")
+    private BigDecimal costPrice;
+
+    @ApiModelProperty(value = "酒精度(%vol)")
+    private BigDecimal alcoholVolume;
+
+    @ApiModelProperty(value = "图片URL")
+    private String picUrl;
+
+    @ApiModelProperty(value = "分类(如:白酒、啤酒、小吃等)")
+    private String category;
+
+    @ApiModelProperty(value = "风味特征")
+    private String flavor;
+
+    @ApiModelProperty(value = "描述")
+    private String description;
+
+    @ApiModelProperty(value = "排序(数值越小越靠前)")
+    private Integer sort;
+
+    @ApiModelProperty(value = "是否推荐(0:否,1:是)")
+    private Integer isRecommended;
+
+    @ApiModelProperty(value = "状态(1:上架,2:下架)")
+    private Integer status;
+
+    @ApiModelProperty(value = "门店ID")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "创建人ID")
+    private Integer createUserId;
+
+    @ApiModelProperty(value = "创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createTime;
+
+    @ApiModelProperty(value = "修改人ID")
+    private Integer updateUserId;
+
+    @ApiModelProperty(value = "修改时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updateTime;
+}

+ 82 - 0
alien-entity/src/main/java/shop/alien/entity/store/SportsEquipmentFacility.java

@@ -0,0 +1,82 @@
+package shop.alien.entity.store;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 运动器材设施表
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Data
+@JsonInclude
+@TableName("sports_equipment_facility")
+@ApiModel(value = "SportsEquipmentFacility对象", description = "运动器材设施表")
+public class SportsEquipmentFacility implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "主键")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty(value = "门店ID")
+    @TableField("store_id")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "设施分类(1:有氧区, 2:力量区, 3:单功能机械区)")
+    @TableField("facility_category")
+    private Integer facilityCategory;
+
+    @ApiModelProperty(value = "设施名称")
+    @TableField("facility_name")
+    private String facilityName;
+
+    @ApiModelProperty(value = "数量")
+    @TableField("quantity")
+    private Integer quantity;
+
+    @ApiModelProperty(value = "品牌")
+    @TableField("brand")
+    private String brand;
+
+    @ApiModelProperty(value = "描述")
+    @TableField("description")
+    private String description;
+
+    @ApiModelProperty(value = "是否显示在店铺详情(0:隐藏, 1:显示)")
+    @TableField("display_in_store_detail")
+    private Integer displayInStoreDetail;
+
+    @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
+    @TableField("delete_flag")
+    @TableLogic
+    private Integer deleteFlag;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(value = "created_time", fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createdTime;
+
+    @ApiModelProperty(value = "创建人ID")
+    @TableField(value = "created_user_id", fill = FieldFill.INSERT)
+    private Integer createdUserId;
+
+    @ApiModelProperty(value = "修改时间")
+    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updatedTime;
+
+    @ApiModelProperty(value = "修改人ID")
+    @TableField(value = "updated_user_id", fill = FieldFill.INSERT_UPDATE)
+    private Integer updatedUserId;
+}
+

+ 1 - 1
alien-entity/src/main/java/shop/alien/entity/store/StoreImg.java

@@ -30,7 +30,7 @@ public class StoreImg extends Model<StoreImg> {
     @TableField("store_id")
     private Integer storeId;
 
-    @ApiModelProperty(value = "图片类型, 0:其他, 1:入口图, 2:相册, 3:菜品, 4:环境, 5:价目表, 6:推荐菜, 7:菜单, 8:用户评论, 9:商家申诉,10:商家头像,11:店铺轮播图,12:联名卡图片,13:动态折扣, 14:套餐图片,15:合同照片,17:打卡广场小人图片 18: 商品发布图片 19:二手商品与用户举报图片,20头图单图模式,21头图多图模式 , 22续签合同,23,二手商品记录图片类型, 24 食品经营许可证审核前状态 25.食品经营许可证审核后状态")
+    @ApiModelProperty(value = "图片类型, 0:其他, 1:入口图, 2:相册, 3:菜品, 4:环境, 5:价目表, 6:推荐菜, 7:菜单, 8:用户评论, 9:商家申诉,10:商家头像,11:店铺轮播图,12:联名卡图片,13:动态折扣, 14:营业执照,15:合同照片,17:打卡广场小人图片 18: 二手商品发布图片 19:二手商品与用户举报图片,20头图单图模式,21头图多图模式 , 22续签合同, 23 二手商品记录图片类型, 24 食品经营许可证审核前类型 25.食品经营许可证审核后类型 26.运营活动活动标题图 27.运营活动活动详情图 28.运动设施 29.洗浴设施及服务 30.酒水 31.娱乐经营许可证 32.娱乐经营许可证审核前")
     @TableField("img_type")
     private Integer imgType;
 

+ 8 - 5
alien-entity/src/main/java/shop/alien/entity/store/StoreInfo.java

@@ -86,6 +86,7 @@ public class StoreInfo {
 
     @ApiModelProperty(value = "到期时间")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @TableField("expiration_time")
     private Date expirationTime;
 
     @ApiModelProperty(value = "门店坐标")
@@ -235,7 +236,7 @@ public class StoreInfo {
     @TableField("update_renew_contract_time")
     private Date  updateRenewContractTime;
 
-    @ApiModelProperty(value = "分类id(词典表 键为 business_classify)")
+    @ApiModelProperty(value = "分类id(词典表 键为 business_classify)(多个ID用逗号拼接)")
     @TableField("business_classify")
     private String businessClassify;
 
@@ -243,11 +244,13 @@ public class StoreInfo {
     @TableField("business_classify_name")
     private String businessClassifyName;
 
-    @ApiModelProperty(value = "是否提供餐食 0 否 1 是")
-    @TableField("meal_provided")
-    private Integer mealProvided;
 
-    @ApiModelProperty(value = "娱乐经营许可证状态 字典 foodLicenceStatus")
+
+    @ApiModelProperty(value = "是否提供餐食")
+    @TableField("meals_flag")
+    private Integer  mealsFlag;
+
+    @ApiModelProperty(value = "娱乐经营许可证状态")
     @TableField("entertainment_licence_status")
     private Integer entertainmentLicenceStatus;
 

+ 19 - 3
alien-entity/src/main/java/shop/alien/entity/store/StoreMenu.java

@@ -34,15 +34,19 @@ public class StoreMenu {
     @TableField("img_id")
     private Integer imgId;
 
-    @ApiModelProperty(value = "菜品名称")
+    @ApiModelProperty(value = "菜单类型:1-菜单,2-酒水")
+    @TableField("dish_menu_type")
+    private String dishMenuType;
+
+    @ApiModelProperty(value = "名称")
     @TableField("dish_name")
     private String dishName;
 
-    @ApiModelProperty(value = "菜品价格")
+    @ApiModelProperty(value = "价格")
     @TableField("dish_price")
     private BigDecimal dishPrice;
 
-    @ApiModelProperty(value = "菜品类型, 0:菜单, 1:推荐")
+    @ApiModelProperty(value = "是否推荐, 0:非推荐, 1:推荐")
     @TableField("dish_type")
     private Integer dishType;
 
@@ -89,5 +93,17 @@ public class StoreMenu {
     @TableField("description")
     private String description;
 
+    @ApiModelProperty(value = "酒精度")
+    @TableField("alcohol_volume")
+    private String alcoholVolume;
+
+    @ApiModelProperty(value = "分类")
+    @TableField("category")
+    private String category;
+
+    @ApiModelProperty(value = "品味")
+    @TableField("flavor")
+    private String flavor;
+
 
 }

+ 75 - 0
alien-entity/src/main/java/shop/alien/entity/store/StorePersonnel.java

@@ -0,0 +1,75 @@
+package shop.alien.entity.store;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 店铺人员实体类
+ *
+ * @author system
+ * @since 2025-01-15
+ */
+@Data
+@JsonInclude
+@TableName("store_personnel")
+@ApiModel(value = "StorePersonnel对象", description = "店铺人员")
+public class StorePersonnel {
+
+    @ApiModelProperty(value = "主键")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty(value = "门店id")
+    @TableField("store_id")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "人员姓名")
+    @TableField("personnel_name")
+    private String personnelName;
+
+    @ApiModelProperty(value = "角色标签,1-歌手,2-技师,3-教练,4-美发师/美容师")
+    @TableField("role_tags")
+    private String roleTags;
+
+    @ApiModelProperty(value = "图片id,关联store_img表")
+    @TableField("img_id")
+    private Integer imgId;
+
+    @ApiModelProperty(value = "人员描述")
+    @TableField("description")
+    private String description;
+
+    @ApiModelProperty(value = "排序")
+    @TableField("sort")
+    private Integer sort;
+
+    @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
+    @TableField("delete_flag")
+    @TableLogic
+    private Integer deleteFlag;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(value = "created_time", fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createdTime;
+
+    @ApiModelProperty(value = "创建人ID")
+    @TableField("created_user_id")
+    private Integer createdUserId;
+
+    @ApiModelProperty(value = "修改时间")
+    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updatedTime;
+
+    @ApiModelProperty(value = "修改人ID")
+    @TableField("updated_user_id")
+    private Integer updatedUserId;
+}
+

+ 21 - 0
alien-entity/src/main/java/shop/alien/entity/store/StoreStaffConfig.java

@@ -7,6 +7,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 
 import java.util.Date;
 
@@ -16,6 +17,7 @@ import java.util.Date;
  * @Description: 员工管理
  */
 @Data
+@EqualsAndHashCode(callSuper = false)
 @JsonInclude
 @TableName("store_staff_config")
 @ApiModel(value = "StoreStaffConfig对象", description = "员工管理")
@@ -27,33 +29,43 @@ public class StoreStaffConfig extends Model<StoreStaffConfig> {
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
 
+    @ApiModelProperty(value = "员工职位")
     @TableField("staff_position")
     private String staffPosition;
 
+    @ApiModelProperty(value = "员工名称/昵称")
     @TableField("name")
     private String name;
 
+    @ApiModelProperty(value = "头像")
     @TableField("staff_image")
     private String staffImage;
 
+    @ApiModelProperty(value = "擅长项目")
     @TableField("proficient_projects")
     private String proficientProjects;
 
+    @ApiModelProperty(value = "标签")
     @TableField("tag")
     private String tag;
 
+    @ApiModelProperty(value = "个人简介")
     @TableField("personal_introduction")
     private String personalIntroduction;
 
+    @ApiModelProperty(value = "人员状态0-待审核 1-审核通过 2-审核拒绝")
     @TableField("status")
     private String status;
 
+    @ApiModelProperty(value = "店铺ID")
     @TableField("store_id")
     private Integer storeId;
 
+    @ApiModelProperty(value = "店铺名称")
     @TableField("store_name")
     private String storeName;
 
+    @ApiModelProperty(value = "拒绝原因")
     @TableField("rejection_reason")
     private String rejectionReason;
 
@@ -79,4 +91,13 @@ public class StoreStaffConfig extends Model<StoreStaffConfig> {
     @ApiModelProperty(value = "修改人ID")
     @TableField("updated_user_id")
     private Integer updatedUserId;
+
+    @ApiModelProperty(value = "置顶状态, 0:未置顶, 1:已置顶")
+    @TableField("top_status")
+    private Integer topStatus;
+
+    @ApiModelProperty(value = "置顶时间")
+    @TableField("top_time")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date topTime;
 }

+ 16 - 12
alien-entity/src/main/java/shop/alien/entity/store/UserActionRewardRule.java

@@ -18,30 +18,34 @@ import java.util.Date;
 @Data
 @JsonInclude
 @TableName("user_action_reward_rule")
-@ApiModel(value = "UserActionRewardRule", description = "用户行为奖励规则配置表")
+@ApiModel(value = "UserActionRewardRule", description = "用户行为奖励规则配置表(3级树形结构)")
 public class UserActionRewardRule {
 
-    @ApiModelProperty(value = "主键")
+    @ApiModelProperty(value = "主键ID")
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
 
-    @ApiModelProperty(value = "角色(如:当用户)")
-    @TableField("role")
-    private String role;
+    @ApiModelProperty(value = "父节点ID,0表示根节点(第一级:角色)")
+    @TableField("parent_id")
+    private Integer parentId;
 
-    @ApiModelProperty(value = "行为(如:核销并评论、核销、打卡)")
-    @TableField("action")
-    private String action;
+    @ApiModelProperty(value = "层级:1-角色,2-行为,3-奖励")
+    @TableField("level")
+    private Integer level;
 
-    @ApiModelProperty(value = "奖励(如:优惠券、红包)")
-    @TableField("reward")
-    private String reward;
+    @ApiModelProperty(value = "名称:根据level区分,1-角色名,2-行为名,3-奖励名")
+    @TableField("name")
+    private String name;
+
+    @ApiModelProperty(value = "奖励数量:如1优惠券、2红包(仅第三级使用)")
+    @TableField("reward_amount")
+    private Integer rewardAmount;
 
     @ApiModelProperty(value = "状态:0-禁用,1-启用")
     @TableField("status")
     private Integer status;
 
-    @ApiModelProperty(value = "排序")
+    @ApiModelProperty(value = "排序:数值越大越靠前")
     @TableField("sort_order")
     private Integer sortOrder;
 

+ 29 - 8
alien-entity/src/main/java/shop/alien/entity/store/dto/StoreInfoDto.java

@@ -3,11 +3,13 @@ package shop.alien.entity.store.dto;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 import shop.alien.entity.store.StoreBusinessInfo;
+import shop.alien.entity.store.dto.deserializer.StringToListDeserializer;
 
 import java.util.Date;
 import java.util.List;
@@ -112,12 +114,14 @@ public class StoreInfoDto {
     private String businessTypeValue;
 
     @ApiModelProperty(value = "经营种类集合")
+    @JsonDeserialize(using = StringToListDeserializer.class)
     private List<String> businessTypesList;
 
     @ApiModelProperty(value = "经营板块id(词典表 键为 business_section)")
     private Integer businessSection;
 
     @ApiModelProperty(value = "经营种类ids")
+    @JsonDeserialize(using = StringToListDeserializer.class)
     private List<String> businessTypes;
 
     @ApiModelProperty(value = "经营种类名称s")
@@ -127,9 +131,11 @@ public class StoreInfoDto {
     private String userAccount;
 
     @ApiModelProperty(value = "营业执照图片地址")
+    @JsonDeserialize(using = StringToListDeserializer.class)
     private List<String> businessLicenseAddress;
 
     @ApiModelProperty(value = "合同图片地址")
+    @JsonDeserialize(using = StringToListDeserializer.class)
     private List<String> contractImageList;
 
     @ApiModelProperty(value = "经营许可证图片地址")
@@ -180,20 +186,35 @@ public class StoreInfoDto {
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private Date foodLicenceExpirationTime;
 
-    @ApiModelProperty(value = "分类id(词典表 键为 business_classify)")
-    private  List<String> businessClassifyList;
+    @ApiModelProperty(value = "分类id(词典表 键为 business_classify)(多个ID用逗号拼接)")
+    @JsonDeserialize(using = StringToListDeserializer.class)
+    private List<String> businessClassify;
 
     @ApiModelProperty(value = "分类名称")
     private String businessClassifyName;
 
-    @ApiModelProperty(value = "分类id(词典表 键为 business_classify)")
-    @TableField("business_classify")
-    private String businessClassify;
+    @ApiModelProperty(value = "是否提供餐食")
+    private Integer mealsFlag;
 
-    @ApiModelProperty(value = "是否提供餐食 0=不提供  1=提供")
-    @TableField("meal_provided")
-    private Integer mealProvided;
+    @ApiModelProperty(value = "娱乐经营许可证图片地址")
+    private String entertainmentLicenceUrl;
+
+    @ApiModelProperty(value = "娱乐经营许可证状态")
+    private Integer entertainmentLicenceStatus;
 
     @ApiModelProperty(value = "娱乐经营许可证")
     private List<String> entertainmentLicenseAddress;
+
+    @ApiModelProperty(value = "娱乐经营许可证原因")
+    private String entertainmentLicenceReason;
+
+    @ApiModelProperty(value = "娱乐经营许可证到期时间")
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date entertainmentLicenceExpirationTime;
+
+//    @ApiModelProperty(value = "分类id(词典表 键为 business_classify)(多个ID用逗号拼接)")
+//    @JsonDeserialize(using = StringToListDeserializer.class)
+//    private List<String> businessClassify;
+
 }

+ 66 - 0
alien-entity/src/main/java/shop/alien/entity/store/dto/deserializer/StringToListDeserializer.java

@@ -0,0 +1,66 @@
+package shop.alien.entity.store.dto.deserializer;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 自定义反序列化器:将字符串或数组转换为List<String>
+ * 支持以下格式:
+ * - 字符串:"0" 或 "1,2,3"
+ * - 数组:["1", "2", "3"]
+ * - null:返回空列表
+ */
+public class StringToListDeserializer extends JsonDeserializer<List<String>> {
+
+    @Override
+    public List<String> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
+        JsonNode node = p.getCodec().readTree(p);
+        
+        if (node == null || node.isNull()) {
+            return new ArrayList<>();
+        }
+        
+        List<String> result = new ArrayList<>();
+        
+        // 如果是数组
+        if (node.isArray()) {
+            for (JsonNode item : node) {
+                if (item != null && !item.isNull()) {
+                    result.add(item.asText());
+                }
+            }
+        } 
+        // 如果是字符串
+        else if (node.isTextual()) {
+            String value = node.asText();
+            if (value != null && !value.trim().isEmpty()) {
+                // 如果是逗号分隔的字符串,则分割
+                if (value.contains(",")) {
+                    String[] parts = value.split(",");
+                    for (String part : parts) {
+                        String trimmed = part.trim();
+                        if (!trimmed.isEmpty()) {
+                            result.add(trimmed);
+                        }
+                    }
+                } else {
+                    // 单个值
+                    result.add(value.trim());
+                }
+            }
+        }
+        // 如果是数字,转换为字符串
+        else if (node.isNumber()) {
+            result.add(node.asText());
+        }
+        
+        return result;
+    }
+}
+

+ 4 - 0
alien-entity/src/main/java/shop/alien/entity/store/excelVo/StoreInfoExcelVo.java

@@ -44,6 +44,10 @@ public class StoreInfoExcelVo {
     @ApiModelProperty(value = "经营种类")
     private String businessTypesName;
 
+    @ExcelHeader("经营分类")
+    @ApiModelProperty(value = "经营分类")
+    private String businessClassifyName;
+
     @ExcelHeader(value = "详细地址")
     @ApiModelProperty(value = "详细地址")
     private String storeAddress;

+ 1 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/AiApproveStoreInfo.java

@@ -11,6 +11,7 @@ import java.util.List;
 @Data
 public class AiApproveStoreInfo {
 
+
     @ApiModelProperty(value = "用户id")
     private String userId;
 

+ 39 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/BathFacilityServiceCategoryVo.java

@@ -0,0 +1,39 @@
+package shop.alien.entity.store.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 洗浴设施及服务分类汇总视图对象
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Data
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@ApiModel(value = "BathFacilityServiceCategoryVo对象", description = "洗浴设施及服务分类汇总视图对象")
+public class BathFacilityServiceCategoryVo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "设施分类(1:洗浴区, 2:汗蒸区, 3:休闲区, 4:餐饮区)")
+    private Integer facilityCategory;
+
+    @ApiModelProperty(value = "设施分类名称")
+    private String facilityCategoryName;
+
+    @ApiModelProperty(value = "该分类下的设备数量")
+    private Integer facilityCount;
+
+    @ApiModelProperty(value = "该分类的代表图片(从该分类下第一个设备的第一张图片获取)")
+    private String categoryImage;
+
+    @ApiModelProperty(value = "该分类下的设备列表(包含设备信息和图片)")
+    private List<BathFacilityServiceVo> facilityList;
+}
+

+ 66 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/BathFacilityServiceVo.java

@@ -0,0 +1,66 @@
+package shop.alien.entity.store.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 洗浴设施及服务视图对象
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Data
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@ApiModel(value = "BathFacilityServiceVo对象", description = "洗浴设施及服务视图对象")
+public class BathFacilityServiceVo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "主键")
+    private Integer id;
+
+    @ApiModelProperty(value = "门店ID")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "设施分类(1:洗浴区, 2:汗蒸区, 3:休闲区, 4:餐饮区)")
+    private Integer facilityCategory;
+
+    @ApiModelProperty(value = "设施分类名称")
+    private String facilityCategoryName;
+
+    @ApiModelProperty(value = "名称")
+    private String facilityName;
+
+    @ApiModelProperty(value = "收费标准")
+    private String chargingStandard;
+
+    @ApiModelProperty(value = "使用时间类型(0:全天, 1:选择时间)")
+    private Integer usageTimeType;
+
+    @ApiModelProperty(value = "使用时间类型文本")
+    private String usageTimeTypeText;
+
+    @ApiModelProperty(value = "使用开始时间(HH:mm格式)")
+    private String usageStartTime;
+
+    @ApiModelProperty(value = "使用结束时间(HH:mm格式)")
+    private String usageEndTime;
+
+    @ApiModelProperty(value = "使用时间范围(如: 08:00-20:00)")
+    private String usageTimeRange;
+
+    @ApiModelProperty(value = "是否显示在店铺详情(0:隐藏, 1:显示)")
+    private Integer displayInStoreDetail;
+
+    @ApiModelProperty(value = "是否显示在店铺详情文本")
+    private String displayInStoreDetailText;
+
+    @ApiModelProperty(value = "图片列表")
+    private List<String> imageList;
+}
+

+ 24 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/CouponAndEventVo.java

@@ -0,0 +1,24 @@
+package shop.alien.entity.store.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import shop.alien.entity.store.StoreImg;
+
+import java.util.List;
+
+
+@Data
+@JsonInclude
+@NoArgsConstructor
+@ApiModel(value = "代金券和营销活动", description = "代金券和营销活动")
+public class CouponAndEventVo {
+
+    @ApiModelProperty(value = "代金券")
+    private List<LifeCouponVo> couponList;
+
+    @ApiModelProperty(value = "营销活动")
+    private List<StoreImg> marketingList;
+}

+ 82 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/DrinkInfoVo.java

@@ -0,0 +1,82 @@
+package shop.alien.entity.store.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 酒水餐食信息表 VO
+ *
+ * @author ssk
+ * @since 2025-06-13
+ */
+@Data
+@ApiModel(value = "DrinkInfoVo", description = "酒水餐食信息表视图对象")
+public class DrinkInfoVo {
+
+    @ApiModelProperty(value = "主键ID")
+    private Integer id;
+
+    @ApiModelProperty(value = "类型(1:餐食,2:酒水)")
+    private Integer type;
+
+    @ApiModelProperty(value = "商品名称")
+    private String name;
+
+    @ApiModelProperty(value = "商品价格")
+    private BigDecimal price;
+
+    @ApiModelProperty(value = "商品成本价")
+    private BigDecimal costPrice;
+
+    @ApiModelProperty(value = "商品分类")
+    private String category;
+
+    @ApiModelProperty(value = "酒精度数")
+    private BigDecimal alcoholVolume;
+
+    @ApiModelProperty(value = "商品图片")
+    private String picUrl;
+
+    @ApiModelProperty(value = "商品描述")
+    private String description;
+
+    @ApiModelProperty(value = "商品口味")
+    private String flavor;
+
+    @ApiModelProperty(value = "门店ID")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "门店名称")
+    private String storeName;
+
+    @ApiModelProperty(value = "是否推荐(0:否, 1:是)")
+    private Integer isRecommended;
+
+    @ApiModelProperty(value = "状态(0:下架, 1:上架)")
+    private Integer status;
+
+    @ApiModelProperty(value = "排序值")
+    private Integer sort;
+
+    @ApiModelProperty(value = "是否删除(0:否, 1:是)")
+    private Integer isDeleted;
+
+    @ApiModelProperty(value = "创建人ID")
+    private Integer createUserId;
+
+    @ApiModelProperty(value = "创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createTime;
+
+    @ApiModelProperty(value = "更新人ID")
+    private Integer updateUserId;
+
+    @ApiModelProperty(value = "更新时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updateTime;
+}

+ 0 - 1
alien-entity/src/main/java/shop/alien/entity/store/vo/LawyerConsultationOrderVO.java

@@ -6,7 +6,6 @@ import com.fasterxml.jackson.annotation.JsonInclude;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
-import shop.alien.entity.store.LawyerLegalProblemScenario;
 
 import java.io.Serializable;
 import java.math.BigDecimal;

+ 3 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/LifeDiscountCouponFriendRuleVo.java

@@ -39,6 +39,9 @@ public class LifeDiscountCouponFriendRuleVo extends LifeDiscountCouponFriendRule
     @ApiModelProperty(value = "优惠券数量")
     private Integer couponNum;
 
+    @ApiModelProperty(value = "优惠券id")
+    private Integer couponId;
+
     @ApiModelProperty(value = "面值")
     private BigDecimal nominalValue;
 

+ 3 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/LifeDiscountCouponVo.java

@@ -120,6 +120,9 @@ public class LifeDiscountCouponVo {
     @ApiModelProperty(value = "经营板块id(词典表 键为 business_section)")
     private Integer businessSection;
 
+    @ApiModelProperty(value = "经营板块名称")
+    private String businessSectionName;
+
     @ApiModelProperty(value = "自定义领取规则数量")
     private Integer claimRuleCustomizeValue;
 

+ 42 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/SportsEquipmentFacilityCategoryVo.java

@@ -0,0 +1,42 @@
+package shop.alien.entity.store.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 运动器材设施分类汇总视图对象
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Data
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@ApiModel(value = "SportsEquipmentFacilityCategoryVo对象", description = "运动器材设施分类汇总视图对象")
+public class SportsEquipmentFacilityCategoryVo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "门店ID")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "设施分类(1:有氧区, 2:力量区, 3:单功能机械区)")
+    private Integer facilityCategory;
+
+    @ApiModelProperty(value = "设施分类名称")
+    private String facilityCategoryName;
+
+    @ApiModelProperty(value = "该分类下的设备数量")
+    private Integer facilityCount;
+
+    @ApiModelProperty(value = "该分类下的图片列表")
+    private List<String> imageList;
+
+    @ApiModelProperty(value = "该分类下的设备列表")
+    private List<SportsEquipmentFacilityVo> facilityList;
+}
+

+ 61 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/SportsEquipmentFacilityVo.java

@@ -0,0 +1,61 @@
+package shop.alien.entity.store.vo;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 运动器材设施视图对象
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Data
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@ApiModel(value = "SportsEquipmentFacilityVo对象", description = "运动器材设施视图对象")
+public class SportsEquipmentFacilityVo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "主键")
+    private Integer id;
+
+    @ApiModelProperty(value = "门店ID")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "设施分类(1:有氧区, 2:力量区, 3:单功能机械区)")
+    private Integer facilityCategory;
+
+    @ApiModelProperty(value = "设施分类名称")
+    private String facilityCategoryName;
+
+    @ApiModelProperty(value = "设施名称")
+    private String facilityName;
+
+    @ApiModelProperty(value = "数量")
+    private Integer quantity;
+
+    @ApiModelProperty(value = "品牌")
+    private String brand;
+
+    @ApiModelProperty(value = "描述")
+    private String description;
+
+    @ApiModelProperty(value = "是否显示在店铺详情(0:隐藏, 1:显示)")
+    private Integer displayInStoreDetail;
+
+    @ApiModelProperty(value = "是否显示在店铺详情文本")
+    private String displayInStoreDetailText;
+
+    @ApiModelProperty(value = "收费类型0-免费,1-收费")
+    private Integer billingType;
+
+    @ApiModelProperty(value = "图片列表")
+    private List<String> imageList;
+}
+

+ 53 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/StoreAlbumDetailVo.java

@@ -0,0 +1,53 @@
+package shop.alien.entity.store.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 官方相册详情VO(包含相册名称、图片列表和数量)
+ *
+ * @author zhangchen
+ * @since 2025-01-16
+ */
+@Data
+@JsonInclude
+@ApiModel(value = "StoreAlbumDetailVo", description = "官方相册详情VO")
+public class StoreAlbumDetailVo {
+
+    @ApiModelProperty(value = "相册名称")
+    private String albumName;
+
+    @ApiModelProperty(value = "该相册下的图片数量")
+    private Integer imgCount;
+
+    @ApiModelProperty(value = "该相册下的图片列表")
+    private List<StoreImgInfo> imgList;
+
+    /**
+     * 图片信息
+     */
+    @Data
+    @JsonInclude
+    @ApiModel(value = "StoreImgInfo", description = "图片信息")
+    public static class StoreImgInfo {
+        @ApiModelProperty(value = "图片ID")
+        private Integer id;
+
+        @ApiModelProperty(value = "图片链接")
+        private String imgUrl;
+
+        @ApiModelProperty(value = "图片描述")
+        private String imgDescription;
+
+        @ApiModelProperty(value = "图片排序")
+        private Integer imgSort;
+
+        @ApiModelProperty(value = "图片类型")
+        private Integer imgType;
+    }
+}
+

+ 25 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/StoreAlbumNameVo.java

@@ -0,0 +1,25 @@
+package shop.alien.entity.store.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * 官方相册名称VO
+ *
+ * @author zhangchen
+ * @since 2025-01-16
+ */
+@Data
+@JsonInclude
+@ApiModel(value = "StoreAlbumNameVo", description = "官方相册名称VO")
+public class StoreAlbumNameVo {
+
+    @ApiModelProperty(value = "相册名称")
+    private String albumName;
+
+    @ApiModelProperty(value = "该相册下的图片数量")
+    private Integer imgCount;
+}
+

+ 4 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/StoreCommentVo.java

@@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import shop.alien.entity.store.StoreComment;
+import shop.alien.entity.store.StoreImg;
 
 import java.util.List;
 
@@ -65,4 +66,7 @@ public class StoreCommentVo extends StoreComment {
 
     @ApiModelProperty(value = "门店名称")
     private String  storeName;
+
+    @ApiModelProperty(value = "图片地址")
+    private List<StoreImg> imgList;
 }

+ 30 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/StoreInfoVo.java

@@ -1,5 +1,6 @@
 package shop.alien.entity.store.vo;
 
+import com.alibaba.fastjson2.JSONObject;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.annotation.JsonInclude;
 import io.swagger.annotations.ApiModel;
@@ -215,6 +216,35 @@ public class StoreInfoVo extends StoreInfo {
     @ApiModelProperty(value = "动态数量")
     private Integer dynamicsNum;
 
+    @ApiModelProperty(value = "推荐列表距离(米)")
+    private String distance3;
+
+    @ApiModelProperty(value = "店铺头图(多图列表)")
+    private List<String> storeAlbumUrlList;
+
+    @ApiModelProperty(value = "分类id(词典表 键为 business_classify)(多个ID用逗号拼接)")
+    private String businessClassify;
+
+    @ApiModelProperty(value = "分类名称")
+    private String businessClassifyName;
+
+    @ApiModelProperty(value = "分类id(词典表 键为 business_classify)(多个ID用逗号拼接)")
+    private List<String> businessClassifyList;
+
+    @ApiModelProperty(value = "分类名称")
+    private List<String> businessClassifyNameList;
+
     @ApiModelProperty(value = "是否提供餐食")
     private Integer  mealsFlag;
+
+    @ApiModelProperty(value = "身份证正面")
+    private JSONObject idcardFace;
+    @ApiModelProperty(value = "身份证反面")
+    private JSONObject idcardBack;
+    @ApiModelProperty(value = "经营许可证")
+    private JSONObject jyxkz;
+    @ApiModelProperty(value = "食品经营许可证")
+    private JSONObject foodLicence;
+    @ApiModelProperty(value = "娱乐经营许可证")
+    private JSONObject entertainmentLicence;
 }

+ 6 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/StoreMainInfoVo.java

@@ -44,6 +44,12 @@ public class StoreMainInfoVo extends StoreInfo {
     @ApiModelProperty(value = "菜单")
     List<StoreMenuVo> menuUrl;
 
+    @ApiModelProperty(value = "推荐酒水")
+    List<StoreMenuVo> recommendBeverageUrl;
+
+    @ApiModelProperty(value = "酒水单")
+    List<StoreMenuVo> beverageUrl;
+
     @ApiModelProperty(value = "门店标签")
     StoreLabel storeLabel;
 

+ 29 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/StoreOfficialAlbumImgVo.java

@@ -0,0 +1,29 @@
+package shop.alien.entity.store.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import shop.alien.entity.store.StoreImg;
+
+import java.util.List;
+
+/**
+ * 官方相册图片列表返回VO
+ *
+ * @author zhangchen
+ * @since 2025-01-16
+ */
+@Data
+@JsonInclude
+@ApiModel(value = "StoreOfficialAlbumImgVo", description = "官方相册图片列表返回VO")
+public class StoreOfficialAlbumImgVo {
+
+    @ApiModelProperty(value = "图片列表")
+    private List<StoreImg> imgList;
+
+    @ApiModelProperty(value = "图片总数")
+    private Integer totalCount;
+
+}
+

+ 34 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/StorePersonnelVo.java

@@ -0,0 +1,34 @@
+package shop.alien.entity.store.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import shop.alien.entity.store.StorePersonnel;
+
+import java.util.List;
+
+/**
+ * 店铺人员视图对象
+ *
+ * @author system
+ * @since 2025-01-15
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@JsonInclude
+public class StorePersonnelVo extends StorePersonnel {
+
+    @ApiModelProperty(value = "图片排序")
+    private Integer imgSort;
+
+    @ApiModelProperty(value = "图片链接")
+    private String imgUrl;
+
+    @ApiModelProperty(value = "图片描述")
+    private String imgDescription;
+
+    @ApiModelProperty(value = "人员排序列表")
+    private List<StorePersonnelVo> sortList;
+}
+

+ 32 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/StoreThreeLevelStructureVo.java

@@ -0,0 +1,32 @@
+package shop.alien.entity.store.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import shop.alien.entity.store.StoreDictionary;
+
+import java.util.List;
+
+/**
+ * 门店三级分类结构VO
+ *
+ * @author ssk
+ * @since 2025-01-XX
+ */
+@Data
+@JsonInclude
+@ApiModel(value = "StoreThreeLevelStructureVo对象", description = "门店三级分类结构")
+public class StoreThreeLevelStructureVo {
+
+    @ApiModelProperty(value = "门店ID")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "门店名称")
+    private String storeName;
+
+    @ApiModelProperty(value = "三级分类树状结构")
+    private List<StoreDictionary> threeLevelStructure;
+
+}
+

+ 3 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/StoreUserVo.java

@@ -39,4 +39,7 @@ public class StoreUserVo extends StoreUser {
 
     @ApiModelProperty(value = "手机号")
     private String phone;
+
+    @ApiModelProperty(value = "是否提供餐食")
+    private Integer mealsFlag;
 }

+ 1 - 1
alien-entity/src/main/java/shop/alien/entity/storePlatform/StoreOperationalActivity.java

@@ -67,7 +67,7 @@ public class StoreOperationalActivity {
     @TableField("coupon_quantity")
     private Integer couponQuantity;
 
-    @ApiModelProperty(value = "状态:0-禁用, 1-启用")
+    @ApiModelProperty(value = "状态:1-待审核, 2-未开始, 3-审核拒绝, 4-已售罄, 5-进行中, 6-已下架, 7-已结束")
     @TableField("status")
     private Integer status;
 

+ 17 - 0
alien-entity/src/main/java/shop/alien/mapper/BathFacilityServiceMapper.java

@@ -0,0 +1,17 @@
+package shop.alien.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import shop.alien.entity.store.BathFacilityService;
+
+/**
+ * 洗浴设施及服务 Mapper 接口
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Mapper
+public interface BathFacilityServiceMapper extends BaseMapper<BathFacilityService> {
+
+}
+

+ 177 - 0
alien-entity/src/main/java/shop/alien/mapper/LifeCouponMapper.java

@@ -80,4 +80,181 @@ public interface LifeCouponMapper extends BaseMapper<LifeCoupon> {
             @Param("buyCount") int buyCount,
             @Param("soldOutStatus") int soldOutStatus
     );
+
+
+    /**
+     * 查询代金券详情(连表查询商铺信息)
+     *
+     * @param id 代金券ID
+     * @return LifeCouponVo
+     */
+    @Select("SELECT " +
+            "lc.id, " +
+            "lc.data_type, " +
+            "lc.buy_use_start_time, " +
+            "lc.buy_use_end_time, " +
+            "lc.use_festival, " +
+            "lc.coupon_code, " +
+            "lc.name, " +
+            "lc.store_id, " +
+            "lc.price, " +
+            "lc.offprice, " +
+            "lc.expiration_date, " +
+            "lc.start_date, " +
+            "lc.end_date, " +
+            "lc.unused_date, " +
+            "lc.single_qty, " +
+            "lc.buy_limit, " +
+            "lc.stock_qty, " +
+            "lc.use_rule, " +
+            "lc.min_use_peoples, " +
+            "lc.max_use_peoples, " +
+            "lc.dietary_preferences, " +
+            "lc.cooking_methods, " +
+            "lc.applicable_rule, " +
+            "lc.status, " +
+            "lc.image_path, " +
+            "lc.store_service, " +
+            "lc.fapiao_info, " +
+            "lc.type, " +
+            "lc.approval_comments, " +
+            "lc.open_price_protection, " +
+            "lc.price_below, " +
+            "lc.coupon_comp, " +
+            "lc.coupon_comp_date, " +
+            "lc.rate_score, " +
+            "lc.discount_tag, " +
+            "lc.discount_tag_name, " +
+            "lc.delete_flag, " +
+            "lc.status_delete_flag, " +
+            "lc.created_time, " +
+            "lc.created_user_id, " +
+            "lc.updated_time, " +
+            "lc.updated_user_id, " +
+            "lc.store_type, " +
+            "lc.sale_time_str_type, " +
+            "lc.sale_time_end_type, " +
+            "lc.purchase_limit_code, " +
+            "lc.original_price, " +
+            "lc.discounted_price, " +
+            "lc.business_types, " +
+            "lc.housing_type, " +
+            "lc.room_type, " +
+            "lc.room_type_code, " +
+            "lc.kitchen_xq, " +
+            "lc.bathroom_xq, " +
+            "lc.living_room, " +
+            "lc.location_of_the_property, " +
+            "lc.total_area, " +
+            "lc.entertainment_facilities_code, " +
+            "lc.entertainment_facilities, " +
+            "lc.convenience_facilities_code, " +
+            "lc.convenience_facilities, " +
+            "lc.bathroom_facilities_code, " +
+            "lc.bathroom_facilities, " +
+            "lc.bath_products_code, " +
+            "lc.bath_products, " +
+            "lc.service_code, " +
+            "lc.service, " +
+            "lc.safety_code, " +
+            "lc.safety, " +
+            "lc.reservation_instructions, " +
+            "lc.in_time, " +
+            "lc.out_time, " +
+            "lc.deposit_flag, " +
+            "lc.deposit_amount, " +
+            "lc.children_flag, " +
+            "lc.children_description, " +
+            "lc.pet_flag, " +
+            "lc.extra_bed_flag, " +
+            "lc.bed_price, " +
+            "lc.invoice_info, " +
+            "lc.invoice_instructions, " +
+            "lc.cancellation_policy_type, " +
+            "lc.cancellation_policy, " +
+            "lc.Cancellation_instructions, " +
+            "lc.insured_price, " +
+            "lc.validity_period_type, " +
+            "lc.box_type_code, " +
+            "lc.box_type, " +
+            "lc.snacks_code, " +
+            "lc.snacks, " +
+            "lc.available_duration, " +
+            "lc.write_off_type, " +
+            "lc.write_off, " +
+            "lc.refund_rules_type, " +
+            "lc.refund_rules, " +
+            "lc.refund_instructions, " +
+            "lc.edit_rules_code, " +
+            "lc.edit_rules, " +
+            "lc.edit_instructions, " +
+            "lc.tangchi_code, " +
+            "lc.tangchi, " +
+            "lc.sweat_sauna_code, " +
+            "lc.sweat_sauna, " +
+            "lc.pictures_and_text, " +
+            "lc.supplement, " +
+            "lc.unavailable_date_type, " +
+            "lc.reservation_rules, " +
+            "lc.applicable_num, " +
+            "lc.other_rules, " +
+            "lc.sales_type, " +
+            "lc.massage_technique_code, " +
+            "lc.massage_technique, " +
+            "lc.massage_area_code, " +
+            "lc.massage_area, " +
+            "lc.massage_tools_code, " +
+            "lc.massage_tools, " +
+            "lc.compress_tools_code, " +
+            "lc.compress_tools, " +
+            "lc.class_format_code, " +
+            "lc.class_format, " +
+            "lc.class_duration_code, " +
+            "lc.class_duration, " +
+            "lc.class_num_code, " +
+            "lc.class_num, " +
+            "lc.applicable_parts_code, " +
+            "lc.applicable_parts, " +
+            "lc.hygiene_code, " +
+            "lc.hygiene, " +
+            "lc.foundation_code, " +
+            "lc.foundation, " +
+            "lc.bathroom_code, " +
+            "lc.bathroom, " +
+            "lc.kitchen_code, " +
+            "lc.kitchen, " +
+            "lc.validity_period_yh_type, " +
+            "lc.validity_period_yh, " +
+            "lc.course_validity_period_code, " +
+            "lc.course_validity_period, " +
+            "lc.uploaded_picList, " +
+            "lc.validity_period, " +
+            "lc.stacking_type, " +
+            "lc.general_type, " +
+            "lc.single_can_use, " +
+            "lc.apply_type, " +
+            "lc.apply_desc, " +
+            "lc.expiration_type, " +
+            "lc.unused_type, " +
+            "lc.house_type, " +
+            "lc.house_type_b, " +
+            "lc.house_type_l, " +
+            "lc.house_type_k, " +
+            "lc.house_type_t, " +
+            "lc.sale_time_str, " +
+            "lc.sale_time_end, " +
+            "lc.unavai_lable_date, " +
+            "lc.room_type_str, " +
+            "lc.time_range, " +
+            "lc.cancellation_policy_str, " +
+            "lc.validity_periodyh_str, " +
+            "si.store_name, " +
+            "si.store_address, " +
+            "si.store_tel AS phone, " +
+            "si.business_status, " +
+            "si.store_status " +
+            "FROM life_coupon lc " +
+            "LEFT JOIN store_info si ON si.id = lc.store_id AND si.delete_flag = 0 " +
+            "WHERE lc.id = #{id} AND lc.delete_flag = 0")
+    LifeCouponVo getNewCouponDetail(@Param("id") String id);
 }

+ 2 - 0
alien-entity/src/main/java/shop/alien/mapper/LifeDiscountCouponStoreFriendMapper.java

@@ -38,6 +38,7 @@ public interface LifeDiscountCouponStoreFriendMapper extends BaseMapper<LifeDisc
     @Select("select ldcsf.created_time endDate,ldc.nominal_value nominalValue,ldc.minimum_spending_amount minimumSpendingAmount,img.img_url imgUrl,\n" +
             "si.store_name storeName,\n" +
             "ldc.name couponName,\n" +
+            "ldc.id couponId,\n" +
             "ldcsf.single_qty couponNum\n" +
             "from  life_discount_coupon_store_friend ldcsf\n" +
             "left join life_discount_coupon ldc\n" +
@@ -53,6 +54,7 @@ public interface LifeDiscountCouponStoreFriendMapper extends BaseMapper<LifeDisc
     @Select("select ldcsf.created_time endDate,ldc.nominal_value nominalValue,ldc.minimum_spending_amount minimumSpendingAmount,img.img_url imgUrl,\n" +
             "si.store_name storeName,\n" +
             "ldc.name couponName,\n" +
+            "ldc.id couponId,\n" +
             "ldcsf.single_qty couponNum\n" +
             "from  life_discount_coupon_store_friend ldcsf\n" +
             "left join life_discount_coupon ldc\n" +

+ 9 - 5
alien-entity/src/main/java/shop/alien/mapper/LifeFansMapper.java

@@ -15,7 +15,8 @@ import java.util.List;
 @Mapper
 public interface LifeFansMapper extends BaseMapper<LifeFans> {
 
-    @Select("select foll.*,lb.id blackListid, if(isnull(fans.id), 0, 1) isFollowMe, 1 as isFollowThis,  " +
+    @Select("select MAX(foll.id) id, MAX(foll.name) name, MAX(foll.image) image, foll.phoneId, MAX(foll.blurb) blurb, MAX(foll.blockedType) blockedType, MAX(foll.blockedId) blockedId, MAX(foll.username) username, MAX(foll.accountBlurb) accountBlurb, " +
+            "  MAX(lb.id) blackListid, MAX(if(isnull(fans.id), 0, 1)) isFollowMe, 1 as isFollowThis,  " +
             "  (select count(1) from life_fans where fans_id= foll.phoneId and delete_flag =0) followNum, " +
             "  (select count(1) from life_fans where followed_id= foll.phoneId and delete_flag =0) fansNum from ( " +
             "    with follow as (   " +
@@ -63,7 +64,8 @@ public interface LifeFansMapper extends BaseMapper<LifeFans> {
             "left join life_fans fans on fans.fans_id = foll.phoneId and fans.followed_id = #{fansId} and fans.delete_flag = 0 ")
     List<LifeFansVo> getMyFollowedAll(@Param("fansId") String fansId);
 
-    @Select("select foll.*,lb.id blackListid, if(isnull(fans.id), 0, 1) isFollowThis, 1 as isFollowMe, " +
+    @Select("select MAX(foll.id) id, MAX(foll.name) name, MAX(foll.image) image, foll.phoneId, MAX(foll.blurb) blurb, MAX(foll.blockedType) blockedType, MAX(foll.blockedId) blockedId, " +
+            "  MAX(lb.id) blackListid, MAX(if(isnull(fans.id), 0, 1)) isFollowThis, 1 as isFollowMe, " +
             "    (select count(1) from life_fans fans2 where fans2.followed_id = foll.phoneId and fans2.delete_flag = 0) fansNum, " +
             "    (select count(1) from life_fans fans3 where fans3.fans_id = foll.phoneId and fans3.delete_flag = 0) followNum " +
             "from ( " +
@@ -169,7 +171,8 @@ public interface LifeFansMapper extends BaseMapper<LifeFans> {
             "${ew.customSqlSegment}")
     IPage<LifeFansVo> getMyStoreFans(IPage<LifeFansVo> iPage, @Param("fansId") String fansId, @Param(Constants.WRAPPER) QueryWrapper<LifeFansVo> wrapper);
 
-    @Select("select foll.*, if(isnull(fans.id), 0, 1) isFollowThis, 1 as isFollowMe, " +
+    @Select("select MAX(foll.id) id, MAX(foll.name) name, MAX(foll.image) image, foll.phoneId, MAX(foll.blurb) blurb, " +
+            "  MAX(if(isnull(fans.id), 0, 1)) isFollowThis, 1 as isFollowMe, " +
             "       (select count(1) from life_fans fans2 where fans2.followed_id = foll.phoneId and fans2.delete_flag = 0) fansNum, " +
             "       (select count(1) from life_fans fans3 where fans3.fans_id = foll.phoneId and fans3.delete_flag = 0) followNum " +
             " from ( " +
@@ -187,7 +190,8 @@ public interface LifeFansMapper extends BaseMapper<LifeFans> {
             "${ew.customSqlSegment} ")
     IPage<LifeFansVo> getMyUserFans(IPage<LifeFansVo> iPage, @Param("fansId") String fansId, @Param(Constants.WRAPPER) QueryWrapper<LifeFansVo> wrapper);
 
-    @Select("select foll.*, lb.id blackListid, 1 as isFollowThis, 1 as isFollowMe, " +
+    @Select("select MAX(foll.id) id, MAX(foll.name) name, MAX(foll.image) image, foll.phoneId, MAX(foll.blurb) blurb, MAX(foll.blockedType) blockedType, MAX(foll.blockedId) blockedId, MAX(foll.username) username, MAX(foll.accountBlurb) accountBlurb, " +
+            "  MAX(lb.id) blackListid, 1 as isFollowThis, 1 as isFollowMe, " +
             "       (select count(1) from life_fans fans2 where fans2.followed_id = foll.phoneId and fans2.delete_flag = 0) fansNum, " +
             "       (select count(1) from life_fans fans3 where fans3.fans_id = foll.phoneId and fans3.delete_flag = 0) followNum " +
             "from ( " +
@@ -213,7 +217,7 @@ public interface LifeFansMapper extends BaseMapper<LifeFans> {
             "${ew.customSqlSegment} ")
     IPage<LifeFansVo> getMutualAttention(IPage<LifeFansVo> iPage, @Param("fansId") String fansId, @Param("blockerType") String blockerType, @Param("blockerId") String blockerId, @Param(Constants.WRAPPER) QueryWrapper<LifeFansVo> wrapper);
 
-    @Select("select foll.*, 1 as isFollowThis, 1 as isFollowMe, " +
+    @Select("select MAX(foll.id) id, MAX(foll.name) name, MAX(foll.image) image, foll.phoneId, MAX(foll.blurb) blurb, 1 as isFollowThis, 1 as isFollowMe, " +
             "       (select count(1) from life_fans fans2 where fans2.followed_id = foll.phoneId and fans2.delete_flag = 0) fansNum, " +
             "       (select count(1) from life_fans fans3 where fans3.fans_id = foll.phoneId and fans3.delete_flag = 0) followNum " +
             "from ( " +

+ 17 - 0
alien-entity/src/main/java/shop/alien/mapper/SportsEquipmentFacilityMapper.java

@@ -0,0 +1,17 @@
+package shop.alien.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import shop.alien.entity.store.SportsEquipmentFacility;
+
+/**
+ * 运动器材设施 Mapper 接口
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Mapper
+public interface SportsEquipmentFacilityMapper extends BaseMapper<SportsEquipmentFacility> {
+
+}
+

+ 13 - 0
alien-entity/src/main/java/shop/alien/mapper/StoreCommentMapper.java

@@ -185,4 +185,17 @@ WHERE
             "AND luo.user_id = #{userId} " +
             "AND luo.id IN (SELECT business_id FROM store_comment WHERE business_type = 5 AND user_id = #{userId} AND delete_flag = 0)")
     IPage<LifeUserOrderCommentVo> getCommentOrderYPJPage(IPage<LifeUserOrderCommentVo> page, @Param("userId") String userId);
+
+    @Select("SELECT\n" +
+            "\ts.*,\n" +
+            "\tlu.user_name, \n" +
+            "\tlu.user_image \n" +
+            "FROM\n" +
+            "\tstore_comment s\n" +
+            "\tLEFT JOIN life_user lu ON s.user_id = lu.id \n" +
+            "WHERE\n" +
+            "\ts.business_type = 5 \n" +
+            "\tAND s.store_id = #{storeId}\n" +
+            "\tLIMIT 1")
+    StoreCommentVo getCommentOneInfo(@Param("storeId") int storeId);
 }

+ 26 - 0
alien-entity/src/main/java/shop/alien/mapper/StoreInfoMapper.java

@@ -158,4 +158,30 @@ public interface StoreInfoMapper extends BaseMapper<StoreInfo> {
             "from store_info where id = #{storeId}"
             )
     Double getStoreDistance(@Param("position") String position,@Param("storeId") Integer storeId);
+
+
+    /**
+     * 更多推荐(用户端)
+     *
+     * @param queryWrapper 查询条件
+     * @param position 经纬度位置(格式:经度,纬度)
+     * @return List<StoreInfoVo>
+     */
+    @Select("select a.*,b.name store_contact, b.phone store_phone, b.id_card idCard, b.password, c.dict_detail store_status_str, d.dict_detail business_status_str, e.dict_detail store_type_str,  " +
+            "( " +
+            " select ifnull(round(avg(score), 1), 0) " +
+            " from store_evaluation eval " +
+            " where eval.store_id = a.id and eval.delete_flag = 0 " +
+            ") score, " +
+            "ROUND(ST_Distance_Sphere(ST_GeomFromText(CONCAT('POINT(', REPLACE(#{position}, ',', ' '), ')' )), ST_GeomFromText(CONCAT('POINT(', REPLACE(a.store_position, ',', ' '), ')' )))) distance3 " +
+            "from store_info a " +
+            "left join store_user b on a.id = b.store_id and a.delete_flag = 0 and b.delete_flag = 0 " +
+            "left join store_dictionary c on a.store_status = c.dict_id and c.type_name = 'storeState' and c.delete_flag = 0 " +
+            "left join store_dictionary d on a.business_status = d.dict_id and d.type_name = 'businessStatus' and d.delete_flag = 0 " +
+            "left join store_dictionary e on e.type_name = 'storeType' and e.dict_id = a.store_type and e.delete_flag = 0 " +
+            "${ew.customSqlSegment} " +
+            "and a.store_position is not null and a.store_position != '' " +
+            "and ROUND(ST_Distance_Sphere(ST_GeomFromText(CONCAT('POINT(', REPLACE(#{position}, ',', ' '), ')' )), ST_GeomFromText(CONCAT('POINT(', REPLACE(a.store_position, ',', ' '), ')' ))) / 1000, 2) <= 1 " +
+            "order by distance3 asc limit 20")
+    List<StoreInfoVo> getMoreRecommendedStores(@Param(Constants.WRAPPER) QueryWrapper<StoreInfoVo> queryWrapper, @Param("position") String position);
 }

+ 54 - 0
alien-entity/src/main/java/shop/alien/mapper/StoreMenuMapper.java

@@ -28,6 +28,21 @@ public interface StoreMenuMapper extends BaseMapper<StoreMenu> {
     //"图片类型, 0:其他, 1:入口图, 2:相册, 3:菜品, 4:环境, 5:价目表, 6:推荐菜, 7:菜单, 8:用户评论, 9:商家申诉, 10:商家头像, 11:店铺轮播图"
     @Select("select a.*, b.img_url, b.img_sort, b.img_description from store_menu a " +
             "left join store_img b on a.img_id = b.id where a.delete_flag = 0 and b.delete_flag = 0 " +
+            "and a.store_id = #{storeId} " +
+            "and (if(#{dishType} is null, 1 = 1, a.dish_type = #{dishType})) " +
+            "and (if(#{dishMenuType} is null, 1 = 1, a.dish_menu_type = #{dishMenuType}))")
+    List<StoreMenuVo> getStoreMenuInfoList(@Param("storeId") Integer storeId, @Param("dishType") Integer dishType, @Param("dishMenuType") Integer dishMenuType);
+
+    /**
+     * 获取菜单
+     *
+     * @param storeId  门店id
+     * @param dishType 菜品类型, 0:菜单, 1:推荐
+     * @return List<StoreMenuVo>
+     */
+    //"图片类型, 0:其他, 1:入口图, 2:相册, 3:菜品, 4:环境, 5:价目表, 6:推荐菜, 7:菜单, 8:用户评论, 9:商家申诉, 10:商家头像, 11:店铺轮播图"
+    @Select("select a.*, b.img_url, b.img_sort, b.img_description from store_menu a " +
+            "left join store_img b on a.img_id = b.id where a.delete_flag = 0 and b.delete_flag = 0 " +
             "and a.store_id = #{storeId} AND (if(#{dishType} is null, 1 = 1, a.dish_type = #{dishType}))")
     List<StoreMenuVo> getStoreMenuList(@Param("storeId") Integer storeId, @Param("dishType") Integer dishType);
 
@@ -35,4 +50,43 @@ public interface StoreMenuMapper extends BaseMapper<StoreMenu> {
             "left join store_img b on a.img_id = b.id where a.delete_flag = 0 and b.delete_flag = 0 " +
             "and a.id = #{id}")
     StoreMenuVo getMenuInfo(@Param("id") Integer id);
+
+    /**
+     * 获取菜单(客户端)
+     * <p>
+     * 根据门店ID查询菜单列表,支持按菜品类型和菜单类型筛选。
+     * 查询未删除的菜单及其关联的图片信息。
+     * </p>
+     *
+     * @param storeId      门店ID,必填
+     * @param dishType     菜品类型,可选,0:非推荐, 1:推荐。当为null时,不限制菜品类型
+     * @param dishMenuType 菜单类型,可选,1-菜单,2-酒水。当为null时,不限制菜单类型
+     * @return 菜单列表,包含菜单信息和关联的图片信息
+     */
+    @Select("<script>" +
+            "SELECT " +
+            "    a.*, " +
+            "    b.img_url, " +
+            "    b.img_sort, " +
+            "    b.img_description " +
+            "FROM store_menu a " +
+            "LEFT JOIN store_img b ON a.img_id = b.id " +
+            "WHERE a.delete_flag = 0 " +
+            "    AND (b.delete_flag = 0 OR b.delete_flag IS NULL) " +
+            "    AND a.store_id = #{storeId} " +
+            "<if test='dishType != null'>" +
+            "    AND a.dish_type = #{dishType} " +
+            "</if>" +
+            "<if test='dishMenuType != null'>" +
+            "    AND a.dish_menu_type = #{dishMenuType} " +
+            "</if>" +
+            "</script>")
+    List<StoreMenuVo> getClientMenuByStoreId(@Param("storeId") Integer storeId,
+                                             @Param("dishType") Integer dishType,
+                                             @Param("dishMenuType") Integer dishMenuType);
+
+    @Select("select a.*, b.img_url, b.img_sort, b.img_description from store_menu a " +
+            "left join store_img b on a.img_id = b.id where a.delete_flag = 0 and b.delete_flag = 0 " +
+            "and a.id = #{id}")
+    StoreMenuVo getClientMenuInfoById(@Param("id") Integer id);
 }

+ 44 - 0
alien-entity/src/main/java/shop/alien/mapper/StorePersonnelMapper.java

@@ -0,0 +1,44 @@
+package shop.alien.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import shop.alien.entity.store.StorePersonnel;
+import shop.alien.entity.store.vo.StorePersonnelVo;
+
+import java.util.List;
+
+/**
+ * 店铺人员 Mapper 接口
+ *
+ * @author system
+ * @since 2025-01-15
+ */
+@Mapper
+public interface StorePersonnelMapper extends BaseMapper<StorePersonnel> {
+
+    /**
+     * 获取店铺人员列表
+     *
+     * @param storeId 门店id
+     * @return List<StorePersonnelVo>
+     */
+    @Select("select a.*, b.img_url, b.img_sort, b.img_description from store_personnel a " +
+            "left join store_img b on a.img_id = b.id where a.delete_flag = 0 and b.delete_flag = 0 " +
+            "and a.store_id = #{storeId} " +
+            "order by a.sort asc")
+    List<StorePersonnelVo> getStorePersonnelList(@Param("storeId") Integer storeId);
+
+    /**
+     * 获取人员详情
+     *
+     * @param id 人员id
+     * @return StorePersonnelVo
+     */
+    @Select("select a.*, b.img_url, b.img_sort, b.img_description from store_personnel a " +
+            "left join store_img b on a.img_id = b.id where a.delete_flag = 0 and b.delete_flag = 0 " +
+            "and a.id = #{id}")
+    StorePersonnelVo getPersonnelInfo(@Param("id") Integer id);
+}
+

+ 40 - 13
alien-entity/src/main/java/shop/alien/mapper/TagsMainMapper.java

@@ -5,6 +5,7 @@ import org.apache.ibatis.annotations.Insert;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Select;
 import shop.alien.entity.store.TagsMain;
+import shop.alien.entity.store.vo.StoreCommentVo;
 import shop.alien.entity.store.vo.TagsMainVo;
 
 import java.util.List;
@@ -40,21 +41,47 @@ public interface TagsMainMapper extends BaseMapper<TagsMain> {
     })
     int insertBatchTagsMain(List<TagsMain> tagsMainList);
 
+
+    @Select("SELECT\n" +
+            "  main.id,\n" +
+            "  main.tag_name,\n" +
+            "  main.store_id,\n" +
+            "  main.tag_type,\n" +
+            "  IFNULL(GROUP_CONCAT(DISTINCT synonym.comment_id ORDER BY synonym.comment_id SEPARATOR ','), '') AS evaluate_ids,\n" +
+            "  IFNULL(COUNT(DISTINCT synonym.comment_id), 0) AS evaluateNumber\n" +
+            "FROM\n" +
+            "  tags_main main\n" +
+            "LEFT JOIN tags_synonym synonym \n" +
+            "  ON main.id = synonym.main_tag_id\n" +
+            "  AND synonym.delete_flag = 0  \n" +
+            "WHERE\n" +
+            "  main.store_id = #{storeId}\n" +
+            "  AND main.delete_flag = 0\n" +
+            "GROUP BY\n" +
+            "  main.id, main.tag_name, main.store_id, main.tag_type  \n" +
+            "ORDER BY\n" +
+            "  main.id;")
+    List<TagsMainVo> getStoreEvaluateTags(Integer storeId);
+
+
     @Select("SELECT\n" +
-            "    main.id,\n" +
-            "    main.tag_name,\n" +
-            "    main.store_id,\n" +
-            "    main.tag_type,\n" +
-            "    COUNT(DISTINCT synonym.comment_id) AS evaluateNumber\n" +
+            "  ts.comment_id,\n" +
+            "  MIN(ts.id) AS tag_id,  \n" +
+            "  ts.main_tag_id,\n" +
+            "  GROUP_CONCAT(DISTINCT ts.synonym_tag SEPARATOR ',') AS synonym_tags,  \n" +
+            "  MIN(ts.delete_flag) AS tag_delete_flag,\n" +
+            "  MAX(ts.created_time) AS tag_created_time,\n" +
+            "  sc.*\n" +
             "FROM\n" +
-            "    tags_main main\n" +
-            "    LEFT JOIN tags_synonym synonym \n" +
-            "        ON main.id = synonym.main_tag_id\n" +
-            "        AND synonym.delete_flag = 0  \n" +
+            "  tags_synonym ts\n" +
+            "LEFT JOIN store_comment sc \n" +
+            "  ON ts.comment_id = sc.id\n" +
             "WHERE\n" +
-            "    main.store_id = #{storeId} \n" +
-            "    AND main.delete_flag = 0\n" +
+            "  ts.main_tag_id = #{mainId}  \n" +
             "GROUP BY\n" +
-            "    main.id")
-    List<TagsMainVo> getStoreEvaluateTags(int storeId);
+            "  ts.comment_id, ts.main_tag_id,  \n" +
+            "  sc.id  \n" +
+            "ORDER BY\n" +
+            "  sc.created_time DESC; ")
+    List<StoreCommentVo> getstoreCommentList(Integer mainId);
 }

+ 13 - 0
alien-job/src/main/java/shop/alien/job/feign/AlienStoreFeign.java

@@ -3,7 +3,12 @@ package shop.alien.job.feign;
 import com.alibaba.fastjson.JSONObject;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
+import shop.alien.entity.result.R;
+
+import java.util.Map;
 
 @FeignClient(url = "${feign.alienStore.url}", name = "alien-store")
 public interface AlienStoreFeign {
@@ -56,4 +61,12 @@ public interface AlienStoreFeign {
                                    @RequestParam(value = "refundReason") String refundReason,
                                    @RequestParam(value = "partialRefundCode") String partialRefundCode);
 
+    /**
+     * 退款接口
+     * @param params 退款参数(包含订单号、退款金额等)
+     * @return 退款结果
+     */
+    @RequestMapping("payment/refunds")
+    public R refunds(@RequestBody Map<String, String> params);
+
 }

+ 14 - 0
alien-job/src/main/java/shop/alien/job/feign/SecondGoodsFeign.java

@@ -28,4 +28,18 @@ public interface SecondGoodsFeign {
 
     @GetMapping("/secondGoods/approveAndListGoods")
     boolean approveAndListGoods(SecondGoods goods);
+
+    /**
+     * 获取AI商品审核结果
+     * @return 处理结果
+     */
+    @GetMapping("/secondGoods/getAiGoodsCheckResult")
+    shop.alien.entity.result.R<String> getAiGoodsCheckResult();
+
+    /**
+     * 处理所有待处理的视频审核任务
+     * @return 处理结果
+     */
+    @GetMapping("/secondGoods/processVideoModerationResult")
+    shop.alien.entity.result.R<String> processVideoModerationResult();
 }

+ 5 - 41
alien-job/src/main/java/shop/alien/job/jobhandler/VideoModerationJobHandler.java

@@ -5,11 +5,8 @@ import com.xxl.job.core.handler.annotation.XxlJob;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
-import shop.alien.entity.SecondVideoTask;
+import shop.alien.entity.result.R;
 import shop.alien.job.feign.SecondGoodsFeign;
-import shop.alien.mapper.system.SecondVideoTaskMapper;
-
-import java.util.List;
 
 /**
  * 视频审核任务XXL-JOB处理器
@@ -20,57 +17,24 @@ import java.util.List;
 public class VideoModerationJobHandler {
 
     /**
-     * 视频审核任务Mapper
-     */
-    private final SecondVideoTaskMapper videoModerationTaskMapper;
-
-    /**
      * 二级商品服务Feign客户端
      */
     private final SecondGoodsFeign secondGoodsFeign;
     
     /**
      * 视频审核结果拉取任务
-     * 每30秒执行一次
+     * 通过Feign调用alien-second服务处理视频审核结果
      */
     @XxlJob("videoModerationResultJobHandler")
     public ReturnT<String> videoModerationResultJobHandler(String param) {
         try {
             log.info("开始执行视频审核结果拉取任务");
-            
-            // 查询待处理的审核任务(状态为SUBMITTED或PROCESSING)
-            List<SecondVideoTask> pendingTasks = videoModerationTaskMapper.selectPendingTasks();
-            
-            if (pendingTasks.isEmpty()) {
-                log.info("没有待处理的视频审核任务");
-                return ReturnT.SUCCESS;
-            }
-            
-            log.info("共找到 {} 个待处理的视频审核任务", pendingTasks.size());
-            
-            // 处理每个任务
-            int successCount = 0;
-            for (SecondVideoTask task : pendingTasks) {
-                try {
-                    boolean success = secondGoodsFeign.processTask(task.getTaskId());
-                    if (success) {
-                        successCount++;
-                        // 处理视频审核结果,更新商品状态
-                        log.info("处理第 {} 个task", successCount);
-                        log.info("TaskId:开始 {} ", task.getTaskId());
-                        secondGoodsFeign.processVideoResult(task.getTaskId());
-                        log.info("TaskId:结束 {} ", task.getTaskId());
-                    }
-                } catch (Exception e) {
-                    log.error("处理视频审核任务时发生异常,任务ID: {}", task.getTaskId(), e);
-                }
-            }
-            
-            log.info("视频审核结果拉取任务执行完成,成功处理 {} 个任务", successCount);
+            R<String> result = secondGoodsFeign.processVideoModerationResult();
+            log.info("视频审核结果拉取任务执行完成: {}", result.getData());
             return ReturnT.SUCCESS;
         } catch (Exception e) {
             log.error("执行视频审核结果拉取任务时发生异常", e);
             return ReturnT.FAIL;
         }
     }
-}
+}

+ 173 - 17
alien-job/src/main/java/shop/alien/job/second/AiCheckXxlJob.java

@@ -3,26 +3,33 @@ package shop.alien.job.second;
 import com.alibaba.fastjson2.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.xxl.job.core.context.XxlJobHelper;
 import com.xxl.job.core.handler.annotation.XxlJob;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.client.ClientHttpRequestInterceptor;
 import org.springframework.stereotype.Component;
 import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.util.MultiValueMap;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.ResourceAccessException;
 import org.springframework.web.client.RestTemplate;
 import org.springframework.http.*;
+import shop.alien.entity.result.R;
 import shop.alien.entity.second.SecondGoodsRecord;
 import shop.alien.entity.second.SecondRiskControlRecord;
-import shop.alien.entity.store.LifeUser;
-import shop.alien.entity.store.LifeUserViolation;
-import shop.alien.entity.store.StoreDictionary;
-import shop.alien.mapper.LifeUserMapper;
-import shop.alien.mapper.LifeUserViolationMapper;
-import shop.alien.mapper.StoreDictionaryMapper;
+import shop.alien.entity.store.*;
+import shop.alien.mapper.*;
 import shop.alien.mapper.second.SecondGoodsRecordMapper;
 import shop.alien.mapper.second.SecondRiskControlRecordMapper;
+import shop.alien.util.common.Constants;
 
+import java.net.SocketException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -39,6 +46,9 @@ import java.util.stream.Collectors;
 @Slf4j
 @Component
 @RequiredArgsConstructor
+//@RestController
+//@RequestMapping("/job")
+//@RequiredArgsConstructor
 public class AiCheckXxlJob {
 
     // 添加RestTemplate用于HTTP调用
@@ -54,6 +64,9 @@ public class AiCheckXxlJob {
 
     private final SecondRiskControlRecordMapper secondRiskControlRecordMapper;
 
+    @Autowired
+    private final StoreImgMapper storeImgMapper;
+
     // 第三方接口地址 登录接口URL
     @Value("${third-party-login.base-url}")
     private String loginUrl;
@@ -66,6 +79,16 @@ public class AiCheckXxlJob {
     @Value("${third-party-pass-word.base-url}")
     private String passWord;
 
+    // 第三方接口地址 登录接口URL
+    @Value("${third-party-goods.base-url}")
+    private String goodsUrl;
+
+    // 第三方接口地址 登录接口URL
+    @Value("${third-party-goodsresult.base-url}")
+    private String goodsResultUrl;
+
+    private final LifeNoticeMapper lifeNoticeMapper;
+
     /**
      * AI自动审核任务处理器
      * <p>
@@ -81,6 +104,7 @@ public class AiCheckXxlJob {
      * @since 1.0.0
      */
     @XxlJob("aiCheckJobHandler")
+//    @PostMapping("/aiCheckJobHandler")
     public void aiCheckJobHandler() {
         log.info("开始执行AI自动审核任务");
 
@@ -88,8 +112,8 @@ public class AiCheckXxlJob {
             log.info("登录Ai服务获取token..." + loginUrl);
             //构建请求参数
             MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
-            formData.add("username", "admin");    // 表单字段 1:用户名
-            formData.add("password", "123456");    // 表单字段 2:密码
+            formData.add("username", userName);    // 表单字段 1:用户名
+            formData.add("password", passWord);    // 表单字段 2:密码
 
             //设置请求头
             HttpHeaders headers = new HttpHeaders();
@@ -97,7 +121,7 @@ public class AiCheckXxlJob {
             HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers);
             ResponseEntity<String> postForEntity = null;
             try {
-                postForEntity = restTemplate.postForEntity("http://192.168.2.78:9000/ai/user-auth-core/api/v1/auth/login", requestEntity, String.class);
+                postForEntity = restTemplate.postForEntity(loginUrl, requestEntity, String.class);
             } catch (Exception e) {
                 log.error("类:PostMethod 方法:post", e);
             }
@@ -110,7 +134,9 @@ public class AiCheckXxlJob {
                     JSONObject dataJson = jsonObject.getJSONObject("data");
                     String accessToken = dataJson.getString("access_token");
                     // 查询所有待处理的用户违规记录
-                    List<LifeUserViolation> lifeUserViolations = lifeUserViolationMapper.selectList(new LambdaQueryWrapper<LifeUserViolation>().eq(LifeUserViolation::getProcessingStatus, "5"));
+                    List<LifeUserViolation> lifeUserViolations = lifeUserViolationMapper.selectList(new LambdaQueryWrapper<LifeUserViolation>()
+                            .eq(LifeUserViolation::getReportContextType, "4")
+                            .eq(LifeUserViolation::getProcessingStatus, "0"));
 
                     // 遍历每条违规记录,组装AI审核请求数据
                     for (LifeUserViolation violation : lifeUserViolations) {
@@ -118,11 +144,11 @@ public class AiCheckXxlJob {
                         Map<String, Object> requestBody = new HashMap<>();
 
                         // 设置投诉记录ID
-                        requestBody.put("complaint_id", violation.getId());
+                        requestBody.put("complaint_id", violation.getId().toString());
 
                         // 查询投诉类型字典信息
                         StoreDictionary storeDictionary = storeDictionaryMapper.selectOne(new LambdaQueryWrapper<StoreDictionary>()
-                                .eq(StoreDictionary::getTypeName, violation.getDictId()).eq(StoreDictionary::getTypeName, violation.getDictType()));
+                                .eq(StoreDictionary::getDictId, violation.getDictId()).eq(StoreDictionary::getTypeName, violation.getDictType()));
                         String complaint_type = "";
                         if (storeDictionary != null) {
                             // 设置投诉类型
@@ -138,20 +164,30 @@ public class AiCheckXxlJob {
                         SecondGoodsRecord secondGoodsRecord = secondGoodsRecordMapper.selectById(violation.getBusinessId());
                         if (secondGoodsRecord != null) {
                             // 设置被举报人信息
-                            requestBody.put("reported_user_id", secondGoodsRecord.getUserId());
+                            requestBody.put("reported_user_id", secondGoodsRecord.getUserId().toString());
                             requestBody.put("reported_user_type", "");
                             requestBody.put("reported_info", lifeUserMapper.selectById(secondGoodsRecord.getUserId()));
                             requestBody.put("product_name", secondGoodsRecord.getTitle());
                         }
                         // 设置商品相关信息
                         requestBody.put("product_info", secondGoodsRecord);
-                        requestBody.put("product_id", violation.getBusinessId());
+                        requestBody.put("product_id", violation.getGoodsId().toString());
 
                         // 设置投诉文本内容
                         requestBody.put("complaint_text", violation.getOtherReasonContent());
 
-                        // 设置证据图片数组(将逗号分隔的字符串转换为数组)
-                        requestBody.put("evidence_images", violation.getReportEvidenceImg() != null ? violation.getReportEvidenceImg().split(",") : new String[0]);
+                        LambdaQueryWrapper<StoreImg> wrapper = new LambdaQueryWrapper<>();
+                        wrapper.eq(StoreImg::getStoreId, violation.getId());
+                        wrapper.eq(StoreImg::getImgType, Constants.ImageType.SECOND_HAND_REPORT);
+                        List<StoreImg> imgList = storeImgMapper.selectList(wrapper);
+
+                        // 将 imgList 中的 ImgUrl 提取为 String[] 数组
+                        String[] imgUrls = imgList.stream()
+                                .map(StoreImg::getImgUrl)
+                                .toArray(String[]::new);
+
+                        // 设置证据图片数组
+                        requestBody.put("evidence_images", imgUrls);
 
                         HttpHeaders aiHeaders = new HttpHeaders();
                         aiHeaders.setContentType(MediaType.APPLICATION_JSON);
@@ -161,8 +197,28 @@ public class AiCheckXxlJob {
                         HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, aiHeaders);
                         ResponseEntity<String> response = null;
                         try {
-                            response = restTemplate.postForEntity("http://192.168.2.78:9000/ai/auto-review/api/v1/product_complaint_record/submit", request, String.class);
+                            response = restTemplate.postForEntity(goodsUrl, request, String.class);
                             log.info("AI自动审核结果:{}", response.getBody());
+                            if (response.getStatusCodeValue() != 200) {
+                                throw new RuntimeException("AI门店审核接口调用失败 http状态:" + response.getStatusCode());
+                            }
+                            if (StringUtils.isNotEmpty(response.getBody())) {
+                                com.alibaba.fastjson.JSONObject taskObject = com.alibaba.fastjson.JSONObject.parseObject(response.getBody());
+                                if (taskObject.getInteger("code") == 200) {
+                                    com.alibaba.fastjson.JSONObject data = taskObject.getJSONObject("data");
+                                    if (data != null) {
+                                        String taskId = data.getString("task_id");
+                                        violation.setAiTaskId(taskId);
+                                        lifeUserViolationMapper.updateById(violation);
+                                    }
+                                }
+                            }
+                        } catch (ResourceAccessException e) {
+                            if (e.getCause() instanceof SocketException) {
+                                log.error("AI自动审核请求网络异常,连接被中断: {}", e.getMessage());
+                            } else {
+                                log.error("AI自动审核请求资源访问异常", e);
+                            }
                         } catch (Exception e) {
                             log.error("AI自动审核请求异常", e);
                         }
@@ -176,6 +232,106 @@ public class AiCheckXxlJob {
         log.info("AI自动审核任务执行完成");
     }
 
+    @XxlJob("aiCheckJobHandlerResult")
+    public void aiCheckJobHandlerResult() {
+        log.info("登录Ai服务获取token..." + loginUrl);
+        MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
+        formData.add("username", userName);
+        formData.add("password", passWord);
+
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers);
+        ResponseEntity<String> postForEntity = null;
+        try {
+            log.info("请求Ai服务登录接口===================>");
+            postForEntity = restTemplate.postForEntity(loginUrl, requestEntity, String.class);
+        } catch (Exception e) {
+            log.error("请求AI服务登录接口失败", e);
+        }
+
+        if (postForEntity != null) {
+            if (postForEntity.getStatusCodeValue() == 200) {
+                log.info("请求Ai服务登录成功 postForEntity.getBody()\t" + postForEntity.getBody());
+                String responseBody = postForEntity.getBody();
+                JSONObject jsonObject = JSONObject.parseObject(responseBody);
+                JSONObject dataJson = jsonObject.getJSONObject("data");
+                String accessToken = dataJson.getString("access_token");
+
+                // 查询所有待处理的用户违规记录
+                List<LifeUserViolation> lifeUserViolations = lifeUserViolationMapper.selectList(new LambdaQueryWrapper<LifeUserViolation>()
+                        .eq(LifeUserViolation::getReportContextType, "4")
+                        .eq(LifeUserViolation::getProcessingStatus, "0"));
+
+                for (LifeUserViolation violation : lifeUserViolations) {
+                    // 初始化请求体Map
+                    Map<String, Object> requestBody = new HashMap<>();
+
+                    // 设置投诉记录ID
+                    requestBody.put("task_id", violation.getAiTaskId());
+                    HttpHeaders aiHeaders = new HttpHeaders();
+                    aiHeaders.setContentType(MediaType.APPLICATION_JSON);
+                    aiHeaders.set("Authorization", "Bearer " + accessToken);
+
+                    System.out.println(requestBody);
+                    HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, aiHeaders);
+                    ResponseEntity<String> response = null;
+                    try {
+                        response = restTemplate.postForEntity(goodsResultUrl, request, String.class);
+                        if (response.getStatusCodeValue() != 200) {
+                            throw new RuntimeException("AI门店审核接口调用失败 http状态:" + response.getStatusCode());
+                        }
+                        if (StringUtils.isNotEmpty(response.getBody())) {
+                            com.alibaba.fastjson.JSONObject taskObject = com.alibaba.fastjson.JSONObject.parseObject(response.getBody());
+                            if (taskObject.getInteger("code") == 200) {
+                                com.alibaba.fastjson.JSONObject data = taskObject.getJSONObject("data");
+                                if (data != null) {
+                                    boolean isValid = data.getBoolean("is_valid");
+                                    String processingStatus;
+                                    if (isValid) {
+                                         processingStatus = "1";
+                                    } else {
+                                        processingStatus = "2";
+                                    }
+                                    violation.setReportResult(data.getString("matched_type"));
+                                    violation.setProcessingStatus(processingStatus);
+                                    lifeUserViolationMapper.updateById(violation);
+
+                                    // 发送通知
+                                    LifeNotice lifeMessage = new LifeNotice();
+                                    LifeUser lifeUser = lifeUserMapper.selectById(violation.getReportingUserId());
+                                    lifeMessage.setReceiverId("user_" + lifeUser.getUserPhone());
+                                    String text = "您的举报用户结果为" + (isValid ? "违规" : "未违规");
+                                    com.alibaba.fastjson.JSONObject lifeMessagejson = new com.alibaba.fastjson.JSONObject();
+                                    lifeMessagejson.put("title", "平台已受理");
+                                    lifeMessagejson.put("message", text);
+                                    lifeMessage.setContext(lifeMessagejson.toJSONString());
+
+                                    lifeMessage.setTitle("举报通知");
+                                    lifeMessage.setBusinessId(violation.getId());
+                                    lifeMessage.setSenderId("system");
+                                    lifeMessage.setIsRead(0);
+                                    lifeMessage.setNoticeType(1);
+                                    lifeNoticeMapper.insert(lifeMessage);
+                                }
+                            }
+                        }
+                    } catch (ResourceAccessException e) {
+                        if (e.getCause() instanceof SocketException) {
+                            log.error("AI自动审核结果查询网络异常,连接被中断: {}", e.getMessage());
+                        } else {
+                            log.error("AI自动审核结果查询资源访问异常", e);
+                        }
+                    } catch (Exception e) {
+                        log.error("AI自动审核结果查询异常", e);
+                    }
+
+                }
+            }
+        }
+
+    }
+
     /**
      * 二手商品风控记录审核任务
      * <p>

+ 25 - 3
alien-job/src/main/java/shop/alien/job/second/AiUserViolationJob.java

@@ -18,8 +18,9 @@ import org.springframework.util.StringUtils;
 import org.springframework.web.client.RestTemplate;
 import shop.alien.entity.result.R;
 import shop.alien.entity.second.SecondGoods;
-import shop.alien.entity.store.LifeUserViolation;
-import shop.alien.entity.store.SecondAiTask;
+import shop.alien.entity.store.*;
+import shop.alien.mapper.LifeNoticeMapper;
+import shop.alien.mapper.LifeUserMapper;
 import shop.alien.mapper.LifeUserViolationMapper;
 
 import java.util.ArrayList;
@@ -33,6 +34,10 @@ public class AiUserViolationJob {
     private final RestTemplate restTemplate;
     private final LifeUserViolationMapper lifeUserViolationMapper;
 
+    private final LifeUserMapper lifeUserMapper;
+
+    private final LifeNoticeMapper lifeNoticeMapper;
+
     @Value("${third-party-user-name.base-url}")
     private String userName;
 
@@ -141,11 +146,28 @@ public class AiUserViolationJob {
                             aiTask.setProcessingStatus("1");
                             aiTask.setReportResult(dataJsonObj.getString("decision_reason"));
                         } else {
-                            aiTask.setProcessingStatus("0");
+                            aiTask.setProcessingStatus("2");
                             aiTask.setReportResult(dataJsonObj.getString("decision_reason"));
                         }
                     }
 
+                    // 发送通知
+                    LifeNotice lifeMessage = new LifeNotice();
+                    LifeUser lifeUser = lifeUserMapper.selectById(task.getReportingUserId());
+                    lifeMessage.setReceiverId("user_" + lifeUser.getUserPhone());
+                    String text = "您的举报用户结果为" + (aiTask.getProcessingStatus().equals("1") ? "违规" : "未违规");
+
+                    com.alibaba.fastjson.JSONObject lifeMessagejson = new com.alibaba.fastjson.JSONObject();
+                    lifeMessagejson.put("title", "平台已受理");
+                    lifeMessagejson.put("message", text);
+                    lifeMessage.setContext(lifeMessagejson.toJSONString());
+                    lifeMessage.setTitle("举报通知");
+                    lifeMessage.setBusinessId(task.getId());
+                    lifeMessage.setSenderId("system");
+                    lifeMessage.setIsRead(0);
+                    lifeMessage.setNoticeType(1);
+                    lifeNoticeMapper.insert(lifeMessage);
+
                     QueryWrapper<LifeUserViolation> queryWrapper = new QueryWrapper<>();
                     queryWrapper.eq("ai_task_id", taskId);
                     LifeUserViolation lifeUserViolation = lifeUserViolationMapper.selectOne(queryWrapper);

+ 13 - 167
alien-job/src/main/java/shop/alien/job/second/goodsCheckJob.java

@@ -1,190 +1,36 @@
 package shop.alien.job.second;
 
-import com.alibaba.fastjson2.JSONObject;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.xxl.job.core.handler.annotation.XxlJob;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.http.HttpEntity;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.http.client.ClientHttpRequestInterceptor;
 import org.springframework.stereotype.Component;
-import org.springframework.util.LinkedMultiValueMap;
-import org.springframework.util.MultiValueMap;
-import org.springframework.util.StringUtils;
-import org.springframework.web.client.RestTemplate;
 import shop.alien.entity.result.R;
-import shop.alien.entity.second.SecondGoods;
-import shop.alien.entity.store.SecondAiTask;
-import shop.alien.entity.store.StoreComment;
-import shop.alien.entity.store.StoreCommentAppeal;
 import shop.alien.job.feign.SecondGoodsFeign;
-import shop.alien.mapper.SecondAiTaskMapper;
-import shop.alien.mapper.second.SecondGoodsMapper;
-
-import javax.annotation.Resource;
-import java.util.ArrayList;
-import java.util.List;
 
+/**
+ * 商品审核定时任务
+ */
 @Slf4j
 @Component
 @RequiredArgsConstructor
 public class goodsCheckJob {
 
-    private final RestTemplate restTemplate;
-
-    private final SecondAiTaskMapper secondAiTaskMapper;
-    private final SecondGoodsMapper secondGoodsMapper;
-
     private final SecondGoodsFeign secondGoodsFeign;
 
-    private String loginUrl = "http://192.168.2.250:9000/ai/user-auth-core/api/v1/auth/login";
-
-    private String goodsCheckUrl = "http://192.168.2.250:9000/ai/auto-review/api/v1/audit_task/getResult";
-
-    @Value("${third-party-user-name.base-url}")
-    private String userName;
-
-    @Value("${third-party-pass-word.base-url}")
-    private String passWord;
-
+    /**
+     * 获取AI商品审核结果
+     * 通过Feign调用alien-second服务处理AI审核结果
+     */
     @XxlJob("getAiGoodsCheckResult")
     public R<String> getAiGoodsCheckResult() {
-        String accessToken = fetchAiServiceToken();
-        if (!StringUtils.hasText(accessToken)) {
-            return R.fail("调用差评申诉辅助系统 登录接口失败");
-        }
-        return getGoodsCheck(accessToken);
-    }
-
-
-    private String fetchAiServiceToken() {
-        log.info("登录Ai服务获取token...{}", loginUrl);
-        MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
-        formData.add("username", userName);
-        formData.add("password", passWord);
-
-        HttpHeaders headers = new HttpHeaders();
-        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
-        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers);
-
+        log.info("开始执行AI商品审核结果获取任务");
         try {
-            ResponseEntity<String> response = restTemplate.postForEntity(loginUrl, requestEntity, String.class);
-            if (response != null && response.getStatusCodeValue() == 200 && response.getBody() != null) {
-                JSONObject jsonObject = JSONObject.parseObject(response.getBody());
-                JSONObject dataJson = jsonObject.getJSONObject("data");
-                return dataJson != null ? dataJson.getString("access_token") : null;
-            }
-            log.error("请求差评申诉辅助系统 登录接口失败 http状态:{}", response != null ? response.getStatusCode() : null);
+            R<String> result = secondGoodsFeign.getAiGoodsCheckResult();
+            log.info("AI商品审核结果获取任务执行完成: {}", result.getData());
+            return result;
         } catch (Exception e) {
-            log.error("调用差评申诉辅助系统登录接口异常", e);
-        }
-        return null;
-    }
-
-
-    private R<String> getGoodsCheck(String accessToken) {
-
-
-        HttpHeaders analyzeHeaders = new HttpHeaders();
-        analyzeHeaders.setContentType(MediaType.APPLICATION_JSON);
-        analyzeHeaders.set("Authorization", "Bearer " + accessToken);
-        // 查询所有状态为处理中的申诉
-        List<SecondAiTask> pendingTasks = secondAiTaskMapper.selectList(
-                new QueryWrapper<SecondAiTask>()
-                        .eq("status", "PROCESSING")
-        );
-
-        // 循环调用查询结果接口
-        for (SecondAiTask task : pendingTasks) {
-            String completedUrl = buildCompletedUrl(task.getTaskId());
-
-            ResponseEntity<String> analyzeResp;
-
-            RestTemplate restTemplateWithAuth = new RestTemplate();
-            List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
-            interceptors.add((request, body, execution) -> {
-                request.getHeaders().set("Authorization", "Bearer " + accessToken);
-                return execution.execute(request, body);
-            });
-            restTemplateWithAuth.setInterceptors(interceptors);
-
-            ResponseEntity<String> response = null;
-
-            try {
-                analyzeResp = restTemplateWithAuth.getForEntity(completedUrl, String.class);
-
-                if (analyzeResp != null && analyzeResp.getStatusCodeValue() == 200) {
-                    String analyzeBody = analyzeResp.getBody();
-                    log.info("商品审核提交成功, 返回: {}", analyzeBody);
-
-                    JSONObject analyzeJson = JSONObject.parseObject(analyzeBody);
-                    JSONObject dataJsonObj = analyzeJson.getJSONObject("data");
-
-                    if (dataJsonObj == null) {
-                        log.error("商品审核返回数据为空");
-                        R.fail("商品审核返回数据为空");
-                        continue;
-                    }
-
-                    // 获取task_id用于后续查询
-                    String taskId = dataJsonObj.getString("task_id");
-                    if (taskId == null) {
-                        log.error("商品审核返回task_id为空");
-                        R.fail("商品审核返回task_id为空");
-                        continue;
-                    }
-
-                    SecondAiTask aiTask = new SecondAiTask();
-                    aiTask.setTaskId(taskId);
-                    if (dataJsonObj.getString("status").equals("pending")) {
-                        R.fail("审核未结束");
-                        continue;
-                    }
-
-                    if (dataJsonObj.getString("status").equals("done")) {
-                        aiTask.setStatus("SUCCESS");
-                    }
-
-                    aiTask.setResult(dataJsonObj.toJSONString());
-
-                    QueryWrapper<SecondGoods> queryWrapper = new QueryWrapper<>();
-                    queryWrapper.eq("ai_task_id", taskId);
-                    SecondGoods goods = secondGoodsMapper.selectOne(queryWrapper);
-                    if (goods == null) {
-                        log.error("商品不存在");
-                        R.fail("商品不存在");
-                        continue;
-                    }
-                    secondGoodsFeign.approveAndListGoods(goods);
-
-                } else {
-                    if (analyzeResp != null) {
-                        log.error("调用商品审核接口失败, http状态: {}", analyzeResp.getStatusCode());
-                        R.fail("调用商品审核接口失败, http状态: " + analyzeResp.getStatusCode());
-                    }
-                }
-            } catch (Exception e) {
-                log.error("调用差评申述查询结果接口异常", e);
-            }
-        }
-        return R.success("调用商品审核结果接口完成");
-    }
-
-
-    private String buildCompletedUrl(String recordId) {
-        String baseUrl = goodsCheckUrl;
-        if (!StringUtils.hasText(baseUrl)) {
-            throw new IllegalStateException("差评申述分析接口地址未配置");
-        }
-        if (baseUrl.endsWith("/")) {
-            baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
+            log.error("AI商品审核结果获取任务执行异常", e);
+            return R.fail("任务执行异常: " + e.getMessage());
         }
-        // 构建新的URL格式: /api/v1/audit_task/getResult?task_id={recordId}
-        return baseUrl + "?task_id=" + recordId;
     }
 }

+ 0 - 1
alien-job/src/main/java/shop/alien/job/store/AiTagJob.java

@@ -1022,5 +1022,4 @@ public class AiTagJob {
             this.end_time = end_time;
         }
     }
-
 }

+ 18 - 2
alien-job/src/main/java/shop/alien/job/store/BadReviewAppealJob.java

@@ -2,6 +2,7 @@ package shop.alien.job.store;
 
 import com.alibaba.fastjson2.JSON;
 import com.alibaba.fastjson2.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.xxl.job.core.context.XxlJobHelper;
 import com.xxl.job.core.handler.annotation.XxlJob;
 import lombok.RequiredArgsConstructor;
@@ -18,11 +19,12 @@ import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.util.MultiValueMap;
 import org.springframework.util.StringUtils;
 import org.springframework.web.client.RestTemplate;
-import shop.alien.entity.store.StoreComment;
-import shop.alien.entity.store.StoreCommentAppeal;
+import shop.alien.entity.store.*;
 import shop.alien.entity.result.R;
+import shop.alien.mapper.LifeNoticeMapper;
 import shop.alien.mapper.StoreCommentAppealMapper;
 import shop.alien.mapper.StoreCommentMapper;
+import shop.alien.mapper.StoreUserMapper;
 
 import java.net.URI;
 import java.net.URISyntaxException;
@@ -48,6 +50,8 @@ public class BadReviewAppealJob {
     private final StoreCommentAppealMapper storeCommentAppealMapper;
 
     private final StoreCommentMapper storeCommentMapper;
+    private final StoreUserMapper storeUserMapper;
+    private final LifeNoticeMapper lifeNoticeMapper;
 
 //    @Value("${third-party-login.base-url}")
 //    private String loginUrl;
@@ -172,6 +176,18 @@ public class BadReviewAppealJob {
                     storeCommentAppealMapper.updateByRecordId(appeal.getRecordId(),
                             sCommentAppeal.getAppealStatus(),
                             sCommentAppeal.getFinalResult());
+
+                    // 发送通知
+                    LifeNotice lifeMessage = new LifeNotice();
+                    StoreUser storeUser = storeUserMapper.selectOne(new QueryWrapper<StoreUser>().eq("store_id", appeal.getStoreId()));
+                    lifeMessage.setReceiverId("store_" + storeUser.getPhone());
+                    String text = "您的评论申诉结果为" + sCommentAppeal.getFinalResult();
+                    lifeMessage.setContext(text);
+                    lifeMessage.setSenderId("system");
+                    lifeMessage.setIsRead(0);
+                    lifeMessage.setNoticeType(1);
+                    lifeNoticeMapper.insert(lifeMessage);
+
                 } else {
                     if (analyzeResp != null) {
                         log.error("调用差评申述置信度分析接口失败, http状态: {}", analyzeResp.getStatusCode());

+ 30 - 7
alien-job/src/main/java/shop/alien/job/store/LifeUserOrderJob.java

@@ -18,6 +18,7 @@ import shop.alien.util.common.UniqueRandomNumGenerator;
 import shop.alien.util.common.constant.CouponTypeEnum;
 import shop.alien.util.common.constant.DiscountCouponEnum;
 import shop.alien.util.common.constant.OrderStatusEnum;
+import shop.alien.util.common.constant.PaymentEnum;
 
 import java.math.BigDecimal;
 import java.text.ParseException;
@@ -212,15 +213,37 @@ public class LifeUserOrderJob {
                         // 统计退款金额
                         BigDecimal totalRefundAmount = refundList.stream().map(x -> x.getPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
                         // 判断本次是否是全退 执行退款
-                        String refundResult = null;
-                        if (refundList.size() == orderCouponMiddleList.size()) {
-                            // 全退
-                            refundResult = alienStoreFeign.processRefund(order.getOrderNo(), totalRefundAmount.toString(), "过期自动退","");
+                        String refundResult = "";
+                        String partialRefundCode = "";
+                        if (refundList.size() != orderCouponMiddleList.size()) {
+                            partialRefundCode = UniqueRandomNumGenerator.generateUniqueCode(12);
+                        }
+                        String payMethod = order.getPayMethod();
+                        String payType = "";
+                        Map<String, String> params = new HashMap<>();
+                        if("支付宝支付".equals(payMethod)) {
+                            payType = PaymentEnum.ALIPAY.getType();
+                            params.put("payType", payType);
+                            params.put("outTradeNo", order.getOrderNo());
+                            params.put("refundAmount", totalRefundAmount.toString());
+                            params.put("refundReason", "过期自动退");
+                            params.put("partialRefundCode",partialRefundCode);
                         } else {
-                            // TODO 本次部分退款
-                            String partialRefundCode = UniqueRandomNumGenerator.generateUniqueCode(12);
-                            refundResult = alienStoreFeign.processRefund(order.getOrderNo(), totalRefundAmount.toString(), "过期自动退",partialRefundCode);
+                            payType = PaymentEnum.WECHAT_PAY.getType();
+                            params.put("payType", payType);
+                            params.put("outTradeNo", order.getOrderNo());
+                            params.put("reason", "过期自动退");
+                            params.put("refundAmount", String.valueOf(totalRefundAmount.multiply(new BigDecimal(100)).longValue()));
+                            params.put("totalAmount", String.valueOf(new BigDecimal(order.getFinalPrice()).multiply(new BigDecimal(100)).longValue()));
+                        }
+                        // 调用支付策略
+                        try {
+                            refundResult = alienStoreFeign.refunds(params).getData().toString();
+                        } catch (Exception e) {
+                            log.error(String.format("LifeUserOrderJob requestRefund error, payType: %s, params: %s, error: %s", payType, params, e.getMessage()));
                         }
+
+
                         if ("调用成功".equals(refundResult)) {
                             //  1.更新中间表状态
                             int updateNum = orderCouponMiddleMapper.update(null, new LambdaUpdateWrapper<OrderCouponMiddle>()

+ 1 - 0
alien-lawyer/src/main/java/shop/alien/lawyer/controller/LawyerUserController.java

@@ -37,6 +37,7 @@ public class LawyerUserController {
     @ApiOperationSupport(order = 1)
     @PostMapping("/addLawyerUser")
     public R<LawyerUser> addLawyerUser(@RequestBody LawyerUser lawyerUser) {
+
         log.info("LawyerUserController.addLawyerUser?lawyerUser={}", lawyerUser);
         return lawyerUserService.addLawyerUser(lawyerUser);
     }

+ 1 - 0
alien-lawyer/src/main/java/shop/alien/lawyer/controller/OrderReviewController.java

@@ -275,5 +275,6 @@ public class OrderReviewController {
         }
         return orderReviewService.getOrderEvaluation(orderId);
     }
+
 }
 

+ 1 - 0
alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/LawyerClientConsultationOrderServiceImpl.java

@@ -1031,6 +1031,7 @@ public class LawyerClientConsultationOrderServiceImpl extends ServiceImpl<Lawyer
                     .set(LawyerConsultationOrder::getOrderStatus, LawyerStatusEnum.REFUNDED.getStatus())
                     .set(LawyerConsultationOrder::getApplyRefundStatus, REFUND_STATUS_AGREED)
                     .set(LawyerConsultationOrder::getApplyRefundProcessTime, processTime)
+                    .set(LawyerConsultationOrder::getApplyRefundTime, processTime)
                     .set(LawyerConsultationOrder::getUpdatedTime, processTime);
 
             int updateCount = consultationOrderMapper.update(null, updateWrapper);

+ 1 - 1
alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/LawyerConsultationOrderServiceImpl.java

@@ -1715,7 +1715,7 @@ public class LawyerConsultationOrderServiceImpl extends ServiceImpl<LawyerConsul
             LifeNotice lifeNotice = new LifeNotice();
             lifeNotice.setSenderId(SYSTEM_SENDER_ID);
             lifeNotice.setBusinessId(order.getId());
-            lifeNotice.setTitle("退款申请通知");
+            lifeNotice.setTitle("申请退款通知");
 
             // 获取申请人接收ID
             String receiverId = getClientReceiverId(clientUserId);

+ 4 - 1
alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/OrderExpirationServiceImpl.java

@@ -29,6 +29,7 @@ import shop.alien.util.common.constant.PaymentEnum;
 import javax.annotation.PostConstruct;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -176,7 +177,7 @@ public class OrderExpirationServiceImpl implements OrderExpirationService, Comma
                     //退款到账通知
                     LifeNotice lifeNotice2 = buildUserLifeNotice(order, "退款到账通知", "您的编号为" + orderNo + "的订单,订单金额已原路返还至您的支付渠道,请查收。");
                     WebSocketVo webSocketVo2 = buildWebSocketVo(lifeNotice2);
-                    lifeNotice2.setCreatedTime(DateUtils.calcMinute(lifeNotice2.getCreatedTime(), 2));
+                    lifeNotice2.setCreatedTime(DateUtils.calcMinute(new Date(), 2));
 
                     lifeNoticeMapper.insert(lifeNotice2);
                     webSocketProcess.sendMessage(lifeNotice2.getReceiverId(), JSONObject.from(webSocketVo2).toJSONString());
@@ -186,6 +187,7 @@ public class OrderExpirationServiceImpl implements OrderExpirationService, Comma
                     LawyerConsultationOrder update = new LawyerConsultationOrder();
                     update.setId(order.getId());
                     update.setOrderStatus(5);
+                    update.setApplyRefundTime(new Date());
                     orderMapper.updateById( update);
                 }
             }
@@ -233,6 +235,7 @@ public class OrderExpirationServiceImpl implements OrderExpirationService, Comma
                     update.setId(order.getId());
                     update.setOrderStatus(5);
                     update.setApplyRefundStatus("4");
+                    update.setApplyRefundTime(new Date());
                     orderMapper.updateById(update);
                 }
             }

+ 2 - 2
alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/OrderReviewServiceImpl.java

@@ -151,7 +151,7 @@ public class OrderReviewServiceImpl extends ServiceImpl<OrderReviewMapper, Order
         try {
             // 计算平均评分(1-5星)
             Double averageRating = orderReviewMapper.getAverageRatingByLawyerUserId(lawyerUserId);
-            
+
             Double serviceScore;
             if (averageRating != null) {
                 // 转换为0-5分,保留一位小数(直接截取,不四舍五入)
@@ -389,7 +389,7 @@ public class OrderReviewServiceImpl extends ServiceImpl<OrderReviewMapper, Order
                         log.warn("管理员删除评价时,更新订单申诉状态失败,评价ID={}, 订单ID={}", reviewId, review.getOrderId());
                     }
                 } catch (Exception e) {
-                    log.error("管理员删除评价时,更新订单申诉状态异常,评价ID={}, 订单ID={}, 错误信息={}", 
+                    log.error("管理员删除评价时,更新订单申诉状态异常,评价ID={}, 订单ID={}, 错误信息={}",
                             reviewId, review.getOrderId(), e.getMessage(), e);
                     // 更新订单申诉状态失败不影响删除评价的操作
                 }

+ 16 - 0
alien-lawyer/src/main/java/shop/alien/lawyer/util/AliSms.java

@@ -9,10 +9,13 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
+import shop.alien.entity.store.StoreVerificationCode;
+import shop.alien.mapper.StoreVerificationCodeMapper;
 import shop.alien.util.common.RandomCreateUtil;
 import shop.alien.lawyer.config.BaseRedisService;
 
 import java.util.Arrays;
+import java.util.Date;
 import java.util.List;
 
 /**
@@ -28,6 +31,8 @@ import java.util.List;
 public class AliSms {
     private final BaseRedisService baseRedisService;
 
+    private final StoreVerificationCodeMapper storeVerificationCodeMapper;
+
     @Value("${ali.sms.accessKeyId}")
     private String accessKeyId;
 
@@ -88,6 +93,17 @@ public class AliSms {
             }
             // 验证码发送成功,将验证码保存到redis中 设置60秒过期
             baseRedisService.setString("verification_lawyer_"+phone,code.toString(),Long.valueOf(300));
+            // 永久存储验证码
+            StoreVerificationCode entity = new StoreVerificationCode();
+            entity.setAppType(2);
+            entity.setBusinessType(7);
+            entity.setPhone(phone);
+            entity.setCode(String.valueOf(code));
+            Date now = new Date();
+            entity.setCreatedTime(now);
+            entity.setUpdatedTime(now);
+            entity.setDeleteFlag(0);
+            storeVerificationCodeMapper.insert(entity);
             return code;
         } catch (Exception e) {
             log.error("AliSmsConfig.sendSms ERROR Msg={}", e.getMessage());

+ 40 - 0
alien-second/src/main/java/shop/alien/second/controller/SecondGoodsController.java

@@ -12,6 +12,7 @@ import shop.alien.entity.result.R;
 import shop.alien.entity.second.SecondGoods;
 import shop.alien.entity.second.vo.SecondGoodsVo;
 import shop.alien.mapper.second.SecondGoodsAuditMapper;
+import shop.alien.second.service.SecondGoodsAuditService;
 import shop.alien.second.service.SecondGoodsService;
 import shop.alien.second.service.VideoModerationService;
 import shop.alien.util.common.JwtUtil;
@@ -56,6 +57,9 @@ public class SecondGoodsController {
     // 注入图片审核工具
     private final ImageModerationUtil imageModerationUtil;
 
+    // 注入二手商品审核服务
+    private final SecondGoodsAuditService secondGoodsAuditService;
+
     /**
      * 根据ID获取二手商品
      */
@@ -318,4 +322,40 @@ public class SecondGoodsController {
             return false;
         }
     }
+
+    /**
+     * 获取AI商品审核结果
+     * 查询所有状态为处理中的AI审核任务,并更新审核结果
+     * @return 处理结果
+     */
+    @ApiOperation("获取AI商品审核结果")
+    @GetMapping("/getAiGoodsCheckResult")
+    public R<String> getAiGoodsCheckResult() {
+        log.info("SecondGoodsController.getAiGoodsCheckResult");
+        try {
+            String result = secondGoodsAuditService.getAiGoodsCheckResult();
+            return R.data(result, "获取AI审核结果完成");
+        } catch (Exception e) {
+            log.error("获取AI商品审核结果异常", e);
+            return R.fail("获取AI商品审核结果异常: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 处理视频审核结果
+     * 查询所有待处理的视频审核任务,拉取审核结果并更新商品状态
+     * @return 处理结果
+     */
+    @ApiOperation("处理所有待处理的视频审核任务")
+    @GetMapping("/processVideoModerationResult")
+    public R<String> processVideoModerationResult() {
+        log.info("SecondGoodsController.processVideoModerationResult");
+        try {
+            String result = videoModerationService.processAllPendingVideoTasks();
+            return R.data(result, "视频审核结果处理完成");
+        } catch (Exception e) {
+            log.error("处理视频审核结果异常", e);
+            return R.fail("处理视频审核结果异常: " + e.getMessage());
+        }
+    }
 }

+ 13 - 1
alien-second/src/main/java/shop/alien/second/service/SecondGoodsAuditService.java

@@ -1,6 +1,5 @@
 package shop.alien.second.service;
 
-import org.springframework.stereotype.Service;
 import shop.alien.entity.SecondVideoTask;
 import shop.alien.entity.second.SecondGoods;
 import shop.alien.entity.second.vo.SecondGoodsVo;
@@ -82,5 +81,18 @@ public interface SecondGoodsAuditService {
     boolean isVideoUrl(String url);
 
     boolean performSecondRoundReview(SecondGoods goods, SecondGoodsVo goodsDTO);
+
+    /**
+     * 获取AI商品审核结果
+     * 查询所有状态为处理中的AI审核任务,并更新审核结果
+     * @return 处理结果
+     */
+    String getAiGoodsCheckResult();
+
+    /**
+     * 商品审核通过后的上架处理(包含风控检查)
+     * @param goods 商品信息
+     */
+    void handleGoodsApprovalSuccess(SecondGoods goods);
 }
 

+ 6 - 0
alien-second/src/main/java/shop/alien/second/service/SecondGoodsService.java

@@ -217,4 +217,10 @@ public interface SecondGoodsService extends IService<SecondGoods> {
      * @return 是否处理成功
      */
     boolean batchShelveGoodsByRiskControlRecord(Integer ruleType, String businessId);
+
+    /**
+     * 执行商品发布风控检查
+     * @param goods 商品信息
+     */
+    void performPublishRiskCheck(SecondGoods goods);
 }

+ 6 - 0
alien-second/src/main/java/shop/alien/second/service/VideoModerationService.java

@@ -32,4 +32,10 @@ public interface VideoModerationService  extends IService<SecondVideoTask> {
      * @return 视频审核任务
      */
     SecondVideoTask getTaskByTaskId(String taskId);
+
+    /**
+     * 处理所有待处理的视频审核任务
+     * @return 处理结果
+     */
+    String processAllPendingVideoTasks();
 }

+ 218 - 1
alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsAuditServiceImpl.java

@@ -8,7 +8,9 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.google.common.collect.Lists;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.util.StringUtils;
 import shop.alien.entity.SecondVideoTask;
@@ -105,6 +107,12 @@ public class SecondGoodsAuditServiceImpl implements SecondGoodsAuditService {
 
     private final AiTaskUtils aiTaskUtil;
 
+    @Lazy
+    @Autowired
+    private SecondGoodsService secondGoodsService;
+
+
+
     /**
      * 执行内容审核
      * @param goodsDTO 商品信息
@@ -178,7 +186,8 @@ public class SecondGoodsAuditServiceImpl implements SecondGoodsAuditService {
             }
 
             // 创建AI任务
-            String taskId = aiTaskUtil.createTask(accessToken, goods.getDescription(), goodsDTO.getImgUrl());
+            String test = goodsDTO.getDescription() + goodsDTO.getTitle() + goods.getLabel() + goods.getTopic();
+            String taskId = aiTaskUtil.createTask(accessToken, test, goodsDTO.getImgUrl());
             if (StringUtils.isEmpty(taskId)) {
                 log.warn("Failed to create AI task for second round review, goods id={}", goods.getId());
                 return false;
@@ -406,6 +415,43 @@ public class SecondGoodsAuditServiceImpl implements SecondGoodsAuditService {
                 operationName = "首次发布";
             }
             operationRecordService.recordGoodsOperation(goods, operationName);
+
+            // 审核通过
+//                goods.setGoodsStatus(SecondGoodsStatusEnum.LISTED.getCode());
+//                goods.setFailedReason("");
+//                goods.setReleaseTime(new Date());
+//                updateById(goods);
+//
+//                // 更新审核记录
+//                createGoodsAudit(goods, "", Constants.AuditStatus.PASSED);
+//
+//                // 发送审核成功消息
+//                sendMessage(goods);
+//                // 审核成功,记录操作历史
+//                // 审核成功,记录操作历史
+//                String operationName = "";
+//                QueryWrapper<SecondGoodsRecord> queryRecordWrapper = new QueryWrapper<>();
+//                queryRecordWrapper.eq("goods_id", goods.getId());
+//                log.info("查询操作记录开始 goods_id: {}", goods.getId());
+//                List<SecondGoodsRecord> recordList = secondGoodsRecordMapper.selectList(queryRecordWrapper);
+//                log.info("查询操作记录结束 recordList: {}", recordList);
+//                if (CollectionUtil.isNotEmpty(recordList)){
+//                    operationName = "重新发布";
+//                }else {
+//                    operationName = "首次发布";
+//                }
+//                recordGoodsOperation(goods, operationName);
+//
+//                // 检查用户是否在24小时内发布同类商品超过阈值
+//                if (!checkUserPublishSameCategoryLimit(goods)) {
+//                    log.warn("用户 {} 在24小时内发布同类商品次数超过限制", goods.getUserId());
+//                }
+//
+//                // 检查用户是否在24小时内发布商品超过阈值
+//                if (!checkUserPublishLimit(goods)) {
+//                    log.warn("用户 {} 在24小时内发布商品次数超过限制", goods.getUserId());
+//
+//                }
         } catch (Exception e) {
             log.error("商品上架过程中发生异常,执行回滚", e);
             // 如果通知已发送但后续操作失败,需要补偿
@@ -542,5 +588,176 @@ public class SecondGoodsAuditServiceImpl implements SecondGoodsAuditService {
         
         return reasonBuilder.toString();
     }
+
+    /**
+     * 获取AI商品审核结果
+     * 查询所有状态为处理中的AI审核任务,并更新审核结果
+     * @return 处理结果
+     */
+    @Override
+    public String getAiGoodsCheckResult() {
+        // 获取AI服务Token
+        String accessToken = aiTaskUtil.getAccessToken();
+        if (!StringUtils.hasText(accessToken)) {
+            log.error("调用AI服务登录接口失败,无法获取token");
+            return "调用AI服务登录接口失败";
+        }
+
+        // 查询所有状态为处理中的任务
+        List<SecondAiTask> pendingTasks = secondAiTaskMapper.selectList(
+                new QueryWrapper<SecondAiTask>().eq("status", "PROCESSING")
+        );
+
+        if (CollectionUtil.isEmpty(pendingTasks)) {
+            log.info("没有处理中的AI审核任务");
+            return "没有处理中的AI审核任务";
+        }
+
+        int passCount = 0;
+        int rejectCount = 0;
+        int pendingCount = 0;
+        int failCount = 0;
+
+        for (SecondAiTask task : pendingTasks) {
+            String result = processAiTaskResult(task, accessToken);
+            switch (result) {
+                case "success": passCount++; break;
+                case "reject": rejectCount++; break;
+                case "pending": pendingCount++; break;
+                default: failCount++;
+            }
+        }
+
+        return String.format("AI审核结果处理完成,通过:%d,拒绝:%d,处理中:%d,异常:%d", passCount, rejectCount, pendingCount, failCount);
+    }
+
+    /**
+     * 处理单个AI任务结果
+     * @param task AI任务
+     * @param accessToken 访问令牌
+     * @return success-审核通过, reject-审核拒绝, pending-处理中, fail-处理失败
+     */
+    private String processAiTaskResult(SecondAiTask task, String accessToken) {
+        String resultUrl = "http://192.168.2.250:9000/ai/auto-review/api/v1/audit_task/getResult?task_id=" + task.getTaskId();
+        try {
+            org.springframework.http.HttpHeaders headers = new org.springframework.http.HttpHeaders();
+            headers.set("Authorization", "Bearer " + accessToken);
+
+            org.springframework.web.client.RestTemplate restTemplate = new org.springframework.web.client.RestTemplate();
+            org.springframework.http.ResponseEntity<String> response = restTemplate.exchange(
+                    resultUrl, org.springframework.http.HttpMethod.GET,
+                    new org.springframework.http.HttpEntity<>(headers), String.class);
+
+            if (response.getStatusCodeValue() != 200 || response.getBody() == null) {
+                log.error("调用AI审核结果接口失败,taskId: {}, http状态: {}", task.getTaskId(), response.getStatusCode());
+                return "fail";
+            }
+
+            JSONObject dataJson = JSONObject.parseObject(response.getBody()).getJSONObject("data");
+            if (dataJson == null) {
+                log.error("AI审核返回数据为空,taskId: {}", task.getTaskId());
+                return "fail";
+            }
+
+            String status = dataJson.getString("status");
+            // 任务仍在处理中
+            if ("pending".equals(status)) {
+                return "pending";
+            }
+
+            // 任务已完成
+            if ("done".equals(status)) {
+                // 更新任务状态和结果
+                task.setStatus("SUCCESS");
+                task.setResult(dataJson.toJSONString());
+                task.setUpdateTime(new Date());
+                secondAiTaskMapper.updateById(task);
+
+                // 查询关联商品
+                SecondGoods goods = secondGoodsMapper.selectOne(
+                        new QueryWrapper<SecondGoods>().eq("ai_task_id", task.getTaskId()));
+                if (goods == null) {
+                    log.error("商品不存在,taskId: {}", task.getTaskId());
+                    return "fail";
+                }
+
+                String result = dataJson.getString("result");
+                if ("pass".equals(result)) {
+                    // 审核通过,上架商品
+                    log.info("AI审核通过,商品ID: {}, taskId: {}", goods.getId(), task.getTaskId());
+                    handleGoodsApprovalSuccess(goods);
+                    return "success";
+                } else if ("reject".equals(result) || "suspect".equals(result)) {
+                    // 审核拒绝,处理失败流程
+                    String reason = dataJson.getString("reason");
+                    String violation = dataJson.getString("violation");
+                    String ruleHit = dataJson.getString("rule_hit");
+
+                    // 构建失败原因
+                    StringBuilder failReason = new StringBuilder("AI审核不通过");
+                    if (StringUtils.hasText(reason)) {
+                        failReason.append(":").append(reason);
+                    }
+                    if (StringUtils.hasText(violation)) {
+                        failReason.append(",违规类型:").append(violation);
+                    }
+                    if (StringUtils.hasText(ruleHit)) {
+                        failReason.append(",命中规则:").append(ruleHit);
+                    }
+
+                    log.info("AI审核拒绝,商品ID: {}, taskId: {}, 原因: {}", goods.getId(), task.getTaskId(), failReason);
+
+                    // 更新商品状态为审核失败
+                    goods.setGoodsStatus(SecondGoodsStatusEnum.REVIEW_FAILED.getCode());
+                    goods.setFailedReason(failReason.toString());
+                    secondGoodsMapper.updateById(goods);
+
+                    // 创建审核失败记录
+                    createGoodsAudit(goods, failReason.toString(), Constants.AuditStatus.FAILED);
+
+                    // 记录操作历史
+                    operationRecordService.recordGoodsOperation(goods, "AI审核失败");
+
+                    // 发送审核失败消息通知
+                    notificationService.sendFailedMsg(goods);
+
+                    return "reject";
+                }
+            }
+            return "fail";
+        } catch (Exception e) {
+            log.error("处理AI审核任务结果异常,taskId: {}", task.getTaskId(), e);
+            return "fail";
+        }
+    }
+
+    /**
+     * 商品审核通过后的上架处理(包含风控检查)
+     * @param goods 商品信息
+     */
+    @Override
+    public void handleGoodsApprovalSuccess(SecondGoods goods) {
+        // 审核通过,设置上架状态
+        goods.setGoodsStatus(SecondGoodsStatusEnum.LISTED.getCode());
+        goods.setFailedReason("");
+        goods.setReleaseTime(new Date());
+        secondGoodsMapper.updateById(goods);
+
+        // 更新审核记录
+        createGoodsAudit(goods, "", Constants.AuditStatus.PASSED);
+
+        // 发送审核成功消息
+        notificationService.sendMessage(goods);
+
+        // 记录操作历史
+        QueryWrapper<SecondGoodsRecord> queryRecordWrapper = new QueryWrapper<>();
+        queryRecordWrapper.eq("goods_id", goods.getId());
+        List<SecondGoodsRecord> recordList = secondGoodsRecordMapper.selectList(queryRecordWrapper);
+        String operationName = CollectionUtil.isNotEmpty(recordList) ? "重新发布" : "首次发布";
+        operationRecordService.recordGoodsOperation(goods, operationName);
+
+        // 执行风控检查
+        secondGoodsService.performPublishRiskCheck(goods);
+    }
 }
 

+ 18 - 0
alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsReportingServiceImpl.java

@@ -21,6 +21,7 @@ import shop.alien.mapper.*;
 import shop.alien.mapper.second.SecondGoodsRecordMapper;
 import shop.alien.second.feign.AlienStoreFeign;
 import shop.alien.second.service.SecondGoodsReportingService;
+import shop.alien.second.util.AiUserViolationUtils;
 import shop.alien.second.util.JsonUtils;
 import shop.alien.util.common.Constants;
 import shop.alien.util.common.EnumUtil;
@@ -63,6 +64,8 @@ public class SecondGoodsReportingServiceImpl implements SecondGoodsReportingServ
     @Autowired
     private final StoreImgMapper storeImgMapper;
 
+    private final AiUserViolationUtils aiUserViolationUtils;
+
     @Override
     public SecondReportingVo queryReportingDetail (Integer id) {
         SecondReportingVo secondReportingVo = new SecondReportingVo();
@@ -194,6 +197,21 @@ public class SecondGoodsReportingServiceImpl implements SecondGoodsReportingServ
             }
             int result = lifeUserViolationMapper.insert(lifeuserViolation);
             if (result > 0) {
+
+                if ("5".equals(lifeuserViolation.getReportContextType())) {
+                    // AI审核
+                    //登录获取token
+                    String token = aiUserViolationUtils.getAccessToken();
+                    //调用AI接口
+                    String taskId = aiUserViolationUtils.createTask(token, lifeuserViolation);
+                    if (org.springframework.util.StringUtils.isEmpty(taskId)) {
+                        log.warn("Failed to create AI task for second round review, lifeuserViolation id={}", lifeuserViolation.getId());
+                        return 0;
+                    }
+                    lifeuserViolation.setAiTaskId(taskId);
+                    lifeUserViolationMapper.updateById(lifeuserViolation);
+                }
+
                 if (lifeuserViolation.getReportContextType().equals("4") || lifeuserViolation.getReportContextType().equals("5")) {
                     String phoneId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getString("userType") + "_" + JwtUtil.getCurrentUserInfo().getString("phone");
                     // 举报通知

+ 79 - 41
alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsServiceImpl.java

@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollectionUtil;
 import com.alibaba.fastjson2.JSON;
 import com.alibaba.fastjson2.JSONArray;
 import com.alibaba.fastjson2.JSONObject;
+import com.alipay.api.domain.GoodsVO;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@@ -750,7 +751,22 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
         return true;
     }
 
+    /**
+     * 执行商品发布风控检查
+     * @param goods 商品信息
+     */
+    @Override
+    public void performPublishRiskCheck(SecondGoods goods) {
+        // 检查用户是否在24小时内发布同类商品超过阈值
+        if (!checkUserPublishSameCategoryLimit(goods)) {
+            log.warn("用户 {} 在24小时内发布同类商品次数超过限制", goods.getUserId());
+        }
 
+        // 检查用户是否在24小时内发布商品超过阈值
+        if (!checkUserPublishLimit(goods)) {
+            log.warn("用户 {} 在24小时内发布商品次数超过限制", goods.getUserId());
+        }
+    }
 
     /**
      * 执行内容审核
@@ -777,6 +793,7 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
             recordGoodsOperation(goods,"文本审核失败");
             return;
         }
+
         // 视频审核
         List<String> taskIds = performVideoReviews(goods, goodsDTO);
 
@@ -792,10 +809,16 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
 //            recordGoodsOperation(goods);
             return;
         }
+
+        List<String> videoUrls = extractVideoUrls(goodsDTO.getImgUrl());
+        if (videoUrls.isEmpty()) {
+            // ai 审核
+            secondGoodsAuditService.performSecondRoundReview(goods, goodsDTO);
+            return;
+        }
+
         // 审核通过后上架商品
-//        approveAndListGoods(goods);
-        // 开始第二轮审核
-        boolean b = secondGoodsAuditService.performSecondRoundReview(goods, goodsDTO);
+        approveAndListGoods(goods);
 
         // 检查用户是否在24小时内发布同类商品超过阈值
         if (!checkUserPublishSameCategoryLimit(goods)) {
@@ -1709,51 +1732,66 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
             
             // 根据审核结果更新商品状态
             if ("none".equals(task.getRiskLevel())) {
-                // 审核通过
-                goods.setGoodsStatus(SecondGoodsStatusEnum.LISTED.getCode());
-                goods.setFailedReason("");
-                goods.setReleaseTime(new Date());
-                updateById(goods);
-                
-                // 更新审核记录
-                createGoodsAudit(goods, "", Constants.AuditStatus.PASSED);
-                
-                // 发送审核成功消息
-                sendMessage(goods);
-                // 审核成功,记录操作历史
-                // 审核成功,记录操作历史
-                String operationName = "";
-                QueryWrapper<SecondGoodsRecord> queryRecordWrapper = new QueryWrapper<>();
-                queryRecordWrapper.eq("goods_id", goods.getId());
-                log.info("查询操作记录开始 goods_id: {}", goods.getId());
-                List<SecondGoodsRecord> recordList = secondGoodsRecordMapper.selectList(queryRecordWrapper);
-                log.info("查询操作记录结束 recordList: {}", recordList);
-                if (CollectionUtil.isNotEmpty(recordList)){
-                    operationName = "重新发布";
-                }else {
-                    operationName = "首次发布";
-                }
-                recordGoodsOperation(goods, operationName);
-
-                // 检查用户是否在24小时内发布同类商品超过阈值
-                if (!checkUserPublishSameCategoryLimit(goods)) {
-                    log.warn("用户 {} 在24小时内发布同类商品次数超过限制", goods.getUserId());
-                }
-
-                // 检查用户是否在24小时内发布商品超过阈值
-                if (!checkUserPublishLimit(goods)) {
-                    log.warn("用户 {} 在24小时内发布商品次数超过限制", goods.getUserId());
-
-                }
+                log.warn("视频审核通过,任务ID: {}", task.getTaskId());
+                SecondGoodsVo secondGoodsVo = new SecondGoodsVo();
+                BeanUtils.copyProperties(goods, secondGoodsVo);
+                QueryWrapper<StoreImg> imgQueryWrapper = new QueryWrapper<>();
+                imgQueryWrapper.eq("store_id", goods.getId());
+                imgQueryWrapper.eq("img_type", 18);
+                List<StoreImg> storeImgs = storeImgMapper.selectList(imgQueryWrapper);
+                List<String> imgUrls = storeImgs.stream()
+                        .map(StoreImg::getImgUrl)
+                        .filter(imgUrl -> StringUtils.hasText(imgUrl))
+                        .collect(Collectors.toList());
+                secondGoodsVo.setImgUrl(imgUrls);
+
+                secondGoodsAuditService.performSecondRoundReview(goods, secondGoodsVo);
+//
+//                // 审核通过
+//                goods.setGoodsStatus(SecondGoodsStatusEnum.LISTED.getCode());
+//                goods.setFailedReason("");
+//                goods.setReleaseTime(new Date());
+//                updateById(goods);
+//
+//                // 更新审核记录
+//                createGoodsAudit(goods, "", Constants.AuditStatus.PASSED);
+//
+//                // 发送审核成功消息
+//                sendMessage(goods);
+//                // 审核成功,记录操作历史
+//                // 审核成功,记录操作历史
+//                String operationName = "";
+//                QueryWrapper<SecondGoodsRecord> queryRecordWrapper = new QueryWrapper<>();
+//                queryRecordWrapper.eq("goods_id", goods.getId());
+//                log.info("查询操作记录开始 goods_id: {}", goods.getId());
+//                List<SecondGoodsRecord> recordList = secondGoodsRecordMapper.selectList(queryRecordWrapper);
+//                log.info("查询操作记录结束 recordList: {}", recordList);
+//                if (CollectionUtil.isNotEmpty(recordList)){
+//                    operationName = "重新发布";
+//                }else {
+//                    operationName = "首次发布";
+//                }
+//                recordGoodsOperation(goods, operationName);
+//
+//                // 检查用户是否在24小时内发布同类商品超过阈值
+//                if (!checkUserPublishSameCategoryLimit(goods)) {
+//                    log.warn("用户 {} 在24小时内发布同类商品次数超过限制", goods.getUserId());
+//                }
+//
+//                // 检查用户是否在24小时内发布商品超过阈值
+//                if (!checkUserPublishLimit(goods)) {
+//                    log.warn("用户 {} 在24小时内发布商品次数超过限制", goods.getUserId());
+//
+//                }
             } else {
                 // 审核不通过
                 goods.setGoodsStatus(SecondGoodsStatusEnum.REVIEW_FAILED.getCode());
-                
+
                 // 解析审核结果,生成具体的失败原因
                 String failedReason = parseVideoModerationFailureReason(task);
                 goods.setFailedReason(failedReason);
                 updateById(goods);
-                
+
                 // 更新审核记录
                 createGoodsAudit(goods, failedReason, Constants.AuditStatus.FAILED);
 

+ 72 - 1
alien-second/src/main/java/shop/alien/second/service/impl/VideoModerationServiceImpl.java

@@ -6,13 +6,17 @@ import com.aliyun.green20220302.models.VideoModerationResultResponse;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import shop.alien.entity.SecondVideoTask;
 import shop.alien.mapper.system.SecondVideoTaskMapper;
+import shop.alien.second.service.SecondGoodsService;
 import shop.alien.second.service.VideoModerationService;
 import shop.alien.util.common.safe.video.VideoModerationUtil;
 
 import java.util.Date;
+import java.util.List;
 import java.util.UUID;
 
 /**
@@ -34,6 +38,13 @@ public class VideoModerationServiceImpl extends ServiceImpl<SecondVideoTaskMappe
     private final SecondVideoTaskMapper videoModerationTaskMapper;
 
     /**
+     * 二手商品服务(使用@Lazy避免循环依赖)
+     */
+    @Lazy
+    @Autowired
+    private SecondGoodsService secondGoodsService;
+
+    /**
      * 提交视频审核任务
      *
      * @param videoUrl 视频URL
@@ -178,7 +189,7 @@ public class VideoModerationServiceImpl extends ServiceImpl<SecondVideoTaskMappe
                     return false;
                 } else {
                     // 审核失败
-                    videoModerationTaskMapper.updateTaskStatus(task.getTaskId(), "FAILED");
+                    videoModerationTaskMapper.updateTaskStatus(task.getTaskId(), "PROCESSING");
                     log.error("视频审核任务处理失败,任务ID: {},错误信息: {}", task.getTaskId(), response.getBody().getMessage());
                     return false;
                 }
@@ -201,4 +212,64 @@ public class VideoModerationServiceImpl extends ServiceImpl<SecondVideoTaskMappe
             return false;
         }
     }
+
+    /**
+     * 处理所有待处理的视频审核任务
+     * @return 处理结果
+     */
+    @Override
+    public String processAllPendingVideoTasks() {
+        try {
+            log.info("开始执行视频审核结果处理");
+
+            // 查询待处理的审核任务(状态为SUBMITTED或PROCESSING)
+            List<SecondVideoTask> pendingTasks = videoModerationTaskMapper.selectPendingTasks();
+
+            if (pendingTasks.isEmpty()) {
+                log.info("没有待处理的视频审核任务");
+                return "没有待处理的视频审核任务";
+            }
+
+            log.info("共找到 {} 个待处理的视频审核任务", pendingTasks.size());
+
+            int successCount = 0;
+            int processingCount = 0;
+            int failCount = 0;
+
+            for (SecondVideoTask task : pendingTasks) {
+                try {
+                    // 1. 拉取视频审核结果
+                    boolean success = processTask(task);
+                    if (success) {
+                        successCount++;
+                        // 2. 视频审核完成后,更新商品业务状态
+                        log.info("TaskId:开始处理商品状态 {}", task.getTaskId());
+                        SecondVideoTask updatedTask = videoModerationTaskMapper.selectByTaskId(task.getTaskId());
+                        if (updatedTask != null) {
+                            secondGoodsService.processVideoModerationResult(updatedTask);
+                        }
+                        log.info("TaskId:商品状态处理完成 {}", task.getTaskId());
+                    } else {
+                        // 检查任务状态判断是处理中还是失败
+                        SecondVideoTask updatedTask = videoModerationTaskMapper.selectByTaskId(task.getTaskId());
+                        if (updatedTask != null && "PROCESSING".equals(updatedTask.getStatus())) {
+                            processingCount++;
+                        } else {
+                            failCount++;
+                        }
+                    }
+                } catch (Exception e) {
+                    log.error("处理视频审核任务时发生异常,任务ID: {}", task.getTaskId(), e);
+                    failCount++;
+                }
+            }
+
+            String result = String.format("视频审核结果处理完成,成功:%d,处理中:%d,失败:%d", successCount, processingCount, failCount);
+            log.info(result);
+            return result;
+        } catch (Exception e) {
+            log.error("执行视频审核结果处理任务时发生异常", e);
+            return "执行异常: " + e.getMessage();
+        }
+    }
 }

+ 271 - 0
alien-second/src/main/java/shop/alien/second/util/AiUserViolationUtils.java

@@ -0,0 +1,271 @@
+package shop.alien.second.util;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.map.HashedMap;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.*;
+import org.springframework.stereotype.Component;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.util.StringUtils;
+import org.springframework.web.client.RestTemplate;
+import shop.alien.entity.result.R;
+import shop.alien.entity.store.LifeMessage;
+import shop.alien.entity.store.LifeUserViolation;
+import shop.alien.entity.store.vo.LifeUserVo;
+import shop.alien.mapper.LifeMessageMapper;
+import shop.alien.mapper.LifeUserMapper;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+@Component
+@RequiredArgsConstructor
+public class AiUserViolationUtils {
+
+    private final RestTemplate restTemplate;
+    private final LifeUserMapper lifeUserMapper;
+    private final LifeMessageMapper lifeMessageMapper;
+
+    //    @Value("${third-party-login.base-url:http://192.168.2.250:9000/ai/user-auth-core/api/v1/auth/login}")
+    private String loginUrl = "http://192.168.2.250:9000/ai/user-auth-core/api/v1/auth/login";
+
+    @Value("${third-party-user-name.base-url:UdUser}")
+    private String userName;
+
+    @Value("${third-party-pass-word.base-url:123456}")
+    private String passWord;
+
+    private String userComplaintRecordUrl = "http://192.168.2.250:9000/ai/auto-review/api/v1/user_complaint_record/submit";
+
+
+    /**
+     * 登录 AI 服务,获取 token
+     *
+     * @return accessToken
+     */
+    public String getAccessToken() {
+        log.info("登录Ai服务获取token...{}", loginUrl);
+        MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
+        formData.add("username", userName);
+        formData.add("password", passWord);
+
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers);
+
+        ResponseEntity<String> response;
+        try {
+            log.info("请求Ai服务登录接口===================>");
+            response = restTemplate.postForEntity(loginUrl, requestEntity, String.class);
+        } catch (Exception e) {
+            log.error("请求AI服务登录接口失败", e);
+            return null;
+        }
+
+        if (response != null && response.getStatusCode() == HttpStatus.OK) {
+            String body = response.getBody();
+            log.info("请求Ai服务登录成功 postForEntity.getBody()\t{}", body);
+            if (StringUtils.hasText(body)) {
+                JSONObject jsonObject = JSONObject.parseObject(body);
+                if (jsonObject != null) {
+                    JSONObject dataJson = jsonObject.getJSONObject("data");
+                    if (dataJson != null) {
+                        return dataJson.getString("access_token");
+                    }
+                }
+            }
+            log.warn("AI服务登录响应解析失败 body: {}", body);
+            return null;
+        }
+
+        log.error("请求AI服务 登录接口失败 http状态:{}", response != null ? response.getStatusCode() : null);
+        return null;
+    }
+
+
+    /**
+     * 调用AI服务创建任务
+     *
+     * @return accessToken
+     */
+    public String createTask(String accessToken, LifeUserViolation lifeuserViolation) {
+        log.info("创建Ai服务任务...{}", userComplaintRecordUrl);
+
+        HttpHeaders analyzeHeaders = new HttpHeaders();
+        analyzeHeaders.setContentType(MediaType.APPLICATION_JSON);
+        analyzeHeaders.set("Authorization", "Bearer " + accessToken);
+
+        Map<String, Object> analyzeRequest = new HashedMap<>();
+        // 对应参数
+        if (1 == lifeuserViolation.getDictId()){
+            analyzeRequest.put("complaint_type", "用户违规");
+        } else if (2 == lifeuserViolation.getDictId()){
+            analyzeRequest.put("complaint_type", "色情低俗");
+        } else if (3 == lifeuserViolation.getDictId()){
+            analyzeRequest.put("complaint_type", "违法违规");
+        } else if (4 == lifeuserViolation.getDictId()){
+            analyzeRequest.put("complaint_type", "谩骂嘲讽、煽动对立");
+        } else if (5 == lifeuserViolation.getDictId()){
+            analyzeRequest.put("complaint_type", "涉嫌诈骗");
+        } else if (6 == lifeuserViolation.getDictId()){
+            analyzeRequest.put("complaint_type", "人身攻击");
+        } else if (7 == lifeuserViolation.getDictId()){
+            analyzeRequest.put("complaint_type", "种族歧视");
+        } else if (8 == lifeuserViolation.getDictId()){
+            analyzeRequest.put("complaint_type", "政治敏感");
+        } else if (9 == lifeuserViolation.getDictId()){
+            analyzeRequest.put("complaint_type", "虚假、不实内容");
+        } else if (10 == lifeuserViolation.getDictId()){
+            analyzeRequest.put("complaint_type", "违反公德秩序");
+        } else if (11 == lifeuserViolation.getDictId()){
+            analyzeRequest.put("complaint_type", "危害人身安全");
+        } else if (12 == lifeuserViolation.getDictId()){
+            analyzeRequest.put("complaint_type", "网络暴力");
+        } else {
+            analyzeRequest.put("complaint_type", "其他");
+        }
+
+        analyzeRequest.put("reporter_user_id", lifeuserViolation.getReportingUserId());
+        analyzeRequest.put("reported_user_id", lifeuserViolation.getReportedUserId());
+
+        //举报人
+        String reporterUserId = lifeuserViolation.getReportingUserId();
+        //被举报人
+        String reportedUserId = lifeuserViolation.getReportedUserId();
+
+        //通过双方userId查询用户信息,查出用户电话,
+        QueryWrapper<LifeUserVo> reporterUserQueryWrapper = new QueryWrapper<>();
+        reporterUserQueryWrapper.eq("id", reporterUserId);
+        LifeUserVo reporterUserById = lifeUserMapper.getUserById(reporterUserQueryWrapper);
+        QueryWrapper<LifeUserVo> reportedUserQueryWrapper = new QueryWrapper<>();
+        reportedUserQueryWrapper.eq("id", reportedUserId);
+        LifeUserVo reportedUserById = lifeUserMapper.getUserById(reportedUserQueryWrapper);
+        // 用user_去拼接,查询life_message表,获取双方两天记录
+        String userReporterUserById = "user_" + reporterUserById.getUserPhone();
+        String userReportedUserById = "user_" + reportedUserById.getUserPhone();
+
+        //将双方两天记录拼接成text,传入analyzeRequest
+        // 获取双方最近的聊天记录
+        List<LifeMessage> chatMessages = getRecentChatMessages(userReporterUserById, userReportedUserById);
+
+        // 将聊天记录转换为文本格式
+        String text = convertMessagesToText(chatMessages);
+        analyzeRequest.put("conversation_context", StringUtils.hasText(text) ? text : "");
+
+//        analyzeRequest.put("text", StringUtils.hasText(text) ? text : "");
+//        analyzeRequest.put("img_urls", img_urls);
+
+        HttpEntity<Map<String, Object>> analyzeEntity = new HttpEntity<>(analyzeRequest, analyzeHeaders);
+
+        ResponseEntity<String> analyzeResp = null;
+        try {
+            analyzeResp = restTemplate.postForEntity(userComplaintRecordUrl, analyzeEntity, String.class);
+        } catch (org.springframework.web.client.HttpServerErrorException.ServiceUnavailable e) {
+            log.error("调用提交用户投诉审核任务接口返回503 Service Unavailable错误: {}", e.getResponseBodyAsString());
+            return  null;
+        } catch (Exception e) {
+            log.error("调用提交用户投诉审核任务接口异常", e);
+            return  null;
+        }
+
+        if (analyzeResp != null && analyzeResp.getStatusCodeValue() == 200) {
+            String analyzeBody = analyzeResp.getBody();
+            log.info("提交用户投诉审核任务提交成功, 返回: {}", analyzeBody);
+
+            JSONObject analyzeJson = JSONObject.parseObject(analyzeBody);
+            JSONObject dataJsonObj = analyzeJson.getJSONObject("data");
+
+            if (dataJsonObj == null) {
+                log.error("提交用户投诉审核任务返回数据为空");
+                R.fail("提交用户投诉审核任务返回数据为空");
+                return  null;
+            }
+
+            // 获取record_id用于后续查询
+            String taskId = dataJsonObj.getString("task_id");
+            if (taskId == null) {
+                log.error("提交用户投诉审核任务返回record_id为空");
+                R.fail("提交用户投诉审核任务返回record_id为空");
+                return  null;
+            }
+            return taskId;
+        } else {
+            if (analyzeResp != null) {
+                log.error("调用提交用户投诉审核任务接口失败, http状态: {}", analyzeResp.getStatusCode());
+                R.fail("调用提交用户投诉审核任务接口失败, http状态: " + analyzeResp.getStatusCode());
+                return  null;
+            }
+        }
+        return  null;
+    }
+
+    /**
+     * 获取双方用户的最近聊天记录
+     * @param userReporterUserById 举报人ID
+     * @param userReportedUserById 被举报人ID
+     * @return 聊天记录列表
+     */
+    public List<LifeMessage> getRecentChatMessages(String userReporterUserById, String userReportedUserById) {
+        // 构建查询条件
+        QueryWrapper<LifeMessage> queryWrapper = new QueryWrapper<>();
+
+        // 查询双方的聊天记录
+        queryWrapper.and(wrapper -> wrapper
+                        .eq("sender_id", userReporterUserById)
+                        .eq("receiver_id", userReportedUserById))
+                .or(wrapper -> wrapper
+                        .eq("sender_id", userReportedUserById)
+                        .eq("receiver_id", userReporterUserById));
+
+        // 按时间倒序排列
+        queryWrapper.orderByDesc("created_time");
+
+        // 限制50条记录
+        queryWrapper.last("LIMIT 50");
+
+        return lifeMessageMapper.selectList(queryWrapper);
+    }
+
+    /**
+     * 将聊天消息列表转换为文本格式
+     * @param messages 聊天消息列表
+     * @return 格式化后的文本字符串
+     */
+    private String convertMessagesToText(List<LifeMessage> messages) {
+        if (messages == null || messages.isEmpty()) {
+            return "";
+        }
+
+        StringBuilder sb = new StringBuilder();
+        // 按时间顺序排列(因为数据库查询是倒序的,这里需要重新排序)
+        for (int i = messages.size() - 1; i >= 0; i--) {
+            LifeMessage message = messages.get(i);
+            // 格式:[时间] 发送者ID: 消息内容
+            sb.append("[").append(formatTime(message.getCreatedTime())).append("] ")
+                    .append(message.getSenderId()).append(": ")
+                    .append(message.getContent()).append("\n");
+        }
+
+        return sb.toString().trim();
+    }
+
+    /**
+     * 格式化时间显示
+     * @param date 时间
+     * @return 格式化后的时间字符串
+     */
+    private String formatTime(Date date) {
+        if (date == null) {
+            return "";
+        }
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        return sdf.format(date);
+    }
+}

+ 12 - 10
alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StorePlatformBarMenuServiceImpl.java

@@ -96,16 +96,18 @@ public class StorePlatformBarMenuServiceImpl extends ServiceImpl<StorePlatformSt
 
         // 查询图片
         List<Integer> ids = list.stream().map(StorePlatformStoreMenu::getId).collect(Collectors.toList());
-        List<StoreImg> imgList = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>()
-                .eq(StoreImg::getStoreId, storeId).eq(StoreImg::getImgType, 7).in(StoreImg::getBusinessId, ids));
-
-        if (CollectionUtil.isNotEmpty(imgList)) {
-            list.forEach(menu -> {
-                imgList.stream()
-                        .filter(img -> img.getBusinessId().equals(menu.getId()))
-                        .findFirst()
-                        .ifPresent(img -> menu.setImgUrl(img.getImgUrl()));
-            });
+        if (CollectionUtil.isNotEmpty(ids)) {
+            List<StoreImg> imgList = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>()
+                    .eq(StoreImg::getStoreId, storeId).eq(StoreImg::getImgType, 7).in(StoreImg::getBusinessId, ids));
+
+            if (CollectionUtil.isNotEmpty(imgList)) {
+                list.forEach(menu -> {
+                    imgList.stream()
+                            .filter(img -> img.getBusinessId().equals(menu.getId()))
+                            .findFirst()
+                            .ifPresent(img -> menu.setImgUrl(img.getImgUrl()));
+                });
+            }
         }
 
 //        // 查询图片

+ 3 - 2
alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StorePlatformLoginServiceImpl.java

@@ -140,6 +140,7 @@ public class StorePlatformLoginServiceImpl extends ServiceImpl<StoreUserMapper,
             if (storeInfo != null) {
                 storeUserVo.setBusinessSection(storeInfo.getBusinessSection());
                 storeUserVo.setBusinessTypesName(storeInfo.getBusinessTypesName());
+                storeUserVo.setMealsFlag(storeInfo.getMealsFlag());
             }
             return R.data(storeUserVo);
         } catch (Exception e) {
@@ -213,10 +214,10 @@ public class StorePlatformLoginServiceImpl extends ServiceImpl<StoreUserMapper,
 
             StoreInfo storeInfo = storeInfoMapper.selectById(storeId);
             if (storeInfo != null) {
-                if (storeInfo.getExpirationTime().compareTo(new Date()) < 0) {
+                if (storeInfo.getExpirationTime() == null || storeInfo.getExpirationTime().compareTo(new Date()) < 0) {
                     jsonObject.put("expirationTime", 0);
                 }
-                if (storeInfo.getFoodLicenceExpirationTime().compareTo(new Date()) < 0) {
+                if (storeInfo.getFoodLicenceExpirationTime() == null || storeInfo.getFoodLicenceExpirationTime().compareTo(new Date()) < 0) {
                     jsonObject.put("foodLicenceExpirationTime", 0);
                 }
                 if (storeInfo.getEntertainmentLicenceExpirationTime() != null && storeInfo.getEntertainmentLicenceExpirationTime().compareTo(new Date()) < 0) {

+ 4 - 2
alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StorePlatformRenovationServiceImpl.java

@@ -64,8 +64,10 @@ public class StorePlatformRenovationServiceImpl extends ServiceImpl<StoreInfoMap
         StoreInfo storeInfo = storeInfoMapper.selectById(id);
         StoreMainInfoVo storeMainInfoVo = storeInfoMapper.getStoreInfo(id);
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
-        String expirationDate = sdf.format(storeMainInfoVo.getExpirationTime());
-        storeMainInfoVo.setExpirationDate(expirationDate);
+        if (storeMainInfoVo.getExpirationTime() != null) {
+            String expirationDate = sdf.format(storeMainInfoVo.getExpirationTime());
+            storeMainInfoVo.setExpirationDate(expirationDate);
+        }
         //审核通过给前台反显未提交
         if (storeMainInfoVo.getRenewContractStatus() == 1) {
             storeMainInfoVo.setRenewContractStatus(0);

+ 214 - 0
alien-store/src/main/java/shop/alien/store/controller/BathFacilityServiceController.java

@@ -0,0 +1,214 @@
+package shop.alien.store.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import io.swagger.annotations.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.entity.store.BathFacilityService;
+import shop.alien.entity.store.vo.BathFacilityServiceCategoryVo;
+import shop.alien.entity.store.vo.BathFacilityServiceVo;
+import shop.alien.store.service.BathFacilityServiceService;
+
+import java.util.List;
+
+/**
+ * 洗浴设施及服务Controller
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Slf4j
+@Api(tags = {"洗浴设施及服务管理"})
+@ApiSort(1)
+@CrossOrigin
+@RestController
+@RequestMapping("/bath/facility/service")
+@RequiredArgsConstructor
+public class BathFacilityServiceController {
+
+    private final BathFacilityServiceService facilityServiceService;
+
+    @ApiOperation("分页查询洗浴设施及服务列表(用户端)")
+    @ApiOperationSupport(order = 1)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "pageNum", value = "页码", dataType = "int", paramType = "query", required = true, defaultValue = "1"),
+            @ApiImplicitParam(name = "pageSize", value = "页大小", dataType = "int", paramType = "query", required = true, defaultValue = "10"),
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "int", paramType = "query", required = true),
+            @ApiImplicitParam(name = "facilityCategory", value = "设施分类(1:洗浴区, 2:汗蒸区, 3:休闲区, 4:餐饮区)", dataType = "int", paramType = "query")
+    })
+    @GetMapping("/page")
+    public R<IPage<BathFacilityServiceVo>> getPageList(
+            @RequestParam(defaultValue = "1") Integer pageNum,
+            @RequestParam(defaultValue = "10") Integer pageSize,
+            @RequestParam Integer storeId,
+            @RequestParam(required = false) Integer facilityCategory) {
+        log.info("BathFacilityServiceController.getPageList?pageNum={},pageSize={},storeId={},facilityCategory={}",
+                pageNum, pageSize, storeId, facilityCategory);
+        return R.data(facilityServiceService.getPageList(pageNum, pageSize, storeId, facilityCategory));
+    }
+
+    @ApiOperation("查询洗浴设施及服务列表")
+    @ApiOperationSupport(order = 2)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "int", paramType = "query", required = true),
+            @ApiImplicitParam(name = "facilityCategory", value = "设施分类(1:洗浴区, 2:汗蒸区, 3:休闲区, 4:餐饮区)", dataType = "int", paramType = "query")
+    })
+    @GetMapping("/list")
+    public R<List<BathFacilityServiceVo>> getList(
+            @RequestParam Integer storeId,
+            @RequestParam(required = false) Integer facilityCategory) {
+        log.info("BathFacilityServiceController.getList?storeId={},facilityCategory={}", storeId, facilityCategory);
+        return R.data(facilityServiceService.getList(storeId, facilityCategory));
+    }
+
+    @ApiOperation("根据ID查询洗浴设施及服务详情(用户端)")
+    @ApiOperationSupport(order = 3)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "主键ID", dataType = "int", paramType = "query", required = true)
+    })
+    @GetMapping("/detail")
+    public R<BathFacilityServiceVo> getDetail(@RequestParam Integer id) {
+        log.info("BathFacilityServiceController.getDetail?id={}", id);
+        BathFacilityServiceVo vo = facilityServiceService.getDetail(id);
+        if (vo == null) {
+            return R.fail("数据不存在");
+        }
+        return R.data(vo);
+    }
+
+    @ApiOperation("新增洗浴设施及服务")
+    @ApiOperationSupport(order = 4)
+    @PostMapping("/save")
+    public R<Boolean> saveFacilityService(@RequestBody BathFacilityServiceVo vo) {
+        log.info("BathFacilityServiceController.saveFacilityService?vo={}", vo);
+        try {
+            BathFacilityService facilityService = new BathFacilityService();
+            facilityService.setStoreId(vo.getStoreId());
+            facilityService.setFacilityCategory(vo.getFacilityCategory());
+            facilityService.setFacilityName(vo.getFacilityName());
+            facilityService.setChargingStandard(vo.getChargingStandard());
+            facilityService.setUsageTimeType(vo.getUsageTimeType());
+            facilityService.setUsageStartTime(vo.getUsageStartTime());
+            facilityService.setUsageEndTime(vo.getUsageEndTime());
+            facilityService.setDisplayInStoreDetail(vo.getDisplayInStoreDetail());
+            boolean result = facilityServiceService.saveFacilityService(facilityService, vo.getImageList());
+            if (result) {
+                return R.success("新增成功");
+            }
+            return R.fail("新增失败");
+        } catch (Exception e) {
+            log.error("BathFacilityServiceController.saveFacilityService异常", e);
+            return R.fail(e.getMessage());
+        }
+    }
+
+    @ApiOperation("修改洗浴设施及服务")
+    @ApiOperationSupport(order = 5)
+    @PostMapping("/update")
+    public R<Boolean> updateFacilityService(@RequestBody BathFacilityServiceVo vo) {
+        log.info("BathFacilityServiceController.updateFacilityService?vo={}", vo);
+        try {
+            if (vo.getId() == null) {
+                return R.fail("主键ID不能为空");
+            }
+            BathFacilityService facilityService = new BathFacilityService();
+            facilityService.setId(vo.getId());
+            facilityService.setStoreId(vo.getStoreId());
+            facilityService.setFacilityCategory(vo.getFacilityCategory());
+            facilityService.setFacilityName(vo.getFacilityName());
+            facilityService.setChargingStandard(vo.getChargingStandard());
+            facilityService.setUsageTimeType(vo.getUsageTimeType());
+            facilityService.setUsageStartTime(vo.getUsageStartTime());
+            facilityService.setUsageEndTime(vo.getUsageEndTime());
+            facilityService.setDisplayInStoreDetail(vo.getDisplayInStoreDetail());
+            boolean result = facilityServiceService.updateFacilityService(facilityService, vo.getImageList());
+            if (result) {
+                return R.success("修改成功");
+            }
+            return R.fail("修改失败");
+        } catch (Exception e) {
+            log.error("BathFacilityServiceController.updateFacilityService异常", e);
+            return R.fail(e.getMessage());
+        }
+    }
+
+    @ApiOperation("删除洗浴设施及服务")
+    @ApiOperationSupport(order = 6)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "主键ID", dataType = "int", paramType = "query", required = true)
+    })
+    @PostMapping("/delete")
+    public R<Boolean> deleteFacilityService(@RequestParam Integer id) {
+        log.info("BathFacilityServiceController.deleteFacilityService?id={}", id);
+        try {
+            boolean result = facilityServiceService.deleteFacilityService(id);
+            if (result) {
+                return R.success("删除成功");
+            }
+            return R.fail("删除失败");
+        } catch (Exception e) {
+            log.error("BathFacilityServiceController.deleteFacilityService异常", e);
+            return R.fail(e.getMessage());
+        }
+    }
+
+    @ApiOperation("查询指定店铺按分类汇总的设备信息(包含设备数量、设备列表和图片)(用户端)")
+    @ApiOperationSupport(order = 7)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "int", paramType = "query", required = true)
+    })
+    @GetMapping("/categorySummary")
+    public R<List<BathFacilityServiceCategoryVo>> getCategorySummary(@RequestParam Integer storeId) {
+        log.info("BathFacilityServiceController.getCategorySummary?storeId={}", storeId);
+        return R.data(facilityServiceService.getCategorySummary(storeId));
+    }
+
+
+    @ApiOperation("分页查询洗浴设施及服务列表(商户端)")
+    @ApiOperationSupport(order = 8)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "pageNum", value = "页码", dataType = "int", paramType = "query", required = true, defaultValue = "1"),
+            @ApiImplicitParam(name = "pageSize", value = "页大小", dataType = "int", paramType = "query", required = true, defaultValue = "10"),
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "int", paramType = "query", required = true),
+            @ApiImplicitParam(name = "facilityCategory", value = "设施分类(1:洗浴区, 2:汗蒸区, 3:休闲区, 4:餐饮区)", dataType = "int", paramType = "query")
+    })
+    @GetMapping("/storePage")
+    public R<IPage<BathFacilityServiceVo>> getStorePageList(
+            @RequestParam(defaultValue = "1") Integer pageNum,
+            @RequestParam(defaultValue = "10") Integer pageSize,
+            @RequestParam Integer storeId,
+            @RequestParam(required = false) Integer facilityCategory) {
+        log.info("BathFacilityServiceController.getStorePageList?pageNum={},pageSize={},storeId={},facilityCategory={}",
+                pageNum, pageSize, storeId, facilityCategory);
+        return R.data(facilityServiceService.getStorePageList(pageNum, pageSize, storeId, facilityCategory));
+    }
+
+    @ApiOperation("根据ID查询洗浴设施及服务详情(商户端)")
+    @ApiOperationSupport(order = 9)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "主键ID", dataType = "int", paramType = "query", required = true)
+    })
+    @GetMapping("/storeDetail")
+    public R<BathFacilityServiceVo> getStoreDetail(@RequestParam Integer id) {
+        log.info("BathFacilityServiceController.getStoreDetail?id={}", id);
+        BathFacilityServiceVo vo = facilityServiceService.getStoreDetail(id);
+        if (vo == null) {
+            return R.fail("数据不存在");
+        }
+        return R.data(vo);
+    }
+
+    @ApiOperation("查询指定店铺按分类汇总的设备信息(包含设备数量、设备列表和图片)(商户端)")
+    @ApiOperationSupport(order = 7)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "int", paramType = "query", required = true)
+    })
+    @GetMapping("/storeCategorySummary")
+    public R<List<BathFacilityServiceCategoryVo>> getStoreCategorySummary(@RequestParam Integer storeId) {
+        log.info("BathFacilityServiceController.getStoreCategorySummary?storeId={}", storeId);
+        return R.data(facilityServiceService.getStoreCategorySummary(storeId));
+    }
+}
+

+ 191 - 0
alien-store/src/main/java/shop/alien/store/controller/DrinkInfoController.java

@@ -0,0 +1,191 @@
+package shop.alien.store.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import io.swagger.annotations.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.entity.store.DrinkInfo;
+import shop.alien.entity.store.vo.DrinkInfoVo;
+import shop.alien.store.service.DrinkInfoService;
+
+import java.util.List;
+
+/**
+ * 酒水餐食信息 Controller
+ * 基于 store_menu 表实现(dish_menu_type: 1=餐食,2=酒水)
+ *
+ * @author ssk
+ * @since 2025-06-13
+ */
+@Slf4j
+@Api(tags = {"酒水餐食管理"})
+@ApiSort(1)
+@CrossOrigin
+@RestController
+@RequestMapping("/store/drink")
+@RequiredArgsConstructor
+public class DrinkInfoController {
+
+    private final DrinkInfoService drinkInfoService;
+
+    @ApiOperation("分页查询酒水餐食列表")
+    @ApiOperationSupport(order = 1)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "page", value = "页码", dataType = "int", paramType = "query", required = true),
+            @ApiImplicitParam(name = "size", value = "页容", dataType = "int", paramType = "query", required = true),
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "type", value = "类型(1:餐食,2:酒水)", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "category", value = "分类", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "name", value = "名称关键词", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "createUserId", value = "创建人ID(只查询自己创建的)", dataType = "Integer", paramType = "query")
+    })
+    @GetMapping("/page")
+    public R<IPage<DrinkInfoVo>> getDrinkInfoPage(
+            @RequestParam("page") int page,
+            @RequestParam("size") int size,
+            @RequestParam(value = "storeId", required = false) Integer storeId,
+            @RequestParam(value = "type", required = false) Integer type,
+            @RequestParam(value = "category", required = false) String category,
+            @RequestParam(value = "name", required = false) String name,
+            @RequestParam(value = "createUserId", required = false) Integer createUserId) {
+        log.info("DrinkInfoController.getDrinkInfoPage?page={}, size={}, storeId={}, type={}, category={}, name={}, createUserId={}", 
+                page, size, storeId, type, category, name, createUserId);
+        IPage<DrinkInfoVo> drinkInfoPage = drinkInfoService.getDrinkInfoPage(page, size, storeId, type, category, name, createUserId);
+        return R.data(drinkInfoPage);
+    }
+
+    @ApiOperation("根据ID查询酒水餐食详情")
+    @ApiOperationSupport(order = 2)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "主键ID", dataType = "Integer", paramType = "path", required = true)
+    })
+    @GetMapping("/{id}")
+    public R<DrinkInfoVo> getDrinkInfoById(@PathVariable("id") Integer id) {
+        log.info("DrinkInfoController.getDrinkInfoById?id={}", id);
+        DrinkInfoVo drinkInfoVo = drinkInfoService.getDrinkInfoById(id);
+        if (drinkInfoVo == null) {
+            return R.fail("未找到该酒水餐食信息");
+        }
+        return R.data(drinkInfoVo);
+    }
+
+    @ApiOperation("新增酒水餐食")
+    @ApiOperationSupport(order = 3)
+    @PostMapping
+    public R<String> saveDrinkInfo(@RequestBody DrinkInfo drinkInfo) {
+        log.info("DrinkInfoController.saveDrinkInfo?drinkInfo={}", drinkInfo);
+        boolean result = drinkInfoService.saveDrinkInfo(drinkInfo);
+        if (result) {
+            return R.success("新增成功");
+        }
+        return R.fail("新增失败");
+    }
+
+    @ApiOperation("修改酒水餐食")
+    @ApiOperationSupport(order = 4)
+    @PutMapping
+    public R<String> updateDrinkInfo(@RequestBody DrinkInfo drinkInfo) {
+        log.info("DrinkInfoController.updateDrinkInfo?drinkInfo={}", drinkInfo);
+        boolean result = drinkInfoService.updateDrinkInfo(drinkInfo);
+        if (result) {
+            return R.success("修改成功");
+        }
+        return R.fail("修改失败");
+    }
+
+    @ApiOperation("删除酒水餐食")
+    @ApiOperationSupport(order = 5)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "主键ID", dataType = "Integer", paramType = "path", required = true)
+    })
+    @DeleteMapping("/{id}")
+    public R<String> deleteDrinkInfo(@PathVariable("id") Integer id) {
+        log.info("DrinkInfoController.deleteDrinkInfo?id={}", id);
+        boolean result = drinkInfoService.deleteDrinkInfo(id);
+        if (result) {
+            return R.success("删除成功");
+        }
+        return R.fail("删除失败");
+    }
+
+    @ApiOperation("设置酒水餐食推荐")
+    @ApiOperationSupport(order = 7)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "主键ID", dataType = "Integer", paramType = "path", required = true),
+            @ApiImplicitParam(name = "isRecommended", value = "是否推荐(0:否, 1:是)", dataType = "Integer", paramType = "query", required = true)
+    })
+    @PutMapping("/{id}/recommended")
+    public R<String> updateIsRecommended(
+            @PathVariable("id") Integer id,
+            @RequestParam("isRecommended") Integer isRecommended) {
+        log.info("DrinkInfoController.updateIsRecommended?id={}, isRecommended={}", id, isRecommended);
+        boolean result = drinkInfoService.updateIsRecommended(id, isRecommended);
+        if (result) {
+            return R.success("操作成功");
+        }
+        return R.fail("操作失败");
+    }
+
+    @ApiOperation("更新酒水餐食排序")
+    @ApiOperationSupport(order = 8)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "主键ID", dataType = "Integer", paramType = "path", required = true),
+            @ApiImplicitParam(name = "sort", value = "排序值", dataType = "Integer", paramType = "query", required = true)
+    })
+    @PutMapping("/{id}/sort")
+    public R<String> updateSort(
+            @PathVariable("id") Integer id,
+            @RequestParam("sort") Integer sort) {
+        log.info("DrinkInfoController.updateSort?id={}, sort={}", id, sort);
+        boolean result = drinkInfoService.updateSort(id, sort);
+        if (result) {
+            return R.success("操作成功");
+        }
+        return R.fail("操作失败");
+    }
+
+    @ApiOperation("根据门店ID查询所有酒水餐食")
+    @ApiOperationSupport(order = 9)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "type", value = "类型(枚举值:酒水/餐食)", dataType = "String", paramType = "query")
+    })
+    @GetMapping("/listByStoreId")
+    public R<List<DrinkInfoVo>> getDrinkInfoListByStoreId(
+            @RequestParam("storeId") Integer storeId,
+            @RequestParam(value = "type", required = false) Integer type) {
+        log.info("DrinkInfoController.getDrinkInfoListByStoreId?storeId={}, type={}", storeId, type);
+        List<DrinkInfoVo> drinkInfoList = drinkInfoService.getDrinkInfoListByStoreId(storeId, type);
+        return R.data(drinkInfoList);
+    }
+
+    @ApiOperation("查询推荐酒水餐食列表")
+    @ApiOperationSupport(order = 10)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "createUserId", value = "创建人ID(只查询自己创建的)", dataType = "Integer", paramType = "query")
+    })
+    @GetMapping("/recommended")
+    public R<List<DrinkInfoVo>> getRecommendedList(
+            @RequestParam(value = "storeId", required = false) Integer storeId,
+            @RequestParam(value = "createUserId", required = false) Integer createUserId) {
+        log.info("DrinkInfoController.getRecommendedList?storeId={}, createUserId={}", storeId, createUserId);
+        List<DrinkInfoVo> drinkInfoList = drinkInfoService.getRecommendedList(storeId, createUserId);
+        return R.data(drinkInfoList);
+    }
+
+    @ApiOperation("批量更新酒水餐食排序")
+    @ApiOperationSupport(order = 11)
+    @PostMapping("/batchSort")
+    public R<String> batchUpdateSort(@RequestBody List<DrinkInfo> drinkInfoList) {
+        log.info("DrinkInfoController.batchUpdateSort?size={}", drinkInfoList.size());
+        boolean result = drinkInfoService.batchUpdateSort(drinkInfoList);
+        if (result) {
+            return R.success("批量更新排序成功");
+        }
+        return R.fail("批量更新排序失败");
+    }
+
+}

+ 17 - 0
alien-store/src/main/java/shop/alien/store/controller/LifeCouponController.java

@@ -10,6 +10,7 @@ import shop.alien.entity.result.R;
 import shop.alien.entity.store.EssentialHolidayComparison;
 import shop.alien.entity.store.LifeCoupon;
 import shop.alien.entity.store.vo.LifeCouponStatusVo;
+import shop.alien.entity.store.vo.LifeCouponVo;
 import shop.alien.store.service.LifeCouponService;
 
 import java.util.Map;
@@ -78,6 +79,22 @@ public class LifeCouponController {
         return R.data(lifeCouponService.getOne(objectLambdaQueryWrapper));
     }
 
+    @ApiOperation("代金劵详情")
+    @GetMapping("/getNewCouponDetail")
+    private R<LifeCouponVo> getNewCouponDetail(@RequestParam("id") String id) {
+        log.info("LifeCouponController.getNewCouponDetail?id={}", id);
+        try {
+            LifeCouponVo lifeCouponVo = lifeCouponService.getNewCouponDetail(id);
+            if (lifeCouponVo == null) {
+                return R.fail("代金券不存在或已删除");
+            }
+            return R.data(lifeCouponVo);
+        } catch (Exception e) {
+            log.error("LifeCouponController.getNewCouponDetail ERROR Msg={}", e.getMessage(), e);
+            return R.fail("查询失败");
+        }
+    }
+
     @ApiOperation("旧 核销订单")
     @ApiImplicitParams({@ApiImplicitParam(name = "storeId", value = "门店id", dataType = "Integer", paramType = "query", required = true), @ApiImplicitParam(name = "quanCode", value = "券码", dataType = "Integer", paramType = "query", required = true)})
     @GetMapping("/verify")

+ 99 - 0
alien-store/src/main/java/shop/alien/store/controller/OperationalActivityController.java

@@ -0,0 +1,99 @@
+package shop.alien.store.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import io.swagger.annotations.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.entity.storePlatform.vo.StoreOperationalActivityVO;
+import shop.alien.store.service.OperationalActivityService;
+
+/**
+ * 运营活动管理控制器
+ *
+ * @author system
+ * @since 2025-11-26
+ */
+@Slf4j
+@Api(tags = {"商家端-运营活动管理"})
+@ApiSort(10)
+@CrossOrigin
+@RestController
+@RequestMapping("/operationalActivity")
+@RequiredArgsConstructor
+public class OperationalActivityController {
+
+    private final OperationalActivityService activityService;
+
+    @ApiOperation("根据活动ID获取详情")
+    @ApiOperationSupport(order = 4)
+    @ApiImplicitParam(name = "id", value = "活动ID", dataTypeClass = Integer.class, paramType = "path", required = true)
+    @GetMapping("/detail/{id}")
+    public R<StoreOperationalActivityVO> getActivityDetailById(@PathVariable("id") Integer id) {
+        log.info("OperationalActivityController.getActivityDetailById: id={}", id);
+        try {
+            StoreOperationalActivityVO result = activityService.getActivityDetailById(id);
+            return R.data(result);
+        } catch (IllegalArgumentException e) {
+            return R.fail(e.getMessage());
+        } catch (Exception e) {
+            log.error("OperationalActivityController.getActivityDetailById ERROR: {}", e.getMessage(), e);
+            return R.fail(e.getMessage());
+        }
+    }
+
+    @ApiOperation("分页查看运营活动列表")
+    @ApiOperationSupport(order = 5)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "商户ID", dataTypeClass = Integer.class, paramType = "query"),
+            @ApiImplicitParam(name = "storeName", value = "商户名称(模糊)", dataTypeClass = String.class, paramType = "query"),
+            @ApiImplicitParam(name = "pageNum", value = "当前页", dataTypeClass = Integer.class, paramType = "query"),
+            @ApiImplicitParam(name = "pageSize", value = "每页数量", dataTypeClass = Integer.class, paramType = "query")
+    })
+    @GetMapping("/detail")
+    public R<IPage<StoreOperationalActivityVO>> pageActivityDetail(
+            @RequestParam(value = "storeId", required = false) Integer storeId,
+            @RequestParam(value = "storeName", required = false) String storeName,
+            @RequestParam(value = "pageNum", required = false) Integer pageNum,
+            @RequestParam(value = "pageSize", required = false) Integer pageSize) {
+        log.info("OperationalActivityController.pageActivityDetail storeId={}, storeName={}, pageNum={}, pageSize={}", storeId, storeName, pageNum, pageSize);
+        try {
+            IPage<StoreOperationalActivityVO> result = activityService.pageActivityDetail(storeId, storeName, pageNum, pageSize);
+            return R.data(result);
+        } catch (IllegalArgumentException e) {
+            return R.fail(e.getMessage());
+        } catch (Exception e) {
+            log.error("OperationalActivityController.pageActivityDetail ERROR: {}", e.getMessage(), e);
+            return R.fail(e.getMessage());
+        }
+    }
+
+    @ApiOperation("运营活动审核处理")
+    @ApiOperationSupport(order = 6)
+    @PostMapping("/audit")
+    public R<String> auditActivity(
+            @RequestParam("id") Integer id,
+            @RequestParam("status") Integer status,
+            @RequestParam(value = "approvalComments", required = false) String approvalComments) {
+        log.info("OperationalActivityController.auditActivity: id={}, status={}, approvalComments={}", id, status, approvalComments);
+        if (id == null) {
+            return R.fail("活动ID不能为空");
+        }
+        if (status == null) {
+            return R.fail("审核状态不能为空");
+        }
+        try {
+            int result = activityService.auditActivity(id, status, approvalComments);
+            if (result > 0) {
+                return R.success("审核处理成功");
+            }
+            return R.fail("审核处理失败");
+        } catch (Exception e) {
+            log.error("OperationalActivityController.auditActivity ERROR: {}", e.getMessage(), e);
+            return R.fail(e.getMessage());
+        }
+    }
+
+}
+

+ 212 - 0
alien-store/src/main/java/shop/alien/store/controller/SportsEquipmentFacilityController.java

@@ -0,0 +1,212 @@
+package shop.alien.store.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import io.swagger.annotations.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.entity.store.SportsEquipmentFacility;
+import shop.alien.entity.store.vo.SportsEquipmentFacilityCategoryVo;
+import shop.alien.entity.store.vo.SportsEquipmentFacilityVo;
+import shop.alien.store.service.SportsEquipmentFacilityService;
+
+import java.util.List;
+
+/**
+ * 运动器材设施Controller
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Slf4j
+@Api(tags = {"运动器材设施管理"})
+@ApiSort(1)
+@CrossOrigin
+@RestController
+@RequestMapping("/sports/equipment/facility")
+@RequiredArgsConstructor
+public class SportsEquipmentFacilityController {
+
+    private final SportsEquipmentFacilityService facilityService;
+
+    @ApiOperation("分页查询运动器材设施列表")
+    @ApiOperationSupport(order = 1)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "pageNum", value = "页码", dataType = "int", paramType = "query", required = true, defaultValue = "1"),
+            @ApiImplicitParam(name = "pageSize", value = "页大小", dataType = "int", paramType = "query", required = true, defaultValue = "10"),
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "int", paramType = "query", required = true),
+            @ApiImplicitParam(name = "facilityCategory", value = "设施分类(1:有氧区, 2:力量区, 3:单功能机械区)", dataType = "int", paramType = "query")
+    })
+    @GetMapping("/page")
+    public R<IPage<SportsEquipmentFacilityVo>> getPageList(
+            @RequestParam(defaultValue = "1") Integer pageNum,
+            @RequestParam(defaultValue = "10") Integer pageSize,
+            @RequestParam Integer storeId,
+            @RequestParam(required = false) Integer facilityCategory) {
+        log.info("SportsEquipmentFacilityController.getPageList?pageNum={},pageSize={},storeId={},facilityCategory={}",
+                pageNum, pageSize, storeId, facilityCategory);
+        return R.data(facilityService.getPageList(pageNum, pageSize, storeId, facilityCategory));
+    }
+
+    @ApiOperation("查询运动器材设施列表")
+    @ApiOperationSupport(order = 2)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "int", paramType = "query", required = true),
+            @ApiImplicitParam(name = "facilityCategory", value = "设施分类(1:有氧区, 2:力量区, 3:单功能机械区)", dataType = "int", paramType = "query")
+    })
+    @GetMapping("/list")
+    public R<List<SportsEquipmentFacilityVo>> getList(
+            @RequestParam Integer storeId,
+            @RequestParam(required = false) Integer facilityCategory) {
+        log.info("SportsEquipmentFacilityController.getList?storeId={},facilityCategory={}", storeId, facilityCategory);
+        return R.data(facilityService.getList(storeId, facilityCategory));
+    }
+
+    @ApiOperation("根据ID查询运动器材设施详情(用户端)")
+    @ApiOperationSupport(order = 3)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "主键ID", dataType = "int", paramType = "query", required = true)
+    })
+    @GetMapping("/detail")
+    public R<SportsEquipmentFacilityVo> getDetail(@RequestParam Integer id) {
+        log.info("SportsEquipmentFacilityController.getDetail?id={}", id);
+        SportsEquipmentFacilityVo vo = facilityService.getDetail(id);
+        if (vo == null) {
+            return R.fail("数据不存在");
+        }
+        return R.data(vo);
+    }
+
+    @ApiOperation("新增运动器材设施")
+    @ApiOperationSupport(order = 4)
+    @PostMapping("/save")
+    public R<Boolean> saveFacility(@RequestBody SportsEquipmentFacilityVo vo) {
+        log.info("SportsEquipmentFacilityController.saveFacility?vo={}", vo);
+        try {
+            SportsEquipmentFacility facility = new SportsEquipmentFacility();
+            facility.setStoreId(vo.getStoreId());
+            facility.setFacilityCategory(vo.getFacilityCategory());
+            facility.setFacilityName(vo.getFacilityName());
+            facility.setQuantity(vo.getQuantity());
+            facility.setBrand(vo.getBrand());
+            facility.setDescription(vo.getDescription());
+            facility.setDisplayInStoreDetail(vo.getDisplayInStoreDetail());
+            boolean result = facilityService.saveFacility(facility, vo.getImageList());
+            if (result) {
+                return R.success("新增成功");
+            }
+            return R.fail("新增失败");
+        } catch (Exception e) {
+            log.error("SportsEquipmentFacilityController.saveFacility异常", e);
+            return R.fail(e.getMessage());
+        }
+    }
+
+    @ApiOperation("修改运动器材设施")
+    @ApiOperationSupport(order = 5)
+    @PostMapping("/update")
+    public R<Boolean> updateFacility(@RequestBody SportsEquipmentFacilityVo vo) {
+        log.info("SportsEquipmentFacilityController.updateFacility?vo={}", vo);
+        try {
+            if (vo.getId() == null) {
+                return R.fail("主键ID不能为空");
+            }
+            SportsEquipmentFacility facility = new SportsEquipmentFacility();
+            facility.setId(vo.getId());
+            facility.setStoreId(vo.getStoreId());
+            facility.setFacilityCategory(vo.getFacilityCategory());
+            facility.setFacilityName(vo.getFacilityName());
+            facility.setQuantity(vo.getQuantity());
+            facility.setBrand(vo.getBrand());
+            facility.setDescription(vo.getDescription());
+            facility.setDisplayInStoreDetail(vo.getDisplayInStoreDetail());
+            boolean result = facilityService.updateFacility(facility, vo.getImageList());
+            if (result) {
+                return R.success("修改成功");
+            }
+            return R.fail("修改失败");
+        } catch (Exception e) {
+            log.error("SportsEquipmentFacilityController.updateFacility异常", e);
+            return R.fail(e.getMessage());
+        }
+    }
+
+    @ApiOperation("删除运动器材设施")
+    @ApiOperationSupport(order = 6)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "主键ID", dataType = "int", paramType = "query", required = true)
+    })
+    @PostMapping("/delete")
+    public R<Boolean> deleteFacility(@RequestParam Integer id) {
+        log.info("SportsEquipmentFacilityController.deleteFacility?id={}", id);
+        try {
+            boolean result = facilityService.deleteFacility(id);
+            if (result) {
+                return R.success("删除成功");
+            }
+            return R.fail("删除失败");
+        } catch (Exception e) {
+            log.error("SportsEquipmentFacilityController.deleteFacility异常", e);
+            return R.fail(e.getMessage());
+        }
+    }
+
+    @ApiOperation("查询指定店铺按分类汇总的设备信息(包含设备数量、图片列表和设备列表)(用户端)")
+    @ApiOperationSupport(order = 7)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "int", paramType = "query", required = true)
+    })
+    @GetMapping("/categorySummary")
+    public R<List<SportsEquipmentFacilityCategoryVo>> getCategorySummary(@RequestParam Integer storeId) {
+        log.info("SportsEquipmentFacilityController.getCategorySummary?storeId={}", storeId);
+        return R.data(facilityService.getCategorySummary(storeId));
+    }
+
+
+
+    @ApiOperation("根据ID查询运动器材设施详情(商户端)")
+    @ApiOperationSupport(order = 8)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "主键ID", dataType = "int", paramType = "query", required = true)
+    })
+    @GetMapping("/storeDetail")
+    public R<SportsEquipmentFacilityVo> getStoreDetail(@RequestParam Integer id) {
+        log.info("SportsEquipmentFacilityController.getStoreDetail?id={}", id);
+        SportsEquipmentFacilityVo vo = facilityService.getStoreDetail(id);
+        if (vo == null) {
+            return R.fail("数据不存在");
+        }
+        return R.data(vo);
+    }
+
+    @ApiOperation("查询指定店铺按分类汇总的设备信息(包含设备数量、图片列表和设备列表)(商户端)")
+    @ApiOperationSupport(order = 9)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "int", paramType = "query", required = true)
+    })
+    @GetMapping("/storeCategorySummary")
+    public R<List<SportsEquipmentFacilityCategoryVo>> getstoreCategorySummary(@RequestParam Integer storeId) {
+        log.info("SportsEquipmentFacilityController.getstoreCategorySummary?storeId={}", storeId);
+        return R.data(facilityService.getstoreCategorySummary(storeId));
+    }
+
+    @ApiOperation("保存分类下的实景图片(商户端)- 设施列表通过添加接口已保存,此接口仅保存图片")
+    @ApiOperationSupport(order = 10)
+    @PostMapping("/saveCategoryImages")
+    public R<Boolean> saveCategoryImages(@RequestBody SportsEquipmentFacilityCategoryVo vo) {
+        log.info("SportsEquipmentFacilityController.saveCategoryImages?storeId={},facilityCategory={},imageList={}", 
+                vo.getStoreId(), vo.getFacilityCategory(), vo.getImageList());
+        try {
+            boolean result = facilityService.saveCategoryImages(vo.getStoreId(), vo.getFacilityCategory(), vo.getImageList());
+            if (result) {
+                return R.success("保存成功");
+            }
+            return R.fail("保存失败");
+        } catch (Exception e) {
+            log.error("SportsEquipmentFacilityController.saveCategoryImages异常", e);
+            return R.fail(e.getMessage());
+        }
+    }
+}
+

+ 412 - 18
alien-store/src/main/java/shop/alien/store/controller/StoreInfoController.java

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import io.swagger.annotations.*;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartRequest;
@@ -15,17 +16,13 @@ import shop.alien.entity.store.*;
 import shop.alien.entity.store.dto.StoreInfoDto;
 import shop.alien.entity.store.vo.*;
 import shop.alien.entity.storePlatform.StoreLicenseHistory;
-import shop.alien.mapper.StoreCommentSummaryInterestMapper;
-import shop.alien.mapper.TagsMainMapper;
-import shop.alien.mapper.WebAuditMapper;
+import shop.alien.mapper.*;
 import shop.alien.mapper.storePlantform.StoreLicenseHistoryMapper;
 import shop.alien.store.config.BaseRedisService;
 import shop.alien.store.service.StoreInfoService;
 
 import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 /**
  * 二期-门店信息Controller
@@ -55,6 +52,10 @@ public class StoreInfoController {
     /** 商户证照历史记录数据访问对象 */
     private final StoreLicenseHistoryMapper licenseHistoryMapper;
 
+    private final StoreImgMapper storeImgMapper;
+
+    private final StoreCommentMapper storeCommentMapper;
+
     @ApiOperation("获取所有门店")
     @ApiOperationSupport(order = 1)
     @GetMapping("/getAll")
@@ -100,6 +101,7 @@ public class StoreInfoController {
         return R.fail("失败");
     }
 
+
     @ApiOperation("新增门店草稿")
     @ApiOperationSupport(order = 3)
     @PostMapping("/saveStoreInfoDraft")
@@ -392,6 +394,24 @@ public class StoreInfoController {
         return R.data(storeDetail);
     }
 
+    @ApiOperation(value = "获取门店代金券明细")
+    @ApiOperationSupport(order = 7)
+    @GetMapping("/getStoreCouponList")
+    @ResponseBody
+    public R getStoreCouponList(@RequestParam("storeId") String storeId) {
+        log.info("StoreInfoController.getStoreCouponList?storeId={}", storeId);
+        CouponAndEventVo couponAndEventVo = new CouponAndEventVo();
+        List<LifeCouponVo> lifeCouponVos = storeInfoService.getStoreCouponList(storeId);
+
+        List<StoreImg> storeImgs = storeInfoService.getBannerUrl(storeId);
+        couponAndEventVo.setCouponList(lifeCouponVos);
+        if (CollectionUtils.isNotEmpty(storeImgs)) {
+            couponAndEventVo.setMarketingList(storeImgs);
+        }
+        couponAndEventVo.setMarketingList(storeImgs);
+        return R.data(couponAndEventVo);
+    }
+
     @ApiOperation(value = "web端审批店铺")
     @ApiOperationSupport(order = 6)
     @GetMapping("/approveStoreInfo")
@@ -402,6 +422,28 @@ public class StoreInfoController {
         return R.success("审批完成");
     }
 
+    @ApiOperation(value = "中台web端获取店铺明细详情")
+    @ApiOperationSupport(order = 21)
+    @GetMapping("/getNewStoreDetail")
+    @ResponseBody
+    public R getNewStoreDetail(@RequestParam("id") String id) {
+        log.info("StoreInfoController.getStoreDetail?id={}", id);
+        StoreInfoVo storeDetail = storeInfoService.getNewStoreDetail(id);
+        return R.data(storeDetail);
+    }
+
+    @ApiOperation("新中台web端修改门店")
+    @ApiOperationSupport(order = 22)
+    @PostMapping("/editNewStoreInfo")
+    public R editNewStoreInfo(@RequestBody StoreInfoDto storeInfoDto) {
+        log.info("StoreInfoController.editStoreInfo?storeInfoDto={}", storeInfoDto);
+        StoreInfoVo storeInfoVo = storeInfoService.editNewStoreInfo(storeInfoDto);
+        if (storeInfoVo != null) {
+            return R.data(storeInfoVo);
+        }
+        return R.fail("失败");
+    }
+
     @ApiOperation(value = "web端导出店铺信息")
     @ApiOperationSupport(order = 6)
     @GetMapping("/exportExcel")
@@ -728,13 +770,53 @@ public class StoreInfoController {
 
     @ApiOperation(value = "AI服务-门店评价标签")
     @GetMapping("/getStoreEvaluateTags")
-    @ApiImplicitParams({@ApiImplicitParam(name = "storeId", value = "门店id", dataType = "int", paramType = "query")})
-    public R<List<TagsMainVo>> getStoreEvaluateTags(int storeId) {
-        log.info("StoreInfoController.getStoreEvaluateTags?storeId={}", storeId);
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店id", dataType = "int", paramType = "query", required = true)
+    })
+    public R<Map<String,Object>> getStoreEvaluateTags(@RequestParam("storeId") int storeId) {
+        log.info("StoreInfoController.getStoreEvaluateTags?storeId={}, tagType={}", storeId);
+        Map<String,Object> map = new HashMap<>();
         List<TagsMainVo> voList = tagsMainMapper.getStoreEvaluateTags(storeId);
-        return R.data(voList);
+        if(voList !=null && voList.size()>0){
+            StoreCommentVo storeComment = storeCommentMapper.getCommentOneInfo(storeId);
+            if(storeComment!=null){
+                if(storeComment.getImgId()!=null){
+                    List<String> imgIds = Arrays.asList(storeComment.getImgId().split(","));
+                    List<StoreImg> storeImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().in(StoreImg::getId, imgIds));
+                    storeComment.setImgList(storeImgs);
+                }
+                LambdaQueryWrapper<StoreComment> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
+                lambdaQueryWrapper1.eq(StoreComment :: getStoreId, storeId);
+                lambdaQueryWrapper1.eq(StoreComment :: getBusinessType, 5);
+                lambdaQueryWrapper1.eq(StoreComment :: getDeleteFlag, 0);
+                Integer commitCount = storeCommentMapper.selectCount(lambdaQueryWrapper1);
+                map.put("commitCount",commitCount);
+            }
+            map.put("tag",voList);
+            map.put("evaluate",storeComment);
+        }
+        return R.data(map);
     }
 
+    @ApiOperation(value = "AI服务-门店评价标签下评价")
+    @GetMapping("/getStoreEvaluateTagsList")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "mainId", value = "标签id", dataType = "int", paramType = "query", required = true)
+    })
+    public R<List<StoreCommentVo>> getStoreEvaluateTagsList(@RequestParam("mainId") int mainId) {
+        log.info("StoreInfoController.getStoreEvaluateTagsList?mainId={}", mainId);
+        List<StoreCommentVo> list = tagsMainMapper.getstoreCommentList(mainId);
+        if(list!=null && list.size()>0){
+            for(int i = 0; i<list.size(); i++){
+                if(list.get(i).getImgId()!=null){
+                    List<String> imgIds = Arrays.asList(list.get(i).getImgId().split(","));
+                    List<StoreImg> storeImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().in(StoreImg::getId, imgIds));
+                    list.get(i).setImgList(storeImgs);
+                }
+            }
+        }
+        return R.data(list);
+    }
     @ApiOperation(value = "AI服务-门店趣味信息")
     @GetMapping("/getStoreInterestInfo")
     @ApiImplicitParams({
@@ -760,25 +842,337 @@ public class StoreInfoController {
         }
     }
 
+    @ApiOperation(value = "更多推荐(用户端)")
+    @GetMapping("/getMoreRecommendedStores")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "lon", value = "经度", dataType = "double", paramType = "query", required = true),
+            @ApiImplicitParam(name = "lat", value = "纬度", dataType = "double", paramType = "query", required = true),
+            @ApiImplicitParam(name = "businessSection", value = "经营板块", dataType = "String", paramType = "query", required = true),
+            @ApiImplicitParam(name = "businessTypes", value = "经营分类", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "businessClassify", value = "分类", dataType = "String", paramType = "query")
+    })
+    public R<List<StoreInfoVo>> getMoreRecommendedStores(Double lon , Double lat, String businessSection, String businessTypes, String businessClassify) {
+        log.info("StoreInfoController.getMoreRecommendedStores?lon={},lat={},businessSection={},businessTypes={},businessClassify={}", lon,lat, businessSection, businessTypes, businessClassify);
+        return R.data(storeInfoService.getMoreRecommendedStores(lon,lat, businessSection, businessTypes, businessClassify));
+
+    }
+
     @ApiOperation(value = "AI服务-门头识别")
     @ApiOperationSupport(order = 16)
     @ApiImplicitParams({
-            @ApiImplicitParam(name = "storeUserId", value = "门店用户id", dataType = "String", paramType = "query", required = true),
-            @ApiImplicitParam(name = "imageUrl", value = "图片URL", dataType = "String", paramType = "query", required = true)
+            @ApiImplicitParam(name = "imageUrl", value = "图片URL", dataType = "String", paramType = "query", required = true),
+            @ApiImplicitParam(name = "merchantName", value = "门店名称", dataType = "String", paramType = "query", required = true)
     })
     @GetMapping("/getStoreOcrData")
-    public R<Map<String, Object>> getStoreOcrData(@RequestParam("storeUserId") String storeUserId,
-                                                  @RequestParam("imageUrl") String imageUrl) {
-        log.info("StoreInfoController.getStoreOcrData?storeId={},imageUrl={}", storeUserId, imageUrl);
-        if (storeUserId == null || storeUserId.trim().isEmpty() || imageUrl == null || imageUrl.trim().isEmpty()) {
-            return R.fail("门店ID与图片URL不能为空");
+    public R<Map<String, Object>> getStoreOcrData(@RequestParam("imageUrl") String imageUrl,
+                                                  @RequestParam("merchantName") String merchantName) {
+        log.info("StoreInfoController.getStoreOcrData?imageUrl={},merchantName{}", imageUrl, merchantName);
+        if (merchantName == null || merchantName.trim().isEmpty() || imageUrl == null || imageUrl.trim().isEmpty()) {
+            return R.fail("门店名称与图片URL不能为空");
         }
         Map<String, Object> ocrData = null;
         try {
-            ocrData = storeInfoService.getStoreOcrData(storeUserId, imageUrl);
+            ocrData = storeInfoService.getStoreOcrData(imageUrl, merchantName);
         } catch (Exception e) {
             return R.fail("未查询到OCR识别数据");
         }
         return R.data(ocrData);
     }
+
+    @ApiOperation(value = "获取店铺详情(用户端)")
+    @ApiOperationSupport(order = 17)
+    @GetMapping("/getClientStoreDetail")
+    @ResponseBody
+    public R getClientStoreDetail(@RequestParam("id") String id,
+                                  @RequestParam(value = "userId", required = false) String userId,
+                                  @RequestParam(value = "jingdu", required = false) String jingdu,
+                                  @RequestParam(value = "weidu", required = false) String weidu) {
+        log.info("StoreInfoController.getClientStoreDetail?id={},userId={},jingdu={},weidu={}", id, jingdu, weidu);
+        StoreInfoVo storeDetail = storeInfoService.getClientStoreDetail(id, userId, jingdu, weidu);
+        return R.data(storeDetail);
+    }
+    /**
+     * 查询四种类型店铺(酒吧、ktv、洗浴汗蒸、按摩足浴)并按距离筛选
+     *
+     * @param lon         经度
+     * @param lat         纬度
+     * @param distance    距离范围(单位:公里)
+     * @param sortType    排序模式(1:智能排序,2:好评优先,3:距离优先)
+     * @param businessType 店铺类型(KTV=3、洗浴汗蒸=4、按摩足浴=5,酒吧需要查询字典表),可选,如果指定则只查询该类型
+     * @param pageNum     页码
+     * @param pageSize    页容
+     * @return R<IPage<StoreInfoVo>> 分页的门店信息列表
+     */
+    @ApiOperation("查询四种类型店铺(酒吧、ktv、洗浴汗蒸、按摩足浴)并按距离筛选")
+    @ApiOperationSupport(order = 16)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "lon", value = "经度", dataType = "Double", paramType = "query", required = true),
+            @ApiImplicitParam(name = "lat", value = "纬度", dataType = "Double", paramType = "query", required = true),
+            @ApiImplicitParam(name = "distance", value = "距离范围(单位:公里)", dataType = "Double", paramType = "query"),
+            @ApiImplicitParam(name = "sortType", value = "排序模式(1:智能排序,2:好评优先,3:距离优先)", dataType = "int", paramType = "query"),
+            @ApiImplicitParam(name = "businessType", value = "店铺类型(KTV=3、洗浴汗蒸=4、按摩足浴=5,丽人美发=6,运动健身=7,酒吧=11)", dataType = "int", paramType = "query"),
+            @ApiImplicitParam(name = "categoryId", value = "字典表id,根据此id查询经营板块、经营种类、分类并匹配店铺", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "storeName", value = "店铺名称(模糊查询)", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "storeType", value = "美食3 休闲娱乐1  健身2 ", dataType = "int", paramType = "query"),
+            @ApiImplicitParam(name = "pageNum", value = "页码", dataType = "int", paramType = "query", required = true),
+            @ApiImplicitParam(name = "pageSize", value = "页容", dataType = "int", paramType = "query", required = true)
+    })
+    @GetMapping("/getSpecialTypeStoresByDistance")
+    public R<IPage<StoreInfoVo>> getSpecialTypeStoresByDistance(
+            @RequestParam("lon") Double lon,
+            @RequestParam("lat") Double lat,
+            @RequestParam(value = "distance", required = false) Double distance,
+            @RequestParam(value = "sortType", required = false, defaultValue = "1") Integer sortType,
+            @RequestParam(value = "businessType", required = false) Integer businessType,
+            @RequestParam(value = "categoryId", required = false) Integer categoryId,
+            @RequestParam(value = "storeName", required = false) String storeName,
+            @RequestParam(value = "storeType", required = false) Integer storeType,
+            @RequestParam(defaultValue = "1") int pageNum,
+            @RequestParam(defaultValue = "10") int pageSize) {
+        log.info("StoreInfoController.getSpecialTypeStoresByDistance?lon={},lat={},distance={},sortType={},businessType={},categoryId={},storeName={},storeType{},pageNum={},pageSize={}",
+                lon, lat, distance, sortType, businessType, categoryId, storeName,storeType, pageNum, pageSize);
+
+        try {
+            // 参数校验:经度范围 [-180, 180],纬度范围 [-90, 90]
+            if (lon == null || lat == null) {
+                return R.fail("经纬度参数不能为空");
+            }
+
+            // 智能检测:如果参数可能传反了(lat超出范围但lon在范围内),给出提示
+            if (Math.abs(lat) > 90 && Math.abs(lon) <= 90) {
+                return R.fail(String.format("参数可能传反了!当前值: lon=%s, lat=%s。经度范围: [-180, 180],纬度范围: [-90, 90]。请检查参数顺序。", lon, lat));
+            }
+
+            if (lon < -180 || lon > 180) {
+                return R.fail("经度参数超出有效范围 [-180, 180],当前值: " + lon);
+            }
+            if (lat < -90 || lat > 90) {
+                return R.fail("纬度参数超出有效范围 [-90, 90],当前值: " + lat);
+            }
+
+            // 调用服务层获取筛选结果
+            IPage<StoreInfoVo> result = storeInfoService.getSpecialTypeStoresByDistance(lon, lat, distance, sortType, businessType, categoryId, storeName,storeType, pageNum, pageSize);
+
+            // 记录响应日志
+            log.info("四种类型店铺距离筛选响应 - 总记录数: {}, 当前页: {}, 页大小: {}",
+                    result.getTotal(), result.getCurrent(), result.getSize());
+
+            return R.data(result);
+        } catch (IllegalArgumentException e) {
+            log.warn("四种类型店铺距离筛选参数错误: {}", e.getMessage());
+            return R.fail(e.getMessage());
+        } catch (Exception e) {
+            log.error("四种类型店铺距离筛选异常", e);
+            return R.fail("筛选失败,请稍后重试");
+        }
+    }
+
+
+
+    /**
+     * 获取休闲娱乐分类数据(主分类和子分类)
+     * 根据图片需求,返回层级结构的分类数据
+     *
+     * @return R<List<StoreDictionaryVo>> 分类列表,包含主分类和子分类
+     */
+    @ApiOperation("获取休闲娱乐分类数据(主分类和子分类)")
+    @ApiOperationSupport(order = 18)
+    @GetMapping("/getLeisureEntertainmentCategories")
+    public R<List<StoreDictionaryVo>> getLeisureEntertainmentCategories() {
+        log.info("StoreInfoController.getLeisureEntertainmentCategories");
+        try {
+            List<StoreDictionaryVo> result = storeInfoService.getLeisureEntertainmentCategories();
+            return R.data(result);
+        } catch (Exception e) {
+            log.error("获取休闲娱乐分类数据异常", e);
+            return R.fail("获取分类数据失败,请稍后重试");
+        }
+    }
+
+    /**
+     * 获取休闲娱乐分类数据(主分类和子分类)
+     * 根据图片需求,返回层级结构的分类数据
+     *getAllBusinessSection
+     * @return R<List<StoreDictionary>> 分类列表,包含主分类和子分类
+     */
+
+
+    @ApiOperation("获取所有经营板块以及子类")
+    @ApiOperationSupport(order = 18)
+    @GetMapping("/getAllBusinessSection")
+    public R<List<StoreDictionary>> queryBusinessSectionTree(
+            @ApiParam(value = "一级分类dictId,可选,如果传入则只返回该一级分类下的二级和三级分类", required = false)
+            @RequestParam(required = false) String businessSection) {
+        log.info("platformBusinessSection.queryBusinessSectionTree, businessSection={}", businessSection);
+
+        try {
+            List<StoreDictionary> result = storeInfoService.getAllBusinessSection(businessSection);
+            return R.data(result);
+        }catch (Exception e){
+            log.error("获取休闲娱乐分类数据异常", e);
+            return R.fail("获取分类数据失败,请稍后重试");
+        }
+
+    }
+
+
+
+    /**
+     * 你可能还喜欢(推荐店铺)
+     * 根据一级分类、二级分类、三级分类进行店铺筛选
+     * 筛选顺序:先三级,然后二级,最后一级
+     *
+     * @param businessSection 一级分类(经营板块)
+     * @param businessTypes 二级分类(经营种类)
+     * @param businessClassify 三级分类(分类)
+     * @param lon 经度
+     * @param lat 纬度
+     * @return R<List<StoreInfoVo>> 店铺信息列表
+     */
+    @ApiOperation("你可能还喜欢(推荐店铺)")
+    @ApiOperationSupport(order = 19)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "businessSection", value = "一级分类(经营板块)", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "businessTypes", value = "二级分类(经营种类)", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "businessClassify", value = "三级分类(分类)", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "lon", value = "经度", dataType = "Double", paramType = "query"),
+            @ApiImplicitParam(name = "lat", value = "纬度", dataType = "Double", paramType = "query")
+    })
+    @GetMapping("/getRecommendedStores")
+    public R<List<StoreInfoVo>> getRecommendedStores(
+            @RequestParam(value = "businessSection", required = true) String businessSection,
+            @RequestParam(value = "businessTypes", required = false) String businessTypes,
+            @RequestParam(value = "businessClassify", required = false) String businessClassify,
+            @RequestParam(value = "lon", required = false) Double lon,
+            @RequestParam(value = "lat", required = false) Double lat) {
+        log.info("StoreInfoController.getRecommendedStores?businessSection={},businessTypes={},businessClassify={},lon={},lat={}",
+                businessSection, businessTypes, businessClassify, lon, lat);
+        try {
+            List<StoreInfoVo> result = storeInfoService.getRecommendedStores(businessSection, businessTypes, businessClassify, lon, lat);
+            return R.data(result);
+        } catch (Exception e) {
+            log.error("获取推荐店铺异常", e);
+            return R.fail("获取推荐店铺失败,请稍后重试");
+        }
+    }
+    /**
+     * 根据business_classify字段获取字典表数据实现UI图中的功能
+     * RESTful风格:GET /store/info/business-classifies
+     * 返回扁平化的分类列表,用于多选分类功能
+     *
+     * @param parentId 父分类ID(可选),如果提供则只返回该父分类下的子分类
+     * @return R<List<StoreDictionaryVo>> 分类列表(扁平化,仅子分类)
+     */
+    @ApiOperation("获取店铺分类信息)")
+    @ApiOperationSupport(order = 19)
+    @GetMapping("/business-classifies")
+    public R<List<StoreDictionaryVo>> getBusinessClassifyData(
+            @RequestParam(value = "parentId", required = false) Integer parentId) {
+        log.info("StoreInfoController.getBusinessClassifyData?parentId={}", parentId);
+        try {
+            List<StoreDictionaryVo> result = storeInfoService.getBusinessClassifyData(parentId);
+            return R.data(result);
+        } catch (Exception e) {
+            log.error("获取business_classify分类数据异常", e);
+            return R.fail("获取分类数据失败,请稍后重试");
+        }
+    }
+
+
+    @ApiOperation(value = "获取banner图详情")
+    @ApiOperationSupport(order = 7)
+    @GetMapping("/getBannerUrlInfo")
+    @ResponseBody
+    public R getBannerUrlInfo(@RequestParam("storeId") String storeId, @RequestParam("businessId") Integer businessId) {
+        log.info("StoreInfoController.getBannerUrlInfo?storeId={},businessId{}", storeId, businessId);
+
+        try {
+
+            return R.data(storeInfoService.getBannerUrlInfo(storeId, businessId));
+
+        } catch (Exception e) {
+
+            log.error("StoreInfoController.getBannerUrlInfo ERROR Msg={}", e.getMessage(), e);
+
+            return R.fail("查询失败");
+        }
+
+    }
+
+
+    /**
+     * 查询两种类型店铺(丽人美发、运动健身)并按距离筛选
+     *
+     * @param lon         经度
+     * @param lat         纬度
+     * @param distance    距离范围(单位:公里)
+     * @param sortType    排序模式(1:智能排序,2:好评优先,3:距离优先)
+     * @param businessType 店铺类型(KTV=3、洗浴汗蒸=4、按摩足浴=5,丽人美发=6,运动健身=7),可选,如果指定则只查询该类型
+     * @param pageNum     页码
+     * @param pageSize    页容
+     * @return R<IPage<StoreInfoVo>> 分页的门店信息列表
+     */
+    @ApiOperation("查询两种类型店铺(丽人美发、运动健身)并按距离筛选")
+    @ApiOperationSupport(order = 16)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "lon", value = "经度", dataType = "Double", paramType = "query", required = true),
+            @ApiImplicitParam(name = "lat", value = "纬度", dataType = "Double", paramType = "query", required = true),
+            @ApiImplicitParam(name = "distance", value = "距离范围(单位:公里)", dataType = "Double", paramType = "query"),
+            @ApiImplicitParam(name = "sortType", value = "排序模式(1:智能排序,2:好评优先,3:距离优先)", dataType = "int", paramType = "query"),
+            @ApiImplicitParam(name = "businessType", value = "店铺类型(KTV=3、洗浴汗蒸=4、按摩足浴=5,丽人美发=6,运动健身=7,酒吧=11)", dataType = "int", paramType = "query"),
+            @ApiImplicitParam(name = "categoryId", value = "字典表id,根据此id查询经营板块、经营种类、分类并匹配店铺", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "storeName", value = "商家名称(模糊查询)", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "pageNum", value = "页码", dataType = "int", paramType = "query", required = true),
+            @ApiImplicitParam(name = "pageSize", value = "页容", dataType = "int", paramType = "query", required = true)
+    })
+    @GetMapping("/getLifeServicesByDistance")
+    public R<IPage<StoreInfoVo>> getLifeServicesByDistance(
+            @RequestParam("lon") Double lon,
+            @RequestParam("lat") Double lat,
+            @RequestParam(value = "distance", required = false) Double distance,
+            @RequestParam(value = "sortType", required = false, defaultValue = "1") Integer sortType,
+            @RequestParam(value = "businessType", required = false) Integer businessType,
+            @RequestParam(value = "categoryId", required = false) Integer categoryId,
+            @RequestParam(value = "storeName", required = false) String storeName,
+            @RequestParam(defaultValue = "1") int pageNum,
+            @RequestParam(defaultValue = "10") int pageSize) {
+        log.info("StoreInfoController.getLifeServicesByDistance?lon={},lat={},distance={},sortType={},businessType={},categoryId={},storeName={},pageNum={},pageSize={}",
+                lon, lat, distance, sortType, businessType, categoryId, storeName, pageNum, pageSize);
+
+        try {
+            // 参数校验:经度范围 [-180, 180],纬度范围 [-90, 90]
+            if (lon == null || lat == null) {
+                return R.fail("经纬度参数不能为空");
+            }
+
+            // 智能检测:如果参数可能传反了(lat超出范围但lon在范围内),给出提示
+            if (Math.abs(lat) > 90 && Math.abs(lon) <= 90) {
+                return R.fail(String.format("参数可能传反了!当前值: lon=%s, lat=%s。经度范围: [-180, 180],纬度范围: [-90, 90]。请检查参数顺序。", lon, lat));
+            }
+
+            if (lon < -180 || lon > 180) {
+                return R.fail("经度参数超出有效范围 [-180, 180],当前值: " + lon);
+            }
+            if (lat < -90 || lat > 90) {
+                return R.fail("纬度参数超出有效范围 [-90, 90],当前值: " + lat);
+            }
+
+            // 调用服务层获取筛选结果
+            IPage<StoreInfoVo> result = storeInfoService.getLifeServicesByDistance(lon, lat, distance, sortType, businessType, categoryId, storeName, pageNum, pageSize);
+
+            // 记录响应日志
+            log.info("四种类型店铺距离筛选响应 - 总记录数: {}, 当前页: {}, 页大小: {}",
+                    result.getTotal(), result.getCurrent(), result.getSize());
+
+            return R.data(result);
+        } catch (IllegalArgumentException e) {
+            log.warn("四种类型店铺距离筛选参数错误: {}", e.getMessage());
+            return R.fail(e.getMessage());
+        } catch (Exception e) {
+            log.error("四种类型店铺距离筛选异常", e);
+            return R.fail("筛选失败,请稍后重试");
+        }
+    }
+
+
 }

+ 84 - 5
alien-store/src/main/java/shop/alien/store/controller/StoreMenuController.java

@@ -10,6 +10,7 @@ import shop.alien.entity.store.vo.StoreMenuVo;
 import shop.alien.store.service.StoreMenuService;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * 二期-门店菜单Controller
@@ -32,13 +33,19 @@ public class StoreMenuController {
     @ApiOperationSupport(order = 1)
     @ApiImplicitParams({
             @ApiImplicitParam(name = "storeId", value = "门店id", dataType = "Integer", paramType = "query", required = true),
-            @ApiImplicitParam(name = "dishType", value = "菜品类型, 0:菜单, 1:推荐", dataType = "Integer", paramType = "query"),
-            @ApiImplicitParam(name = "phoneId", value = "消息标识", dataType = "Integer", paramType = "query")
+            @ApiImplicitParam(name = "dishType", value = "菜品类型, 0:非推荐, 1:推荐", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "phoneId", value = "用户手机号", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "dishMenuType", value = "菜单类型:1-菜单,2-酒水", dataType = "String", paramType = "query")
     })
     @GetMapping("/getMenuByStoreId")
-    public R<List<StoreMenuVo>> getMenuByStoreId(Integer storeId, Integer dishType, String phoneId) {
-        log.info("StoreRecommendController.getByStoreId?id={}&dishType={}&phoneId={}", storeId, dishType, phoneId);
-        return R.data(storeMenuService.getStoreMenu(storeId, dishType, phoneId));
+    public R<List<StoreMenuVo>> getMenuByStoreId(
+            @RequestParam(value = "storeId", required = true) Integer storeId,
+            @RequestParam(value = "dishType", required = false) Integer dishType,
+            @RequestParam(value = "phoneId", required = false) String phoneId,
+            @RequestParam(value = "dishMenuType", required = false) Integer dishMenuType) {
+        log.info("StoreMenuController.getMenuByStoreId?storeId={}&dishType={}&phoneId={}&dishMenuType={}",
+                storeId, dishType, phoneId, dishMenuType);
+        return R.data(storeMenuService.getStoreMenu(storeId, dishType, phoneId, dishMenuType));
     }
 
     @ApiOperation("新增或修改门店菜单")
@@ -116,4 +123,76 @@ public class StoreMenuController {
         log.info("StoreRecommendController.getMenuLikeStatus?userId={}&menuId={}", userId, menuId);
         return R.data(storeMenuService.getMenuLikeStatus(userId, menuId));
     }
+
+
+    /**
+     * 获取菜单(用户端)
+     * <p>
+     * 根据门店ID获取菜单列表,支持按菜品类型、菜单类型筛选,并可查询用户点赞状态
+     * 返回菜单列表以及按四种组合统计的数量:
+     * 1. menu_all: dish_menu_type=1(菜单),dish_type=0(全部)
+     * 2. menu_recommend: dish_menu_type=1(菜单),dish_type=1(推荐)
+     * 3. drink_all: dish_menu_type=2(酒水),dish_type=0(全部)
+     * 4. drink_recommend: dish_menu_type=2(酒水),dish_type=1(推荐)
+     * </p>
+     *
+     * @param storeId      门店ID,必填,必须大于0
+     * @param dishType     菜品类型,可选,0:非推荐, 1:推荐
+     * @param phoneId      用户手机号,可选,用于查询点赞状态
+     * @param dishMenuType 菜单类型,可选,1-菜单,2-酒水
+     * @return 统一返回结果,包含菜单列表和统计信息(list:菜单列表,count:按四种组合统计的数量)
+     * @throws IllegalArgumentException 当门店ID为空或小于等于0时抛出
+     */
+    @ApiOperation("获取菜单(用户端)")
+    @ApiOperationSupport(order = 9)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店id", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "dishType", value = "菜品类型, 0:(推荐+非推荐), 1:推荐", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "phoneId", value = "用户手机号", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "dishMenuType", value = "菜单类型:1-菜,2-酒,不传就是菜+酒(页面叫酒水)", dataType = "Integer", paramType = "query")
+    })
+    @GetMapping("/getClientMenuByStoreId")
+    public R<Map<String, Object>> getClientMenuByStoreId(
+            @RequestParam(value = "storeId", required = true) Integer storeId,
+            @RequestParam(value = "dishType", required = false) Integer dishType,
+            @RequestParam(value = "phoneId", required = true) String phoneId,
+            @RequestParam(value = "dishMenuType", required = false) Integer dishMenuType) {
+        // 记录请求入参
+        log.info("获取用户端菜单,入参:storeId={}, dishType={}, phoneId={}, dishMenuType={}",
+                storeId, dishType, phoneId, dishMenuType);
+
+        // 参数校验
+        if (storeId == null || storeId <= 0) {
+            log.warn("获取用户端菜单失败,门店ID无效:storeId={}", storeId);
+            return R.fail("门店ID不能为空且必须大于0");
+        }
+
+        try {
+            // 调用服务层获取菜单列表和统计信息
+            Map<String, Object> result = storeMenuService.getClientMenuByStoreId(
+                    storeId, dishType, phoneId, dishMenuType);
+
+            // 记录返回结果
+            @SuppressWarnings("unchecked")
+            List<StoreMenuVo> menuList = (List<StoreMenuVo>) result.get("list");
+            log.info("获取用户端菜单成功,门店ID:{},返回菜单数量:{},统计信息:{}",
+                    storeId, menuList != null ? menuList.size() : 0, result.get("count"));
+
+            return R.data(result);
+        } catch (Exception e) {
+            log.error("获取用户端菜单异常,门店ID:{},异常信息:{}", storeId, e.getMessage(), e);
+            return R.fail("获取菜单失败:" + e.getMessage());
+        }
+    }
+
+    @ApiOperation("获取门店菜单详情(用户端)")
+    @ApiOperationSupport(order = 4)
+    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "菜单ID", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "phoneId", value = "用户手机号", dataType = "String", paramType = "query")})
+    @GetMapping("/getClientMenuInfoById")
+    public R<StoreMenuVo> getClientMenuInfoById(@RequestParam(value = "id", required = true) Integer id,
+                                                @RequestParam(value = "phoneId", required = true) String phoneId) {
+        log.info("StoreRecommendController.getClientMenuInfoById?id={},phoneId={}", id, phoneId);
+        return R.data(storeMenuService.getClientMenuInfoById(id, phoneId));
+    }
 }

+ 90 - 4
alien-store/src/main/java/shop/alien/store/controller/StoreOfficialAlbumController.java

@@ -1,9 +1,6 @@
 package shop.alien.store.controller;
 
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiOperationSupport;
-import io.swagger.annotations.ApiSort;
+import io.swagger.annotations.*;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.*;
@@ -11,6 +8,8 @@ import shop.alien.entity.result.R;
 import shop.alien.entity.store.StoreOfficialAlbum;
 import shop.alien.entity.store.vo.StoreOfficialAlbumVo;
 import shop.alien.store.service.StoreOfficialAlbumService;
+import shop.alien.entity.store.vo.StoreAlbumNameVo;
+import shop.alien.entity.store.vo.StoreOfficialAlbumImgVo;
 
 import java.util.List;
 
@@ -59,4 +58,91 @@ public class StoreOfficialAlbumController {
         }
         return R.fail("失败");
     }
+    /**
+     * 获取官方相册图片列表(客户端)
+     * <p>
+     * 根据门店ID和相册名称查询官方相册中的图片列表
+     * 查询条件:imgType = 2(官方相册),通过 business_id 关联到 store_official_album 表,按 albumName 筛选
+     * </p>
+     *
+     * @param storeId   门店ID,必填,必须大于0
+     * @param albumName 相册名称,可选。例如:酒水、餐食、环境、全部等。当为null或空字符串时,查询全部
+     * @return 统一返回结果,包含图片列表和总数
+     * @throws IllegalArgumentException 当门店ID为空或小于等于0时抛出
+     */
+    @ApiOperation("获取官方相册图片列表(客户端)")
+    @ApiOperationSupport(order = 4)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "albumName", value = "相册名称,例如:酒水、餐食、环境、全部等。不传或传空字符串时查询全部", dataType = "String", paramType = "query")
+    })
+    @GetMapping("/getOfficialAlbumImgList")
+    public R<StoreOfficialAlbumImgVo> getOfficialAlbumImgList(
+            @RequestParam(value = "storeId", required = true) Integer storeId,
+            @RequestParam(value = "albumName", required = false) String albumName) {
+        // 记录请求入参
+        log.info("获取官方相册图片列表,入参:storeId={}, albumName={}", storeId, albumName);
+
+        // 参数校验
+        if (storeId == null || storeId <= 0) {
+            log.warn("获取官方相册图片列表失败,门店ID无效:storeId={}", storeId);
+            return R.fail("门店ID不能为空且必须大于0");
+        }
+
+        try {
+            // 调用服务层获取图片列表
+            StoreOfficialAlbumImgVo result = storeOfficialAlbumService.getOfficialAlbumImgList(storeId, albumName);
+
+            // 记录返回结果
+            log.info("获取官方相册图片列表成功,门店ID:{},相册名称:{},返回图片数量:{}",
+                    storeId, albumName, result.getTotalCount());
+
+            return R.data(result);
+        } catch (Exception e) {
+            log.error("获取官方相册图片列表异常,门店ID:{},异常信息:{}", storeId, e.getMessage(), e);
+            return R.fail("获取图片列表失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 获取官方相册名称列表(客户端)
+     * <p>
+     * 根据门店ID查询所有可用的相册名称列表,用于前端展示筛选选项
+     * 返回每个相册名称及其对应的图片数量
+     * </p>
+     *
+     * @param storeId 门店ID,必填,必须大于0
+     * @return 统一返回结果,包含相册名称列表和每个相册的图片数量
+     * @throws IllegalArgumentException 当门店ID为空或小于等于0时抛出
+     */
+    @ApiOperation("获取官方相册名称列表(客户端)")
+    @ApiOperationSupport(order = 5)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/getAlbumNameList")
+    public R<List<StoreAlbumNameVo>> getAlbumNameList(
+            @RequestParam(value = "storeId", required = true) Integer storeId) {
+        // 记录请求入参
+        log.info("获取官方相册名称列表,入参:storeId={}", storeId);
+
+        // 参数校验
+        if (storeId == null || storeId <= 0) {
+            log.warn("获取官方相册名称列表失败,门店ID无效:storeId={}", storeId);
+            return R.fail("门店ID不能为空且必须大于0");
+        }
+
+        try {
+            // 调用服务层获取相册名称列表
+            List<StoreAlbumNameVo> result = storeOfficialAlbumService.getAlbumNameList(storeId);
+
+            // 记录返回结果
+            log.info("获取官方相册名称列表成功,门店ID:{},返回相册数量:{}", storeId, result.size());
+
+            return R.data(result);
+        } catch (Exception e) {
+            log.error("获取官方相册名称列表异常,门店ID:{},异常信息:{}", storeId, e.getMessage(), e);
+            return R.fail("获取相册名称列表失败:" + e.getMessage());
+        }
+    }
 }

+ 87 - 0
alien-store/src/main/java/shop/alien/store/controller/StorePersonnelController.java

@@ -0,0 +1,87 @@
+package shop.alien.store.controller;
+
+import io.swagger.annotations.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.entity.store.StorePersonnel;
+import shop.alien.entity.store.vo.StorePersonnelVo;
+import shop.alien.store.service.StorePersonnelService;
+
+import java.util.List;
+
+/**
+ * 店铺人员Controller
+ *
+ * @author system
+ * @since 2025-01-15
+ */
+@Slf4j
+@Api(tags = {"店铺人员"})
+@ApiSort(5)
+@CrossOrigin
+@RestController
+@RequestMapping("/personnel")
+@RequiredArgsConstructor
+public class StorePersonnelController {
+
+    private final StorePersonnelService storePersonnelService;
+
+    @ApiOperation("获取店铺人员列表")
+    @ApiOperationSupport(order = 1)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店id", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/getPersonnelList")
+    public R<List<StorePersonnelVo>> getPersonnelList(
+            @RequestParam(value = "storeId", required = true) Integer storeId) {
+        log.info("StorePersonnelController.getPersonnelList?storeId={}", storeId);
+        return R.data(storePersonnelService.getStorePersonnelList(storeId));
+    }
+
+    @ApiOperation("获取人员详情")
+    @ApiOperationSupport(order = 2)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "人员id", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/getPersonnelInfo")
+    public R<StorePersonnelVo> getPersonnelInfo(
+            @RequestParam(value = "id", required = true) Integer id) {
+        log.info("StorePersonnelController.getPersonnelInfo?id={}", id);
+        return R.data(storePersonnelService.getPersonnelInfo(id));
+    }
+
+    @ApiOperation("新增或修改店铺人员")
+    @ApiOperationSupport(order = 3)
+    @PostMapping("/saveOrUpdate")
+    public R<String> saveOrUpdate(@RequestBody StorePersonnelVo storePersonnelVo) {
+        log.info("StorePersonnelController.saveOrUpdate?storePersonnelVo={}", storePersonnelVo);
+        return storePersonnelService.saveOrUpdatePersonnel(storePersonnelVo);
+    }
+
+    @ApiOperation("删除店铺人员")
+    @ApiOperationSupport(order = 4)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "ids", value = "人员id列表", dataType = "List<Integer>", paramType = "query", required = true)
+    })
+    @GetMapping("/delete")
+    public R<String> delete(@RequestParam(value = "ids") List<Integer> ids) {
+        log.info("StorePersonnelController.delete?ids={}", ids);
+        return storePersonnelService.deletePersonnel(ids);
+    }
+
+    @ApiOperation("保存人员排序")
+    @ApiOperationSupport(order = 5)
+    @PostMapping("/savePersonnelSort")
+    public R<Boolean> savePersonnelSort(@RequestBody List<StorePersonnel> storePersonnelList) {
+        log.info("StorePersonnelController.savePersonnelSort?storePersonnelList={}", storePersonnelList);
+        Boolean flag = storePersonnelService.savePersonnelSort(storePersonnelList);
+        if (flag) {
+            return R.success("已更新排序");
+        } else {
+            return R.fail("排序失败");
+        }
+    }
+}
+

+ 68 - 0
alien-store/src/main/java/shop/alien/store/controller/StoreStaffConfigController.java

@@ -78,4 +78,72 @@ public class StoreStaffConfigController {
         return R.data(s);
     }
 
+    @ApiOperation("删除员工")
+    @ApiOperationSupport(order = 4)
+    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "主键id", dataType = "Integer", paramType = "query", required = true)})
+    @GetMapping("/deleteStaffConfig")
+    public R<Integer> deleteStaffConfig(Integer id) {
+        log.info("StoreStaffConfigController.deleteStaffConfig?id={}", id);
+        return R.data(storeStaffConfigService.deleteStaffConfig(id));
+    }
+
+    @ApiOperation("置顶员工")
+    @ApiOperationSupport(order = 5)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "主键id", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "topStatus", value = "置顶状态 0-取消置顶, 1-置顶", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/setTopStatus")
+    public R<Integer> setTopStatus(Integer id, Integer topStatus) {
+        log.info("StoreStaffConfigController.setTopStatus?id={},topStatus={}", id, topStatus);
+        return R.data(storeStaffConfigService.setTopStatus(id, topStatus));
+    }
+    /**
+     * 员工列表查询接口(用户端)
+     *
+     * @param page    分页页数
+     * @param size    分页条数
+     * @param storeId 店铺ID
+     * @param status  员工状态
+     * @return 员工列表
+     */
+    @ApiOperation("员工列表查询(用户端)")
+    @ApiOperationSupport(order = 5)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "page", value = "分页页数", dataType = "Integer", paramType = "query", required = false),
+            @ApiImplicitParam(name = "size", value = "分页条数", dataType = "Integer", paramType = "query", required = false),
+            @ApiImplicitParam(name = "storeId", value = "店铺ID", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "status", value = "员工状态(0-待审核 1-审核通过 2-审核拒绝)", dataType = "String", paramType = "query", required = false)
+    })
+    @GetMapping("/queryStaffList")
+    public R<IPage<StoreStaffConfig>> queryStaffList(
+            @RequestParam(value = "page", defaultValue = "1") Integer page,
+            @RequestParam(value = "size", defaultValue = "100") Integer size,
+            @RequestParam(value = "storeId", required = true) Integer storeId,
+            @RequestParam(value = "status", required = false) String status) {
+        log.info("StoreStaffConfigController.queryStaffList?page={}&size={}&storeId={}&status={}", page, size, storeId, status);
+        IPage<StoreStaffConfig> result = storeStaffConfigService.queryStaffList(page, size, storeId, status);
+        return R.data(result);
+    }
+
+    /**
+     * 员工详情查询接口(用户端)
+     *
+     * @param id 员工主键id
+     * @return 员工详情
+     */
+    @ApiOperation("员工详情查询(用户端)")
+    @ApiOperationSupport(order = 6)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "员工主键id", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/queryStaffDetail")
+    public R<StoreStaffConfig> queryStaffDetail(@RequestParam(value = "id", required = true) Integer id) {
+        log.info("StoreStaffConfigController.queryStaffDetail?id={}", id);
+        StoreStaffConfig result = storeStaffConfigService.queryStaffDetail(id);
+        if (result == null) {
+            return R.fail("员工不存在");
+        }
+        return R.data(result);
+    }
 }

+ 88 - 0
alien-store/src/main/java/shop/alien/store/service/BathFacilityServiceService.java

@@ -0,0 +1,88 @@
+package shop.alien.store.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+import shop.alien.entity.store.BathFacilityService;
+import shop.alien.entity.store.vo.BathFacilityServiceCategoryVo;
+import shop.alien.entity.store.vo.BathFacilityServiceVo;
+
+import java.util.List;
+
+/**
+ * 洗浴设施及服务服务接口
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+public interface BathFacilityServiceService extends IService<BathFacilityService> {
+
+    /**
+     * 分页查询洗浴设施及服务列表
+     *
+     * @param pageNum          页码
+     * @param pageSize         页大小
+     * @param storeId          门店ID
+     * @param facilityCategory 设施分类
+     * @return IPage<BathFacilityServiceVo>
+     */
+    IPage<BathFacilityServiceVo> getPageList(Integer pageNum, Integer pageSize, Integer storeId, Integer facilityCategory);
+
+    /**
+     * 查询洗浴设施及服务列表
+     *
+     * @param storeId          门店ID
+     * @param facilityCategory 设施分类
+     * @return List<BathFacilityServiceVo>
+     */
+    List<BathFacilityServiceVo> getList(Integer storeId, Integer facilityCategory);
+
+    /**
+     * 根据ID查询详情
+     *
+     * @param id 主键ID
+     * @return BathFacilityServiceVo
+     */
+    BathFacilityServiceVo getDetail(Integer id);
+
+    /**
+     * 新增洗浴设施及服务
+     *
+     * @param facilityService 设施服务信息
+     * @param imageList       图片列表
+     * @return boolean
+     */
+    boolean saveFacilityService(BathFacilityService facilityService, List<String> imageList);
+
+    /**
+     * 修改洗浴设施及服务
+     *
+     * @param facilityService 设施服务信息
+     * @param imageList       图片列表
+     * @return boolean
+     */
+    boolean updateFacilityService(BathFacilityService facilityService, List<String> imageList);
+
+    /**
+     * 删除洗浴设施及服务
+     *
+     * @param id 主键ID
+     * @return boolean
+     */
+    boolean deleteFacilityService(Integer id);
+
+    /**
+     * 查询指定店铺按分类汇总的设备信息
+     * 包含每个分类的设备数量和设备列表(包括设备信息和图片)
+     *
+     * @param storeId 门店ID
+     * @return List<BathFacilityServiceCategoryVo>
+     */
+    List<BathFacilityServiceCategoryVo> getCategorySummary(Integer storeId);
+
+    IPage<BathFacilityServiceVo> getStorePageList(Integer pageNum, Integer pageSize, Integer storeId, Integer facilityCategory);
+
+    BathFacilityServiceVo getStoreDetail(Integer id);
+
+    List<BathFacilityServiceCategoryVo> getStoreCategorySummary(Integer storeId);
+}
+

+ 116 - 0
alien-store/src/main/java/shop/alien/store/service/DrinkInfoService.java

@@ -0,0 +1,116 @@
+package shop.alien.store.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import shop.alien.entity.store.DrinkInfo;
+import shop.alien.entity.store.vo.DrinkInfoVo;
+
+import java.util.List;
+
+/**
+ * 酒水餐食信息表 服务类
+ * 注意:drink_info 表已废弃,现在基于 store_menu 表实现
+ *
+ * @author ssk
+ * @since 2025-06-13
+ */
+public interface DrinkInfoService {
+
+    /**
+     * 分页查询酒水餐食列表
+     *
+     * @param page         页码
+     * @param size         页容
+     * @param storeId      门店ID
+     * @param type         类型(1:菜品,2:酒水)
+     * @param category     分类
+     * @param name         名称关键词
+     * @param createUserId 创建人ID(只查询指定用户创建的)
+     * @return IPage<DrinkInfoVo>
+     */
+    IPage<DrinkInfoVo> getDrinkInfoPage(int page, int size, Integer storeId, Integer type, String category, String name, Integer createUserId);
+
+    /**
+     * 根据ID查询酒水餐食详情
+     *
+     * @param id 主键ID
+     * @return DrinkInfoVo
+     */
+    DrinkInfoVo getDrinkInfoById(Integer id);
+
+    /**
+     * 新增酒水餐食
+     *
+     * @param drinkInfo 酒水餐食信息
+     * @return boolean
+     */
+    boolean saveDrinkInfo(DrinkInfo drinkInfo);
+
+    /**
+     * 修改酒水餐食
+     *
+     * @param drinkInfo 酒水餐食信息
+     * @return boolean
+     */
+    boolean updateDrinkInfo(DrinkInfo drinkInfo);
+
+    /**
+     * 删除酒水餐食(软删除)
+     *
+     * @param id 主键ID
+     * @return boolean
+     */
+    boolean deleteDrinkInfo(Integer id);
+
+    /**
+     * 上下架酒水餐食
+     *
+     * @param id     主键ID
+     * @param status 状态(0:下架, 1:上架)
+     * @return boolean
+     */
+    boolean updateStatus(Integer id, Integer status);
+
+    /**
+     * 设置酒水餐食推荐
+     *
+     * @param id            主键ID
+     * @param isRecommended 是否推荐(0:否, 1:是)
+     * @return boolean
+     */
+    boolean updateIsRecommended(Integer id, Integer isRecommended);
+
+    /**
+     * 更新酒水餐食排序
+     *
+     * @param id   主键ID
+     * @param sort 排序值
+     * @return boolean
+     */
+    boolean updateSort(Integer id, Integer sort);
+
+    /**
+     * 根据门店ID查询所有酒水餐食
+     *
+     * @param storeId 门店ID
+     * @param type    类型(1:菜品,2:酒水)
+     * @return List<DrinkInfoVo>
+     */
+    List<DrinkInfoVo> getDrinkInfoListByStoreId(Integer storeId, Integer type);
+
+    /**
+     * 查询推荐酒水餐食列表
+     *
+     * @param storeId      门店ID
+     * @param createUserId 创建人ID(只查询指定用户创建的)
+     * @return List<DrinkInfoVo>
+     */
+    List<DrinkInfoVo> getRecommendedList(Integer storeId, Integer createUserId);
+
+    /**
+     * 批量更新酒水餐食排序
+     *
+     * @param drinkInfoList 酒水餐食列表(包含id和sort字段)
+     * @return boolean
+     */
+    boolean batchUpdateSort(List<DrinkInfo> drinkInfoList);
+}

+ 49 - 44
alien-store/src/main/java/shop/alien/store/service/LifeCommentService.java

@@ -54,6 +54,7 @@ public class LifeCommentService {
         updateWrapper.eq(LifeLikeRecord::getType, type);
         updateWrapper.eq(LifeLikeRecord::getDianzanId, userId);
         updateWrapper.eq(LifeLikeRecord::getHuifuId, huifuId);
+        updateWrapper.eq(LifeLikeRecord::getDeleteFlag, 0);
         List<LifeLikeRecord> record = lifeLikeRecordMapper.selectList(updateWrapper);
         if (CollectionUtils.isEmpty(record)) {
             LifeLikeRecord lifeLikeRecord = new LifeLikeRecord();
@@ -62,39 +63,40 @@ public class LifeCommentService {
             lifeLikeRecord.setDianzanId(userId);
             lifeLikeRecord.setType(type);
             lifeLikeRecordMapper.insert(lifeLikeRecord);
-        }
-        if ("1".equals(type)) {
-            LambdaUpdateWrapper<StoreComment> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
-            lambdaUpdateWrapper.eq(StoreComment::getId, huifuId);
-            lambdaUpdateWrapper.setSql("like_count = like_count + 1");
-            return storeCommentMapper.update(null, lambdaUpdateWrapper);
-        } else if ("2".equals(type)) {
-            LambdaUpdateWrapper<LifeUserDynamics> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
-            lambdaUpdateWrapper.eq(LifeUserDynamics::getId, huifuId);
-            lambdaUpdateWrapper.setSql("dianzan_count = dianzan_count + 1");
-            int num = lifeUserDynamicsMapper.update(null, lambdaUpdateWrapper);
-            if (num > 0) insertNotice(userId, huifuId, type);
-            return num;
-        } else if ("3".equals(type)) {
-            LambdaUpdateWrapper<LifeActivity> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
-            lambdaUpdateWrapper.eq(LifeActivity::getId, huifuId);
-            lambdaUpdateWrapper.setSql("dianzan_count = dianzan_count + 1");
-            return lifeActivityMapper.update(null, lambdaUpdateWrapper);
-        } else if ("4".equals(type)) {
-            LambdaUpdateWrapper<StoreMenu> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
-            lambdaUpdateWrapper.eq(StoreMenu::getId, huifuId);
-            lambdaUpdateWrapper.setSql("like_count = like_count + 1");
-            return storeRecommendMapper.update(null, lambdaUpdateWrapper);
-        } else if ("5".equals(type)) {
-            LambdaUpdateWrapper<StoreClockIn> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
-            lambdaUpdateWrapper.eq(StoreClockIn::getId, huifuId);
-            lambdaUpdateWrapper.setSql("like_count = like_count + 1");
-            return storeClockInMapper.update(null, lambdaUpdateWrapper);
-        } else if ("6".equals(type)) {
-            LambdaUpdateWrapper<SecondGoods> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
-            lambdaUpdateWrapper.eq(SecondGoods::getId, huifuId);
-            lambdaUpdateWrapper.setSql("like_count = like_count + 1");
-            return secondGoodsMapper.update(null, lambdaUpdateWrapper);
+
+            if ("1".equals(type)) {
+                LambdaUpdateWrapper<StoreComment> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
+                lambdaUpdateWrapper.eq(StoreComment::getId, huifuId);
+                lambdaUpdateWrapper.setSql("like_count = like_count + 1");
+                return storeCommentMapper.update(null, lambdaUpdateWrapper);
+            } else if ("2".equals(type)) {
+                LambdaUpdateWrapper<LifeUserDynamics> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
+                lambdaUpdateWrapper.eq(LifeUserDynamics::getId, huifuId);
+                lambdaUpdateWrapper.setSql("dianzan_count = dianzan_count + 1");
+                int num = lifeUserDynamicsMapper.update(null, lambdaUpdateWrapper);
+                if (num > 0) insertNotice(userId, huifuId, type);
+                return num;
+            } else if ("3".equals(type)) {
+                LambdaUpdateWrapper<LifeActivity> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
+                lambdaUpdateWrapper.eq(LifeActivity::getId, huifuId);
+                lambdaUpdateWrapper.setSql("dianzan_count = dianzan_count + 1");
+                return lifeActivityMapper.update(null, lambdaUpdateWrapper);
+            } else if ("4".equals(type)) {
+                LambdaUpdateWrapper<StoreMenu> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
+                lambdaUpdateWrapper.eq(StoreMenu::getId, huifuId);
+                lambdaUpdateWrapper.setSql("like_count = like_count + 1");
+                return storeRecommendMapper.update(null, lambdaUpdateWrapper);
+            } else if ("5".equals(type)) {
+                LambdaUpdateWrapper<StoreClockIn> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
+                lambdaUpdateWrapper.eq(StoreClockIn::getId, huifuId);
+                lambdaUpdateWrapper.setSql("like_count = like_count + 1");
+                return storeClockInMapper.update(null, lambdaUpdateWrapper);
+            } else if ("6".equals(type)) {
+                LambdaUpdateWrapper<SecondGoods> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
+                lambdaUpdateWrapper.eq(SecondGoods::getId, huifuId);
+                lambdaUpdateWrapper.setSql("like_count = like_count + 1");
+                return secondGoodsMapper.update(null, lambdaUpdateWrapper);
+            }
         }
         return 0;
     }
@@ -117,17 +119,19 @@ public class LifeCommentService {
     }
 
     public int cancelLike(String userId, String huifuId, String type) {
-        LambdaUpdateWrapper<LifeLikeRecord> updateWrapper = new LambdaUpdateWrapper<>();
-        updateWrapper.eq(LifeLikeRecord::getDianzanId, userId);
-        updateWrapper.eq(LifeLikeRecord::getHuifuId, huifuId);
-        List<LifeLikeRecord> record = lifeLikeRecordMapper.selectList(updateWrapper);
+        LambdaQueryWrapper<LifeLikeRecord> lifeLikeRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
+        lifeLikeRecordLambdaQueryWrapper.eq(LifeLikeRecord::getDianzanId, userId);
+        lifeLikeRecordLambdaQueryWrapper.eq(LifeLikeRecord::getHuifuId, huifuId);
+        lifeLikeRecordLambdaQueryWrapper.eq(LifeLikeRecord::getType, type);
+        lifeLikeRecordLambdaQueryWrapper.eq(LifeLikeRecord::getDeleteFlag, 0);
+        List<LifeLikeRecord> record = lifeLikeRecordMapper.selectList(lifeLikeRecordLambdaQueryWrapper);
         if (!CollectionUtils.isEmpty(record)) {
-            LambdaUpdateWrapper<LifeLikeRecord> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
-            lambdaUpdateWrapper.eq(LifeLikeRecord::getHuifuId, huifuId);
-            lambdaUpdateWrapper.eq(LifeLikeRecord::getDianzanId, userId);
-            lambdaUpdateWrapper.eq(LifeLikeRecord::getType, type);
-            lifeLikeRecordMapper.delete(lambdaUpdateWrapper);
-        }
+            LambdaUpdateWrapper<LifeLikeRecord> lifeLikeRecordLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
+            lifeLikeRecordLambdaUpdateWrapper.eq(LifeLikeRecord::getHuifuId, huifuId);
+            lifeLikeRecordLambdaUpdateWrapper.eq(LifeLikeRecord::getDianzanId, userId);
+            lifeLikeRecordLambdaUpdateWrapper.eq(LifeLikeRecord::getType, type);
+            lifeLikeRecordMapper.delete(lifeLikeRecordLambdaUpdateWrapper);
+
         if ("1".equals(type)) {
             LambdaUpdateWrapper<StoreComment> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
             lambdaUpdateWrapper.eq(StoreComment::getId, huifuId).gt(StoreComment::getLikeCount, 0);
@@ -159,8 +163,9 @@ public class LifeCommentService {
             lambdaUpdateWrapper.setSql("like_count = like_count - 1");
             return secondGoodsMapper.update(null, lambdaUpdateWrapper);
         }
-        return 0;
     }
+        return 0;
+}
 
     public int addOrUpdateStore(LifeComment store) {
         if (StringUtils.isEmpty(store.getId())) {

+ 7 - 0
alien-store/src/main/java/shop/alien/store/service/LifeCouponService.java

@@ -56,4 +56,11 @@ public interface LifeCouponService extends IService<LifeCoupon> {
      * @return
      */
     R<String> orderVerify(String orderCode);
+
+    /**
+     * 获取代金券详情(包含商铺信息)
+     * @param id 代金券ID
+     * @return LifeCouponVo
+     */
+    shop.alien.entity.store.vo.LifeCouponVo getNewCouponDetail(String id);
 }

+ 1 - 1
alien-store/src/main/java/shop/alien/store/service/LifeUserDynamicsService.java

@@ -250,7 +250,7 @@ public class LifeUserDynamicsService extends ServiceImpl<LifeUserDynamicsMapper,
             // 查询拉黑的对象
             LambdaQueryWrapper<LifeBlacklist> myLifeBlacklistWrapper = new LambdaQueryWrapper<>();
 
-            if (null != myLifeUser.getId()) {
+            if (null != myLifeUser && null != myLifeUser.getId()) {
                 myLifeBlacklistWrapper.eq(LifeBlacklist::getBlockerType, "2");
                 myLifeBlacklistWrapper.eq(LifeBlacklist::getBlockerId, myLifeUser.getId());
             } else {

+ 5 - 0
alien-store/src/main/java/shop/alien/store/service/LifeUserStoreService.java

@@ -135,7 +135,12 @@ public class LifeUserStoreService {
                 storeMap.put("businessStatusStr", store.getBusinessStatusStr());
 
                 //474bug
+                storeMap.put("businessSection", store.getBusinessSection());
+                storeMap.put("businessSectionName", store.getBusinessSectionName());
+                storeMap.put("businessTypes", store.getBusinessTypes());
                 storeMap.put("businessTypesName", store.getBusinessTypesName());
+                storeMap.put("businessClassify", store.getBusinessClassify());
+                storeMap.put("businessClassifyName", store.getBusinessClassifyName());
                 storeMap.put("storeBusinessInfo", storeBusinessInfo);
                 // 添加门店ID
                 storeMap.put("storeId", store.getId());

+ 44 - 0
alien-store/src/main/java/shop/alien/store/service/OperationalActivityService.java

@@ -0,0 +1,44 @@
+package shop.alien.store.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import shop.alien.entity.storePlatform.vo.StoreOperationalActivityVO;
+
+/**
+ * 运营活动服务接口
+ *
+ * @author system
+ * @since 2025-11-26
+ */
+public interface OperationalActivityService {
+
+    /**
+     * 审核运营活动
+     *
+     * @param id               活动ID
+     * @param status           审核状态(1通过/0驳回等)
+     * @param approvalComments 驳回原因
+     * @return 更新结果
+     */
+    int auditActivity(Integer id, Integer status, String approvalComments);
+
+    /**
+     * 根据门店条件分页查询运营活动
+     *
+     * @param storeId   门店ID
+     * @param storeName 门店名称(模糊)
+     * @param pageNum   页码
+     * @param pageSize  每页数量
+     * @return 活动分页结果
+     */
+    IPage<StoreOperationalActivityVO> pageActivityDetail(Integer storeId, String storeName, Integer pageNum, Integer pageSize);
+
+    /**
+     * 根据活动ID获取活动详情
+     *
+     * @param id 活动ID
+     * @return 活动详情
+     */
+    StoreOperationalActivityVO getActivityDetailById(Integer id);
+
+}
+

+ 97 - 0
alien-store/src/main/java/shop/alien/store/service/SportsEquipmentFacilityService.java

@@ -0,0 +1,97 @@
+package shop.alien.store.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+import shop.alien.entity.store.SportsEquipmentFacility;
+import shop.alien.entity.store.vo.SportsEquipmentFacilityCategoryVo;
+import shop.alien.entity.store.vo.SportsEquipmentFacilityVo;
+
+import java.util.List;
+
+/**
+ * 运动器材设施服务接口
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+public interface SportsEquipmentFacilityService extends IService<SportsEquipmentFacility> {
+
+    /**
+     * 分页查询运动器材设施列表
+     *
+     * @param pageNum          页码
+     * @param pageSize         页大小
+     * @param storeId           门店ID
+     * @param facilityCategory 设施分类
+     * @return IPage<SportsEquipmentFacilityVo>
+     */
+    IPage<SportsEquipmentFacilityVo> getPageList(Integer pageNum, Integer pageSize, Integer storeId, Integer facilityCategory);
+
+    /**
+     * 查询运动器材设施列表
+     *
+     * @param storeId           门店ID
+     * @param facilityCategory 设施分类
+     * @return List<SportsEquipmentFacilityVo>
+     */
+    List<SportsEquipmentFacilityVo> getList(Integer storeId, Integer facilityCategory);
+
+    /**
+     * 根据ID查询详情
+     *
+     * @param id 主键ID
+     * @return SportsEquipmentFacilityVo
+     */
+    SportsEquipmentFacilityVo getDetail(Integer id);
+
+    /**
+     * 新增运动器材设施
+     *
+     * @param facility 设施信息
+     * @param imageList 图片列表
+     * @return boolean
+     */
+    boolean saveFacility(SportsEquipmentFacility facility, List<String> imageList);
+
+    /**
+     * 修改运动器材设施
+     *
+     * @param facility 设施信息
+     * @param imageList 图片列表
+     * @return boolean
+     */
+    boolean updateFacility(SportsEquipmentFacility facility, List<String> imageList);
+
+    /**
+     * 删除运动器材设施
+     *
+     * @param id 主键ID
+     * @return boolean
+     */
+    boolean deleteFacility(Integer id);
+
+    /**
+     * 查询指定店铺按分类汇总的设备信息
+     * 包含每个分类的设备数量、图片列表和设备列表
+     *
+     * @param storeId 门店ID
+     * @return List<SportsEquipmentFacilityCategoryVo>
+     */
+    List<SportsEquipmentFacilityCategoryVo> getCategorySummary(Integer storeId);
+
+    SportsEquipmentFacilityVo getStoreDetail(Integer id);
+
+    List<SportsEquipmentFacilityCategoryVo> getstoreCategorySummary(Integer storeId);
+
+    /**
+     * 保存分类下的图片
+     * 设施列表通过添加接口已保存,此接口仅保存该分类的实景图片
+     *
+     * @param storeId          门店ID
+     * @param facilityCategory 设施分类(1:有氧区, 2:力量区, 3:单功能机械区)
+     * @param imageList        图片列表
+     * @return boolean
+     */
+    boolean saveCategoryImages(Integer storeId, Integer facilityCategory, List<String> imageList);
+}
+

+ 149 - 6
alien-store/src/main/java/shop/alien/store/service/StoreInfoService.java

@@ -4,10 +4,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.multipart.MultipartRequest;
-import shop.alien.entity.store.StoreBusinessInfo;
-import shop.alien.entity.store.StoreImg;
-import shop.alien.entity.store.StoreInfo;
-import shop.alien.entity.store.StoreInfoDraft;
+import shop.alien.entity.store.*;
 import shop.alien.entity.store.dto.StoreInfoDto;
 import shop.alien.entity.store.vo.*;
 
@@ -141,6 +138,13 @@ public interface StoreInfoService extends IService<StoreInfo> {
     StoreInfoVo editStoreInfo(StoreInfoDto storeInfoDto);
 
     /**
+     * 新中台web端修改门店及门店用户
+     *
+     * @return ResponseEntity
+     */
+    StoreInfoVo editNewStoreInfo(StoreInfoDto storeInfoDto);
+
+    /**
      * web端删除门店及门店用户
      *
      * @return ResponseEntity
@@ -180,6 +184,11 @@ public interface StoreInfoService extends IService<StoreInfo> {
     StoreInfoVo getStoreDetail(String storeId, String userId, String jingdu, String weidu);
 
     /**
+     * 中台web端查询门店明细
+     */
+    StoreInfoVo getNewStoreDetail(String storeId);
+
+    /**
      * web端审批结果
      */
     void approveStoreInfo(String storeId, Integer approvalStatus, String reason);
@@ -294,13 +303,147 @@ public interface StoreInfoService extends IService<StoreInfo> {
     int foodLicenceType(int id);
 
     /**
+     * 店铺娱乐经营许可证
+     * @param storeImg
+     * @return
+     */
+    int uploadEntertainmentLicence(StoreImg storeImg);
+
+    /**
+     * 获取店铺娱乐经营许可证状态以及店铺状态为审核中合同图片list
+     * @param id
+     * @return
+     */
+    Map<String,Object> getStoreEntertainmentLicenceStatus(int id);
+
+    /**
+     * 娱乐经营许可证审核通过后 图片类型变为审核通过后 img_type26
+     *
+     */
+    int entertainmentLicenceType(int id);
+
+    /**
+     * 获取门店代金券
+     */
+    List<LifeCouponVo> getStoreCouponList(String storeId);
+
+
+    /**
+     * 获取活动banner图
+     */
+    List<StoreImg> getBannerUrl (String storeId);
+    /**
+     * 获取活动banner图
+     */
+
+    List<StoreImg> getBannerUrlInfo(String storeId, Integer businessId);
+
+
+    /**
+     * web-分页查询店铺信息
+     *
+
+     * @return IPage<StoreInfoVo>
+     */
+    List<StoreInfoVo> getMoreRecommendedStores(Double lon , Double lat, String businessSection, String businessTypes, String businessClassify);
+
+
+    /**
      * 根据门店及图片地址查询最新OCR识别数据
      *
-     * @param storeUserId  门店ID
      * @param imageUrl 图片URL
      * @return OCR识别记录
      */
-    Map<String, Object> getStoreOcrData(String storeUserId, String imageUrl);
+    Map<String, Object> getStoreOcrData(String imageUrl, String merchantName);
+
+    /**
+     * 查询四种类型店铺(酒吧、ktv、洗浴汗蒸、按摩足浴)并按距离筛选
+     *
+     * @param lon         经度
+     * @param lat         纬度
+     * @param distance    距离范围(单位:公里)
+     * @param sortType    排序模式(1:智能排序,2:好评优先,3:距离优先)
+     * @param businessType 店铺类型(KTV=3、洗浴汗蒸=4、按摩足浴=5,酒吧需要查询字典表),可选
+     * @param categoryId  分类ID(二级或三级分类的dictId,从getAllBusinessSection接口获取),可选
+     * @param storeName   店铺名称(模糊查询),可选
+     * @param pageNum     页码
+     * @param pageSize    页容
+     * @return IPage<StoreInfoVo> 分页的门店信息列表
+     */
+    IPage<StoreInfoVo> getSpecialTypeStoresByDistance(Double lon, Double lat, Double distance, Integer sortType, Integer businessType, Integer categoryId, String storeName,Integer storeType, int pageNum, int pageSize);
+
+    /**
+     * web端查询门店明细
+     */
+    StoreInfoVo getClientStoreDetail(String storeId, String userId, String jingdu, String weidu);
+
+    /**
+     * 获取休闲娱乐分类数据(主分类和子分类)
+     * 返回层级结构的分类数据,包含主分类和对应的子分类
+     *
+     * @return List<StoreDictionaryVo> 分类列表,包含主分类和子分类
+     */
+    List<StoreDictionaryVo> getLeisureEntertainmentCategories();
+
+
+    List<StoreDictionary> getAllBusinessSection();
+
+    /**
+     * 根据一级分类获取该分类下的二级和三级分类
+     *
+     * @param businessSection 一级分类的dictId(可选,如果为空则返回所有分类)
+     * @return List<StoreDictionary> 分类树形结构
+     */
+    List<StoreDictionary> getAllBusinessSection(String businessSection);
+
+    /**
+     * 获取门店下三级分类结构
+     * 根据门店ID查询该门店的经营板块、经营种类和分类的三级结构
+     *
+     * @param storeId 门店ID
+     * @return StoreThreeLevelStructureVo 包含门店信息和三级分类树形结构
+     */
+    StoreThreeLevelStructureVo getStoreThreeLevelStructure(Integer storeId);
+
+    /**
+     * 你可能还喜欢(推荐店铺)
+     * 根据一级分类、二级分类、三级分类进行店铺筛选
+     * 筛选顺序:先三级,然后二级,最后一级
+     *
+     * @param businessSection 一级分类(经营板块)
+     * @param businessTypes 二级分类(经营种类)
+     * @param businessClassify 三级分类(分类)
+     * @param lon 经度
+     * @param lat 纬度
+     * @return List<StoreInfoVo> 店铺信息列表
+     */
+    List<StoreInfoVo> getRecommendedStores(String businessSection, String businessTypes, String businessClassify, Double lon, Double lat);
+
+    /**
+     * 获取三级分类数据
+     * 根据二级分类ID获取该分类下的三级分类
+     *
+     * @param parentId 二级分类ID
+     * @return List<StoreDictionaryVo> 三级分类列表
+     */
+    List<StoreDictionaryVo> getBusinessClassifyData(Integer parentId);
 
     void aiApproveStoreInfo(AiApproveStoreInfo aiApproveStoreInfo);
+
+
+    /**
+     * 查询两种类型店铺(丽人美发、运动健身)并按距离筛选
+     *
+     * @param lon         经度
+     * @param lat         纬度
+     * @param distance    距离范围(单位:公里)
+     * @param sortType    排序模式(1:智能排序,2:好评优先,3:距离优先)
+     * @param businessType 店铺类型(KTV=3、洗浴汗蒸=4、按摩足浴=5,丽人美发=6,运动健身=7),可选,如果指定则只查询该类型
+     * @param categoryId  字典表id,根据此id查询经营板块、经营种类、分类并匹配店铺
+     * @param storeName   商家名称(模糊查询)
+     * @param pageNum     页码
+     * @param pageSize    页容
+     * @return R<IPage<StoreInfoVo>> 分页的门店信息列表
+     */
+    IPage<StoreInfoVo> getLifeServicesByDistance(Double lon, Double lat, Double distance, Integer sortType, Integer businessType, Integer categoryId, String storeName, int pageNum, int pageSize);
 }

+ 32 - 4
alien-store/src/main/java/shop/alien/store/service/StoreMenuService.java

@@ -19,12 +19,14 @@ public interface StoreMenuService extends IService<StoreMenu> {
     /**
      * 获取门店菜单
      *
-     * @param storeId  门店id
-     * @param dishType 菜品类型, 0:菜单, 1:推荐
-     * @param phoneId  消息标识
+     * @param storeId      门店id
+     * @param dishType     菜品类型, 0:非推荐, 1:推荐
+     * @param phoneId      用户手机号
+     * @param dishMenuType 菜单类型:1-菜单,2-酒水
      * @return list
      */
-    List<StoreMenuVo> getStoreMenu(Integer storeId, Integer dishType, String phoneId);
+    List<StoreMenuVo> getStoreMenu(Integer storeId, Integer dishType, String phoneId, Integer dishMenuType);
+
 
     /**
      * 获取菜品详情
@@ -76,5 +78,31 @@ public interface StoreMenuService extends IService<StoreMenu> {
      * @return boolean
      */
     boolean getMenuLikeStatus(String userId, Integer menuId);
+
+
+    /**
+     * 获取门店菜单(客户端)
+     * <p>
+     * 根据门店ID查询菜单列表,支持按菜品类型和菜单类型筛选。
+     * 当查询推荐菜且提供用户手机号时,会批量查询并设置用户的点赞状态。
+     * 最终结果按排序字段升序排列。
+     * </p>
+     *
+     * @param storeId      门店ID,必填,必须大于0
+     * @param dishType     菜品类型,可选,0:非推荐, 1:推荐。当为0时,查询条件中不包含菜品类型限制
+     * @param phoneId      用户手机号,可选,用于查询用户对推荐菜的点赞状态
+     * @param dishMenuType 菜单类型,可选,1-菜单,2-酒水
+     * @return Map包含菜单列表和统计信息:list(菜单列表)、count(按四种组合统计:menu_all、menu_recommend、drink_all、drink_recommend)
+     * @throws IllegalArgumentException 当门店ID为空或小于等于0时抛出
+     */
+    java.util.Map<String, Object> getClientMenuByStoreId(Integer storeId, Integer dishType, String phoneId, Integer dishMenuType);
+
+    /**
+     * 获取菜品详情
+     *
+     * @param id 菜品id
+     * @return StoreMenuVo
+     */
+    StoreMenuVo getClientMenuInfoById(Integer id, String phoneId);
 }
 

+ 27 - 1
alien-store/src/main/java/shop/alien/store/service/StoreOfficialAlbumService.java

@@ -2,6 +2,8 @@ package shop.alien.store.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import shop.alien.entity.store.StoreOfficialAlbum;
+import shop.alien.entity.store.vo.StoreAlbumNameVo;
+import shop.alien.entity.store.vo.StoreOfficialAlbumImgVo;
 import shop.alien.entity.store.vo.StoreOfficialAlbumVo;
 
 import java.util.List;
@@ -13,4 +15,28 @@ public interface StoreOfficialAlbumService extends IService<StoreOfficialAlbum>
     StoreOfficialAlbum createOrUpdateOfficialAlbum(StoreOfficialAlbum storeOfficialAlbum);
     List<StoreOfficialAlbumVo> getOfficialAlbumList(String storeId);
     int deleteOfficialAlbum(List<StoreOfficialAlbum> storeOfficialAlbumList);
-}
+
+    /**
+     * 获取官方相册图片列表(客户端)
+     * <p>
+     * 根据门店ID和相册名称查询官方相册中的图片列表
+     * 查询条件:imgType = 2(官方相册),通过 business_id 关联到 store_official_album 表,按 albumName 筛选
+     * </p>
+     *
+     * @param storeId   门店ID,必填
+     * @param albumName 相册名称,可选。例如:酒水、餐食、环境、全部等。当为null或空字符串时,查询全部
+     * @return 图片列表和总数
+     */
+    StoreOfficialAlbumImgVo getOfficialAlbumImgList(Integer storeId, String albumName);
+
+    /**
+     * 获取官方相册名称列表(客户端)
+     * <p>
+     * 根据门店ID查询所有可用的相册名称列表,用于前端展示筛选选项
+     * </p>
+     *
+     * @param storeId 门店ID,必填
+     * @return 相册名称列表,包含相册名称和图片数量
+     */
+    List<StoreAlbumNameVo> getAlbumNameList(Integer storeId);
+}

+ 58 - 0
alien-store/src/main/java/shop/alien/store/service/StorePersonnelService.java

@@ -0,0 +1,58 @@
+package shop.alien.store.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import shop.alien.entity.result.R;
+import shop.alien.entity.store.StorePersonnel;
+import shop.alien.entity.store.vo.StorePersonnelVo;
+
+import java.util.List;
+
+/**
+ * 店铺人员服务类
+ *
+ * @author system
+ * @since 2025-01-15
+ */
+public interface StorePersonnelService extends IService<StorePersonnel> {
+
+    /**
+     * 获取店铺人员列表
+     *
+     * @param storeId 门店id
+     * @return List<StorePersonnelVo>
+     */
+    List<StorePersonnelVo> getStorePersonnelList(Integer storeId);
+
+    /**
+     * 获取人员详情
+     *
+     * @param id 人员id
+     * @return StorePersonnelVo
+     */
+    StorePersonnelVo getPersonnelInfo(Integer id);
+
+    /**
+     * 新增或修改店铺人员
+     *
+     * @param storePersonnelVo 人员信息
+     * @return R<String>
+     */
+    R<String> saveOrUpdatePersonnel(StorePersonnelVo storePersonnelVo);
+
+    /**
+     * 删除店铺人员
+     *
+     * @param ids 人员id列表
+     * @return R<String>
+     */
+    R<String> deletePersonnel(List<Integer> ids);
+
+    /**
+     * 保存人员排序
+     *
+     * @param storePersonnelList 人员列表
+     * @return Boolean
+     */
+    Boolean savePersonnelSort(List<StorePersonnel> storePersonnelList);
+}
+

+ 37 - 0
alien-store/src/main/java/shop/alien/store/service/StoreStaffConfigService.java

@@ -17,4 +17,41 @@ public interface StoreStaffConfigService {
     StoreStaffConfig getStaffConfigDeatail(Integer id);
 
     String staffConfigExport(String status) throws IOException;
+
+    /**
+     * 删除员工
+     *
+     * @param id
+     * @return
+     */
+    Integer deleteStaffConfig(Integer id);
+
+    /**
+     * 置顶员工
+     *
+     * @param id 员工ID
+     * @param topStatus 置顶状态 0-未置顶, 1-置顶
+     * @return
+     */
+    Integer setTopStatus(Integer id, Integer topStatus);
+
+
+    /**
+     * 员工列表查询
+     *
+     * @param page    分页页数
+     * @param size    分页条数
+     * @param storeId 店铺ID
+     * @param status  员工状态
+     * @return 员工列表
+     */
+    IPage<StoreStaffConfig> queryStaffList(Integer page, Integer size, Integer storeId, String status);
+
+    /**
+     * 员工详情查询
+     *
+     * @param id 员工主键id
+     * @return 员工详情
+     */
+    StoreStaffConfig queryStaffDetail(Integer id);
 }

+ 333 - 0
alien-store/src/main/java/shop/alien/store/service/impl/BathFacilityServiceServiceImpl.java

@@ -0,0 +1,333 @@
+package shop.alien.store.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+import shop.alien.entity.store.BathFacilityService;
+import shop.alien.entity.store.StoreImg;
+import shop.alien.entity.store.vo.BathFacilityServiceCategoryVo;
+import shop.alien.entity.store.vo.BathFacilityServiceVo;
+import shop.alien.mapper.BathFacilityServiceMapper;
+import shop.alien.mapper.StoreImgMapper;
+import shop.alien.store.service.BathFacilityServiceService;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 洗浴设施及服务服务实现类
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+@Transactional(rollbackFor = Exception.class)
+public class BathFacilityServiceServiceImpl extends ServiceImpl<BathFacilityServiceMapper, BathFacilityService>
+        implements BathFacilityServiceService {
+
+    private final BathFacilityServiceMapper facilityServiceMapper;
+    private final StoreImgMapper storeImgMapper;
+
+    /**
+     * 设施分类名称映射
+     */
+    private static final String[] FACILITY_CATEGORY_NAMES = {"", "洗浴区", "汗蒸区", "休闲区", "餐饮区"};
+
+    /**
+     * 洗浴设施及服务图片类型
+     */
+    private static final Integer IMG_TYPE_BATH_FACILITY = 29;
+
+    @Override
+    public IPage<BathFacilityServiceVo> getPageList(Integer pageNum, Integer pageSize, Integer storeId, Integer facilityCategory) {
+        Page<BathFacilityService> page = new Page<>(pageNum, pageSize);
+        LambdaQueryWrapper<BathFacilityService> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(BathFacilityService::getStoreId, storeId);
+        if (facilityCategory != null) {
+            queryWrapper.eq(BathFacilityService::getFacilityCategory, facilityCategory);
+        }
+        queryWrapper.orderByDesc(BathFacilityService::getCreatedTime);
+        IPage<BathFacilityService> facilityServicePage = facilityServiceMapper.selectPage(page, queryWrapper);
+        return facilityServicePage.convert(this::convertToVo);
+    }
+
+    @Override
+    public List<BathFacilityServiceVo> getList(Integer storeId, Integer facilityCategory) {
+        LambdaQueryWrapper<BathFacilityService> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(BathFacilityService::getStoreId, storeId);
+        if (facilityCategory != null) {
+            queryWrapper.eq(BathFacilityService::getFacilityCategory, facilityCategory);
+        }
+        queryWrapper.orderByDesc(BathFacilityService::getCreatedTime);
+        List<BathFacilityService> facilityServiceList = facilityServiceMapper.selectList(queryWrapper);
+        return facilityServiceList.stream().map(this::convertToVo).collect(Collectors.toList());
+    }
+
+    @Override
+    public BathFacilityServiceVo getDetail(Integer id) {
+        BathFacilityService facilityService = facilityServiceMapper.selectById(id);
+        if (facilityService == null) {
+            return null;
+        }
+        return convertToVo(facilityService);
+    }
+
+    @Override
+    public boolean saveFacilityService(BathFacilityService facilityService, List<String> imageList) {
+        // 校验使用时间
+        validateUsageTime(facilityService);
+        // 保存设施服务信息
+        boolean result = this.save(facilityService);
+        if (result && !CollectionUtils.isEmpty(imageList)) {
+            // 保存图片
+            saveImages(facilityService.getId(), facilityService.getStoreId(), imageList);
+        }
+        return result;
+    }
+
+    @Override
+    public boolean updateFacilityService(BathFacilityService facilityService, List<String> imageList) {
+        // 校验使用时间
+        validateUsageTime(facilityService);
+        // 更新设施服务信息
+        boolean result = this.updateById(facilityService);
+        if (result && !CollectionUtils.isEmpty(imageList)) {
+            // 删除旧图片
+            LambdaQueryWrapper<StoreImg> deleteWrapper = new LambdaQueryWrapper<>();
+            deleteWrapper.eq(StoreImg::getBusinessId, facilityService.getId())
+                    .eq(StoreImg::getImgType, IMG_TYPE_BATH_FACILITY);
+            storeImgMapper.delete(deleteWrapper);
+            // 保存新图片
+            saveImages(facilityService.getId(), facilityService.getStoreId(), imageList);
+        }
+        return result;
+    }
+
+    @Override
+    public boolean deleteFacilityService(Integer id) {
+        // 删除图片
+        LambdaQueryWrapper<StoreImg> deleteWrapper = new LambdaQueryWrapper<>();
+        deleteWrapper.eq(StoreImg::getBusinessId, id)
+                .eq(StoreImg::getImgType, IMG_TYPE_BATH_FACILITY);
+        storeImgMapper.delete(deleteWrapper);
+        // 删除设施服务
+        return this.removeById(id);
+    }
+
+    /**
+     * 校验使用时间
+     */
+    private void validateUsageTime(BathFacilityService facilityService) {
+        if (facilityService.getUsageTimeType() == null) {
+            throw new RuntimeException("使用时间类型不能为空");
+        }
+        // 如果选择时间,需要填写开始时间和结束时间
+        if (facilityService.getUsageTimeType() == 1) {
+            if (!StringUtils.hasText(facilityService.getUsageStartTime())
+                    || !StringUtils.hasText(facilityService.getUsageEndTime())) {
+                throw new RuntimeException("选择时间时,开始时间和结束时间不能为空");
+            }
+            // 校验时间格式
+            if (!facilityService.getUsageStartTime().matches("^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$")
+                    || !facilityService.getUsageEndTime().matches("^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$")) {
+                throw new RuntimeException("时间格式错误,请使用HH:mm格式");
+            }
+        }
+    }
+
+    /**
+     * 保存图片
+     */
+    private void saveImages(Integer facilityServiceId, Integer storeId, List<String> imageList) {
+        for (int i = 0; i < imageList.size(); i++) {
+            StoreImg storeImg = new StoreImg();
+            storeImg.setStoreId(storeId);
+            storeImg.setImgType(IMG_TYPE_BATH_FACILITY);
+            storeImg.setBusinessId(facilityServiceId);
+            storeImg.setImgUrl(imageList.get(i));
+            storeImg.setImgSort(i + 1);
+            storeImg.setImgDescription("洗浴设施及服务图片");
+            storeImgMapper.insert(storeImg);
+        }
+    }
+
+    /**
+     * 转换为VO对象
+     */
+    private BathFacilityServiceVo convertToVo(BathFacilityService facilityService) {
+        BathFacilityServiceVo vo = new BathFacilityServiceVo();
+        BeanUtils.copyProperties(facilityService, vo);
+        // 设置分类名称
+        if (facilityService.getFacilityCategory() != null && facilityService.getFacilityCategory() > 0
+                && facilityService.getFacilityCategory() < FACILITY_CATEGORY_NAMES.length) {
+            vo.setFacilityCategoryName(FACILITY_CATEGORY_NAMES[facilityService.getFacilityCategory()]);
+        }
+        // 设置使用时间类型文本
+        if (facilityService.getUsageTimeType() != null) {
+            vo.setUsageTimeTypeText(facilityService.getUsageTimeType() == 0 ? "全天" : "选择时间");
+            // 设置使用时间范围
+            if (facilityService.getUsageTimeType() == 1
+                    && StringUtils.hasText(facilityService.getUsageStartTime())
+                    && StringUtils.hasText(facilityService.getUsageEndTime())) {
+                vo.setUsageTimeRange(facilityService.getUsageStartTime() + "-" + facilityService.getUsageEndTime());
+            }
+        }
+        // 设置显示状态文本
+        if (facilityService.getDisplayInStoreDetail() != null) {
+            vo.setDisplayInStoreDetailText(facilityService.getDisplayInStoreDetail() == 1 ? "显示" : "隐藏");
+        }
+        // 查询图片列表
+        LambdaQueryWrapper<StoreImg> imageWrapper = new LambdaQueryWrapper<>();
+        imageWrapper.eq(StoreImg::getBusinessId, facilityService.getId())
+                .eq(StoreImg::getImgType, IMG_TYPE_BATH_FACILITY);
+        imageWrapper.orderByAsc(StoreImg::getImgSort);
+        List<StoreImg> imageList = storeImgMapper.selectList(imageWrapper);
+        if (!CollectionUtils.isEmpty(imageList)) {
+            vo.setImageList(imageList.stream().map(StoreImg::getImgUrl)
+                    .collect(Collectors.toList()));
+        } else {
+            vo.setImageList(new ArrayList<>());
+        }
+        return vo;
+    }
+
+    @Override
+    public List<BathFacilityServiceCategoryVo> getCategorySummary(Integer storeId) {
+        List<BathFacilityServiceCategoryVo> result = new ArrayList<>();
+        
+        // 遍历所有分类(1:洗浴区, 2:汗蒸区, 3:休闲区, 4:餐饮区)
+        for (int category = 1; category < FACILITY_CATEGORY_NAMES.length; category++) {
+            BathFacilityServiceCategoryVo categoryVo = new BathFacilityServiceCategoryVo();
+            categoryVo.setFacilityCategory(category);
+            categoryVo.setFacilityCategoryName(FACILITY_CATEGORY_NAMES[category]);
+            
+            // 查询该分类下的设备列表(不分页)
+            LambdaQueryWrapper<BathFacilityService> facilityWrapper = new LambdaQueryWrapper<>();
+            facilityWrapper.eq(BathFacilityService::getStoreId, storeId)
+                    .eq(BathFacilityService::getFacilityCategory, category);
+            facilityWrapper.orderByDesc(BathFacilityService::getCreatedTime);
+            List<BathFacilityService> facilityServiceList = facilityServiceMapper.selectList(facilityWrapper);
+            
+            // 设置设备数量
+            categoryVo.setFacilityCount(facilityServiceList != null ? facilityServiceList.size() : 0);
+            
+            // 查询该分类的代表图片(从第一个设备的第一张图片获取)
+            if (!CollectionUtils.isEmpty(facilityServiceList)) {
+                BathFacilityService firstFacility = facilityServiceList.get(0);
+                // 查询该设备的第一张图片
+                LambdaQueryWrapper<StoreImg> imageWrapper = new LambdaQueryWrapper<>();
+                imageWrapper.eq(StoreImg::getStoreId, storeId)
+                        .eq(StoreImg::getBusinessId, firstFacility.getId())
+                        .eq(StoreImg::getImgType, IMG_TYPE_BATH_FACILITY);
+                imageWrapper.orderByAsc(StoreImg::getImgSort);
+                imageWrapper.last("LIMIT 1");
+                StoreImg firstImage = storeImgMapper.selectOne(imageWrapper);
+                if (firstImage != null) {
+                    categoryVo.setCategoryImage(firstImage.getImgUrl());
+                }
+            }
+            
+            // 转换为VO列表(包含设备信息和图片)
+            List<BathFacilityServiceVo> facilityVoList = new ArrayList<>();
+            if (!CollectionUtils.isEmpty(facilityServiceList)) {
+                for (BathFacilityService facilityService : facilityServiceList) {
+                    // 使用现有的convertToVo方法,它会自动查询图片
+                    BathFacilityServiceVo vo = convertToVo(facilityService);
+                    facilityVoList.add(vo);
+                }
+            }
+            categoryVo.setFacilityList(facilityVoList);
+            
+            result.add(categoryVo);
+        }
+        
+        return result;
+    }
+
+    @Override
+    public IPage<BathFacilityServiceVo> getStorePageList(Integer pageNum, Integer pageSize, Integer storeId, Integer facilityCategory) {
+        Page<BathFacilityService> page = new Page<>(pageNum, pageSize);
+        LambdaQueryWrapper<BathFacilityService> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(BathFacilityService::getStoreId, storeId);
+        if (facilityCategory != null) {
+            queryWrapper.eq(BathFacilityService::getFacilityCategory, facilityCategory);
+        }
+        queryWrapper.orderByDesc(BathFacilityService::getCreatedTime);
+        IPage<BathFacilityService> facilityServicePage = facilityServiceMapper.selectPage(page, queryWrapper);
+        return facilityServicePage.convert(this::convertToVo);
+    }
+
+    @Override
+    public BathFacilityServiceVo getStoreDetail(Integer id) {
+        BathFacilityService facilityService = facilityServiceMapper.selectById(id);
+        if (facilityService == null) {
+            return null;
+        }
+        return convertToVo(facilityService);
+    }
+
+    @Override
+    public List<BathFacilityServiceCategoryVo> getStoreCategorySummary(Integer storeId) {
+        List<BathFacilityServiceCategoryVo> result = new ArrayList<>();
+
+        // 遍历所有分类(1:洗浴区, 2:汗蒸区, 3:休闲区, 4:餐饮区)
+        for (int category = 1; category < FACILITY_CATEGORY_NAMES.length; category++) {
+            BathFacilityServiceCategoryVo categoryVo = new BathFacilityServiceCategoryVo();
+            categoryVo.setFacilityCategory(category);
+            categoryVo.setFacilityCategoryName(FACILITY_CATEGORY_NAMES[category]);
+
+            // 查询该分类下的设备列表(不分页)
+            LambdaQueryWrapper<BathFacilityService> facilityWrapper = new LambdaQueryWrapper<>();
+            facilityWrapper.eq(BathFacilityService::getStoreId, storeId)
+                    .eq(BathFacilityService::getFacilityCategory, category);
+            facilityWrapper.orderByDesc(BathFacilityService::getCreatedTime);
+            List<BathFacilityService> facilityServiceList = facilityServiceMapper.selectList(facilityWrapper);
+
+            // 设置设备数量
+            categoryVo.setFacilityCount(facilityServiceList != null ? facilityServiceList.size() : 0);
+
+            // 查询该分类的代表图片(从第一个设备的第一张图片获取)
+            if (!CollectionUtils.isEmpty(facilityServiceList)) {
+                BathFacilityService firstFacility = facilityServiceList.get(0);
+                // 查询该设备的第一张图片
+                LambdaQueryWrapper<StoreImg> imageWrapper = new LambdaQueryWrapper<>();
+                imageWrapper.eq(StoreImg::getStoreId, storeId)
+                        .eq(StoreImg::getBusinessId, firstFacility.getId())
+                        .eq(StoreImg::getImgType, IMG_TYPE_BATH_FACILITY);
+                imageWrapper.orderByAsc(StoreImg::getImgSort);
+                imageWrapper.last("LIMIT 1");
+                StoreImg firstImage = storeImgMapper.selectOne(imageWrapper);
+                if (firstImage != null) {
+                    categoryVo.setCategoryImage(firstImage.getImgUrl());
+                }
+            }
+
+            // 转换为VO列表(包含设备信息和图片)
+            List<BathFacilityServiceVo> facilityVoList = new ArrayList<>();
+            if (!CollectionUtils.isEmpty(facilityServiceList)) {
+                for (BathFacilityService facilityService : facilityServiceList) {
+                    // 使用现有的convertToVo方法,它会自动查询图片
+                    BathFacilityServiceVo vo = convertToVo(facilityService);
+                    facilityVoList.add(vo);
+                }
+            }
+            categoryVo.setFacilityList(facilityVoList);
+
+            result.add(categoryVo);
+        }
+
+        return result;
+    }
+}
+

+ 367 - 0
alien-store/src/main/java/shop/alien/store/service/impl/DrinkInfoServiceImpl.java

@@ -0,0 +1,367 @@
+package shop.alien.store.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+import shop.alien.entity.store.DrinkInfo;
+import shop.alien.entity.store.StoreImg;
+import shop.alien.entity.store.StoreMenu;
+import shop.alien.entity.store.vo.DrinkInfoVo;
+import shop.alien.mapper.StoreImgMapper;
+import shop.alien.mapper.StoreMenuMapper;
+import shop.alien.store.service.DrinkInfoService;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 酒水餐食信息 服务实现类
+ * 基于 store_menu 表实现
+ * dish_menu_type: 1=餐食(菜单/菜品),2=酒水
+ * 注意:drink_info 表已废弃,现在使用 store_menu 表
+ *
+ * @author ssk
+ * @since 2025-06-13
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+@Transactional
+public class DrinkInfoServiceImpl implements DrinkInfoService {
+
+    private final StoreMenuMapper storeMenuMapper;
+    private final StoreImgMapper storeImgMapper;
+    
+    /**
+     * 菜单类型常量
+     * 1 = 餐食(菜单/菜品)
+     * 2 = 酒水
+     */
+    private static final String MENU_TYPE_FOOD = "1";
+    private static final String MENU_TYPE_DRINK = "2";
+    
+    /**
+     * 菜单图片类型
+     */
+    private static final Integer IMG_TYPE_MENU = 7;
+
+    @Override
+    public IPage<DrinkInfoVo> getDrinkInfoPage(int page, int size, Integer storeId, Integer type, String category, String name, Integer createUserId) {
+        LambdaQueryWrapper<StoreMenu> queryWrapper = new LambdaQueryWrapper<>();
+        
+        // type 参数:1=餐食,2=酒水
+        if (type != null) {
+            queryWrapper.eq(StoreMenu::getDishMenuType, type.toString());
+        } else {
+            // 不传则查询所有(餐食和酒水)
+            queryWrapper.in(StoreMenu::getDishMenuType, MENU_TYPE_FOOD, MENU_TYPE_DRINK);
+        }
+        
+        // 筛选条件
+        if (createUserId != null) {
+            queryWrapper.eq(StoreMenu::getCreatedUserId, createUserId);
+        }
+        if (storeId != null) {
+            queryWrapper.eq(StoreMenu::getStoreId, storeId);
+        }
+        if (category != null && !category.isEmpty()) {
+            queryWrapper.eq(StoreMenu::getCategory, category);
+        }
+        if (name != null && !name.isEmpty()) {
+            queryWrapper.like(StoreMenu::getDishName, name);
+        }
+        // 按排序和创建时间倒序
+        queryWrapper.orderByAsc(StoreMenu::getSort);
+        queryWrapper.orderByDesc(StoreMenu::getCreatedTime);
+
+        IPage<StoreMenu> menuPage = storeMenuMapper.selectPage(new Page<>(page, size), queryWrapper);
+        // 转换为Vo
+        IPage<DrinkInfoVo> drinkInfoVoPage = new Page<>(page, size);
+        drinkInfoVoPage.setTotal(menuPage.getTotal());
+        List<DrinkInfoVo> drinkInfoVoList = menuPage.getRecords().stream()
+                .map(this::convertMenuToVo)
+                .collect(Collectors.toList());
+        drinkInfoVoPage.setRecords(drinkInfoVoList);
+
+        return drinkInfoVoPage;
+    }
+
+    @Override
+    public DrinkInfoVo getDrinkInfoById(Integer id) {
+        StoreMenu menu = storeMenuMapper.selectById(id);
+        // 验证是否为餐食或酒水类型
+        if (menu == null || 
+            (!MENU_TYPE_FOOD.equals(menu.getDishMenuType()) && !MENU_TYPE_DRINK.equals(menu.getDishMenuType()))) {
+            return null;
+        }
+        return convertMenuToVo(menu);
+    }
+
+    @Override
+    public boolean saveDrinkInfo(DrinkInfo drinkInfo) {
+        // 转换为 StoreMenu 对象
+        StoreMenu menu = new StoreMenu();
+        menu.setStoreId(drinkInfo.getStoreId());
+        menu.setDishName(drinkInfo.getName());
+        menu.setDishPrice(drinkInfo.getPrice());
+        menu.setCostPrice(drinkInfo.getCostPrice());
+        // type: 1=餐食,2=酒水,默认为酒水
+        menu.setDishMenuType(drinkInfo.getType() != null ? drinkInfo.getType().toString() : MENU_TYPE_DRINK);
+        menu.setCategory(drinkInfo.getCategory());
+        menu.setAlcoholVolume(drinkInfo.getAlcoholVolume() != null ? drinkInfo.getAlcoholVolume().toString() : "0");
+        menu.setFlavor(drinkInfo.getFlavor());
+        menu.setDescription(drinkInfo.getDescription());
+        menu.setDishType(drinkInfo.getIsRecommended() != null ? drinkInfo.getIsRecommended() : 0);
+        menu.setSort(drinkInfo.getSort() != null ? drinkInfo.getSort() : 0);
+        menu.setDishesUnit("份");
+        menu.setLikeCount(0);
+        
+        // 保存菜单
+        int result = storeMenuMapper.insert(menu);
+        
+        // 如果有图片URL,保存到 store_img 表
+        if (result > 0 && StringUtils.hasText(drinkInfo.getPicUrl())) {
+            StoreImg img = new StoreImg();
+            img.setStoreId(menu.getStoreId());
+            img.setImgType(IMG_TYPE_MENU);
+            img.setImgUrl(drinkInfo.getPicUrl());
+            img.setBusinessId(menu.getId());
+            String typeDesc = MENU_TYPE_DRINK.equals(menu.getDishMenuType()) ? "酒水" : "餐食";
+            img.setImgDescription(typeDesc + "图片-" + menu.getDishName());
+            img.setImgSort(1);
+            storeImgMapper.insert(img);
+            
+            // 更新菜单的 img_id
+            menu.setImgId(img.getId());
+            storeMenuMapper.updateById(menu);
+        }
+        
+        return result > 0;
+    }
+
+    @Override
+    public boolean updateDrinkInfo(DrinkInfo drinkInfo) {
+        if (drinkInfo.getId() == null) {
+            return false;
+        }
+        
+        // 验证是否为餐食或酒水类型
+        StoreMenu existMenu = storeMenuMapper.selectById(drinkInfo.getId());
+        if (existMenu == null || 
+            (!MENU_TYPE_FOOD.equals(existMenu.getDishMenuType()) && !MENU_TYPE_DRINK.equals(existMenu.getDishMenuType()))) {
+            log.warn("该商品不是餐食/酒水类型,无法修改");
+            return false;
+        }
+        
+        // 构建更新对象
+        StoreMenu menu = new StoreMenu();
+        menu.setId(drinkInfo.getId());
+        if (StringUtils.hasText(drinkInfo.getName())) {
+            menu.setDishName(drinkInfo.getName());
+        }
+        if (drinkInfo.getPrice() != null) {
+            menu.setDishPrice(drinkInfo.getPrice());
+        }
+        if (drinkInfo.getCostPrice() != null) {
+            menu.setCostPrice(drinkInfo.getCostPrice());
+        }
+        if (StringUtils.hasText(drinkInfo.getCategory())) {
+            menu.setCategory(drinkInfo.getCategory());
+        }
+        if (drinkInfo.getAlcoholVolume() != null) {
+            menu.setAlcoholVolume(drinkInfo.getAlcoholVolume().toString());
+        }
+        if (StringUtils.hasText(drinkInfo.getFlavor())) {
+            menu.setFlavor(drinkInfo.getFlavor());
+        }
+        if (StringUtils.hasText(drinkInfo.getDescription())) {
+            menu.setDescription(drinkInfo.getDescription());
+        }
+        if (drinkInfo.getIsRecommended() != null) {
+            menu.setDishType(drinkInfo.getIsRecommended());
+        }
+        if (drinkInfo.getSort() != null) {
+            menu.setSort(drinkInfo.getSort());
+        }
+        if (drinkInfo.getType() != null) {
+            menu.setDishMenuType(drinkInfo.getType().toString());
+        }
+        
+        // 处理图片更新
+        if (StringUtils.hasText(drinkInfo.getPicUrl())) {
+            // 删除旧图片
+            if (existMenu.getImgId() != null) {
+                storeImgMapper.deleteById(existMenu.getImgId());
+            }
+            
+            // 保存新图片
+            StoreImg img = new StoreImg();
+            img.setStoreId(existMenu.getStoreId());
+            img.setImgType(IMG_TYPE_MENU);
+            img.setImgUrl(drinkInfo.getPicUrl());
+            img.setBusinessId(drinkInfo.getId());
+            String typeDesc = MENU_TYPE_DRINK.equals(existMenu.getDishMenuType()) ? "酒水" : "餐食";
+            String dishName = menu.getDishName() != null ? menu.getDishName() : existMenu.getDishName();
+            img.setImgDescription(typeDesc + "图片-" + dishName);
+            img.setImgSort(1);
+            storeImgMapper.insert(img);
+            
+            menu.setImgId(img.getId());
+        }
+        
+        return storeMenuMapper.updateById(menu) > 0;
+    }
+
+    @Override
+    public boolean deleteDrinkInfo(Integer id) {
+        // 验证是否为餐食或酒水类型
+        StoreMenu menu = storeMenuMapper.selectById(id);
+        if (menu == null || 
+            (!MENU_TYPE_FOOD.equals(menu.getDishMenuType()) && !MENU_TYPE_DRINK.equals(menu.getDishMenuType()))) {
+            log.warn("该商品不是餐食/酒水类型,无法删除");
+            return false;
+        }
+        
+        // 逻辑删除(由 @TableLogic 自动处理)
+        return storeMenuMapper.deleteById(id) > 0;
+    }
+
+    @Override
+    public boolean updateStatus(Integer id, Integer status) {
+        // 注意:store_menu 表有 status 字段了,但 StoreMenu 实体类暂未映射
+        LambdaUpdateWrapper<StoreMenu> updateWrapper = new LambdaUpdateWrapper<>();
+        updateWrapper.eq(StoreMenu::getId, id)
+                .in(StoreMenu::getDishMenuType, MENU_TYPE_FOOD, MENU_TYPE_DRINK);  // 允许修改餐食和酒水
+        // TODO: 在 StoreMenu 实体类中添加 status 字段映射后启用
+        // .set(StoreMenu::getStatus, status);
+        return true;  // 暂时返回 true
+    }
+
+    @Override
+    public boolean updateIsRecommended(Integer id, Integer isRecommended) {
+        LambdaUpdateWrapper<StoreMenu> updateWrapper = new LambdaUpdateWrapper<>();
+        updateWrapper.eq(StoreMenu::getId, id)
+                .eq(StoreMenu::getDishMenuType, MENU_TYPE_DRINK)  // 只支持酒水
+                .set(StoreMenu::getDishType, isRecommended);
+        return storeMenuMapper.update(null, updateWrapper) > 0;
+    }
+
+    @Override
+    public boolean updateSort(Integer id, Integer sort) {
+        LambdaUpdateWrapper<StoreMenu> updateWrapper = new LambdaUpdateWrapper<>();
+        updateWrapper.eq(StoreMenu::getId, id)
+                .eq(StoreMenu::getDishMenuType, MENU_TYPE_DRINK)  // 只支持酒水
+                .set(StoreMenu::getSort, sort);
+        return storeMenuMapper.update(null, updateWrapper) > 0;
+    }
+
+    @Override
+    public List<DrinkInfoVo> getDrinkInfoListByStoreId(Integer storeId, Integer type) {
+        LambdaQueryWrapper<StoreMenu> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(StoreMenu::getStoreId, storeId);
+        
+        // type 参数:2=酒水,3=餐食
+        if (type != null) {
+            queryWrapper.eq(StoreMenu::getDishMenuType, type.toString());
+        } else {
+            // 不传则查询所有(餐食和酒水)
+            queryWrapper.in(StoreMenu::getDishMenuType, MENU_TYPE_FOOD, MENU_TYPE_DRINK);
+        }
+        
+        queryWrapper.orderByAsc(StoreMenu::getSort);
+        queryWrapper.orderByDesc(StoreMenu::getCreatedTime);
+
+        List<StoreMenu> menuList = storeMenuMapper.selectList(queryWrapper);
+        return menuList.stream()
+                .map(this::convertMenuToVo)
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public List<DrinkInfoVo> getRecommendedList(Integer storeId, Integer createUserId) {
+        LambdaQueryWrapper<StoreMenu> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.in(StoreMenu::getDishMenuType, MENU_TYPE_FOOD, MENU_TYPE_DRINK)  // 查询餐食和酒水
+                .eq(StoreMenu::getDishType, 1);  // 推荐
+        
+        // 只查询指定用户创建的商品
+        if (createUserId != null) {
+            queryWrapper.eq(StoreMenu::getCreatedUserId, createUserId);
+        }
+        
+        if (storeId != null) {
+            queryWrapper.eq(StoreMenu::getStoreId, storeId);
+        }
+        queryWrapper.orderByAsc(StoreMenu::getSort);
+        queryWrapper.orderByDesc(StoreMenu::getCreatedTime);
+
+        List<StoreMenu> menuList = storeMenuMapper.selectList(queryWrapper);
+        return menuList.stream()
+                .map(this::convertMenuToVo)
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public boolean batchUpdateSort(List<DrinkInfo> drinkInfoList) {
+        if (drinkInfoList == null || drinkInfoList.isEmpty()) {
+            return false;
+        }
+        try {
+            for (DrinkInfo drinkInfo : drinkInfoList) {
+                if (drinkInfo.getId() != null && drinkInfo.getSort() != null) {
+                    LambdaUpdateWrapper<StoreMenu> updateWrapper = new LambdaUpdateWrapper<>();
+                    updateWrapper.eq(StoreMenu::getId, drinkInfo.getId())
+                            .in(StoreMenu::getDishMenuType, MENU_TYPE_FOOD, MENU_TYPE_DRINK)  // 支持餐食和酒水
+                            .set(StoreMenu::getSort, drinkInfo.getSort());
+                    storeMenuMapper.update(null, updateWrapper);
+                }
+            }
+            return true;
+        } catch (Exception e) {
+            log.error("批量更新排序失败", e);
+            return false;
+        }
+    }
+    /**
+     * 将 StoreMenu 转换为 DrinkInfoVo
+     *
+     * @param menu StoreMenu对象
+     * @return DrinkInfoVo对象
+     */
+    private DrinkInfoVo convertMenuToVo(StoreMenu menu) {
+        DrinkInfoVo vo = new DrinkInfoVo();
+        vo.setId(menu.getId());
+        vo.setName(menu.getDishName());
+        vo.setPrice(menu.getDishPrice());
+        vo.setCostPrice(menu.getCostPrice());
+        // 转换类型为数字:1=餐食,2=酒水
+        vo.setType(menu.getDishMenuType() != null ? Integer.parseInt(menu.getDishMenuType()) : 2);
+        vo.setCategory(menu.getCategory());
+        vo.setAlcoholVolume(menu.getAlcoholVolume() != null ? new java.math.BigDecimal(menu.getAlcoholVolume()) : java.math.BigDecimal.ZERO);
+        vo.setFlavor(menu.getFlavor());
+        vo.setDescription(menu.getDescription());
+        vo.setIsRecommended(menu.getDishType());
+        vo.setStoreId(menu.getStoreId());
+        vo.setCreateUserId(menu.getCreatedUserId());
+        vo.setUpdateUserId(menu.getUpdatedUserId());
+        vo.setSort(menu.getSort());
+        vo.setStatus(1);  // 默认上架
+        vo.setCreateTime(menu.getCreatedTime());
+        vo.setUpdateTime(menu.getUpdatedTime());
+        
+        // 获取图片URL
+        if (menu.getImgId() != null) {
+            StoreImg img = storeImgMapper.selectById(menu.getImgId());
+            if (img != null) {
+                vo.setPicUrl(img.getImgUrl());
+            }
+        }
+        
+        return vo;
+    }
+}

+ 7 - 7
alien-store/src/main/java/shop/alien/store/service/impl/LifeBlacklistServiceImpl.java

@@ -106,16 +106,16 @@ public class LifeBlacklistServiceImpl extends ServiceImpl<LifeBlacklistMapper, L
                 if ("1".equals(lifeBlacklist.getBlockedType())) {
                     StoreUser storeUser = storeUserMapper.selectById(lifeBlacklist.getBlockedId());
                     StoreImg storeImg = null;
-//                    if (storeUser != null) {
-//                        storeImg = storeImgMapper.selectOne(new LambdaUpdateWrapper<StoreImg>().eq(StoreImg::getStoreId, storeUser.getStoreId()).eq(StoreImg::getImgType, 10));
-//                    }
                     if (storeUser != null) {
-                        lifeBlacklist.setName(storeUser.getNickName());
+                        storeImg = storeImgMapper.selectOne(new LambdaUpdateWrapper<StoreImg>().eq(StoreImg::getStoreId, storeUser.getStoreId()).eq(StoreImg::getImgType, 10));
+                    }
+                    if (storeUser != null) {
+                        lifeBlacklist.setName(storeUser.getName());
                         lifeBlacklist.setPhoneId(storeUser.getPhone());
                         lifeBlacklist.setUserImage(storeUser.getHeadImg());
-//                        if (storeImg != null) {
-//                            lifeBlacklist.setUserImage(storeImg.getImgUrl());
-//                        }
+                        if (storeImg != null) {
+                            lifeBlacklist.setUserImage(storeImg.getImgUrl());
+                        }
                     }
                 } else {
                     LifeUser lifeUser = lifeUserMapper.selectById(lifeBlacklist.getBlockedId());

+ 5 - 0
alien-store/src/main/java/shop/alien/store/service/impl/LifeCouponServiceImpl.java

@@ -689,4 +689,9 @@ public class LifeCouponServiceImpl extends ServiceImpl<LifeCouponMapper, LifeCou
         return R.success("效验通过");
     }
 
+    @Override
+    public shop.alien.entity.store.vo.LifeCouponVo getNewCouponDetail(String id) {
+        return lifeCouponMapper.getNewCouponDetail(id);
+    }
+
 }

+ 5 - 2
alien-store/src/main/java/shop/alien/store/service/impl/LifeDiscountCouponServiceImpl.java

@@ -347,8 +347,10 @@ public class LifeDiscountCouponServiceImpl extends ServiceImpl<LifeDiscountCoupo
         try {
             LocalDateTime now = LocalDateTime.now();
             //根据店铺id查询该店铺的优惠券,状态是开启领取的券
-            List<LifeDiscountCoupon> lifeDiscountCoupons = lifeDiscountCouponMapper.selectList(new LambdaQueryWrapper<LifeDiscountCoupon>().eq(LifeDiscountCoupon::getStoreId, storeId).eq(LifeDiscountCoupon::getGetStatus, "1") //还有库存
-                    .ge(LifeDiscountCoupon::getEndGetDate, LocalDate.now()).orderByDesc(LifeDiscountCoupon::getCreatedTime));
+            List<LifeDiscountCoupon> lifeDiscountCoupons = lifeDiscountCouponMapper.selectList(new LambdaQueryWrapper<LifeDiscountCoupon>()
+                    .eq(LifeDiscountCoupon::getStoreId, storeId).eq(LifeDiscountCoupon::getGetStatus, "1") //还有库存
+                    .ge(LifeDiscountCoupon::getEndGetDate, LocalDate.now())
+                    .orderByDesc(LifeDiscountCoupon::getAttentionCanReceived));
             //根据优惠券列表查询该优惠券是否领取过
             for (LifeDiscountCoupon lifeDiscountCoupon : lifeDiscountCoupons) {
                 LifeDiscountCouponVo lifeDiscountCouponVo = new LifeDiscountCouponVo();
@@ -684,6 +686,7 @@ public class LifeDiscountCouponServiceImpl extends ServiceImpl<LifeDiscountCoupo
             LifeDiscountCouponVo lifeDiscountCouponVo = new LifeDiscountCouponVo();
             if (null != storeInfoOne) {
                 lifeDiscountCouponVo.setBusinessSection(storeInfoOne.getBusinessSection());
+                lifeDiscountCouponVo.setBusinessSectionName(storeInfoOne.getBusinessSectionName());
             }
             lifeDiscountCouponVo.setCouponId(lifeDiscountCouponOne.getId());
             BeanUtils.copyProperties(lifeDiscountCouponOne, lifeDiscountCouponVo);

+ 9 - 9
alien-store/src/main/java/shop/alien/store/service/impl/LifeUserViolationServiceImpl.java

@@ -112,15 +112,15 @@ public class LifeUserViolationServiceImpl extends ServiceImpl<LifeUserViolationM
             if (result > 0) {
                 // AI审核
                 //登录获取token
-                String token = aiUserViolationUtils.getAccessToken();
-                //调用AI接口
-                String taskId = aiUserViolationUtils.createTask(token, lifeuserViolation);
-                if (org.springframework.util.StringUtils.isEmpty(taskId)) {
-                    log.warn("Failed to create AI task for second round review, lifeuserViolation id={}", lifeuserViolation.getId());
-                    return 0;
-                }
-                lifeuserViolation.setAiTaskId(taskId);
-                lifeUserViolationMapper.updateById(lifeuserViolation);
+//                String token = aiUserViolationUtils.getAccessToken();
+//                //调用AI接口
+//                String taskId = aiUserViolationUtils.createTask(token, lifeuserViolation);
+//                if (org.springframework.util.StringUtils.isEmpty(taskId)) {
+//                    log.warn("Failed to create AI task for second round review, lifeuserViolation id={}", lifeuserViolation.getId());
+//                    return 0;
+//                }
+//                lifeuserViolation.setAiTaskId(taskId);
+//                lifeUserViolationMapper.updateById(lifeuserViolation);
 
 
                 //String phoneId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getString("userType") + "_" + JwtUtil.getCurrentUserInfo().getString("phone");

部分文件因文件數量過多而無法顯示