Browse Source

Merge remote-tracking branch 'origin/sit' into sit

qxy 1 week ago
parent
commit
ffc928c207
100 changed files with 6555 additions and 115 deletions
  1. 4 0
      alien-entity/src/main/java/shop/alien/entity/second/SecondGoods.java
  2. 25 0
      alien-entity/src/main/java/shop/alien/entity/second/vo/StoreImgDTO.java
  3. 86 0
      alien-entity/src/main/java/shop/alien/entity/store/BathFacilityService.java
  4. 4 0
      alien-entity/src/main/java/shop/alien/entity/store/LawyerConsultationOrder.java
  5. 29 0
      alien-entity/src/main/java/shop/alien/entity/store/LifeUserDynamics.java
  6. 4 0
      alien-entity/src/main/java/shop/alien/entity/store/LifeUserViolation.java
  7. 154 0
      alien-entity/src/main/java/shop/alien/entity/store/RefundRecord.java
  8. 66 0
      alien-entity/src/main/java/shop/alien/entity/store/SecondAiTask.java
  9. 86 0
      alien-entity/src/main/java/shop/alien/entity/store/SportsEquipmentFacility.java
  10. 12 0
      alien-entity/src/main/java/shop/alien/entity/store/StoreClockIn.java
  11. 1 0
      alien-entity/src/main/java/shop/alien/entity/store/StoreComment.java
  12. 7 0
      alien-entity/src/main/java/shop/alien/entity/store/StoreCommentAppeal.java
  13. 9 0
      alien-entity/src/main/java/shop/alien/entity/store/StoreDictionary.java
  14. 1 1
      alien-entity/src/main/java/shop/alien/entity/store/StoreImg.java
  15. 30 0
      alien-entity/src/main/java/shop/alien/entity/store/StoreInfo.java
  16. 19 3
      alien-entity/src/main/java/shop/alien/entity/store/StoreMenu.java
  17. 75 0
      alien-entity/src/main/java/shop/alien/entity/store/StorePersonnel.java
  18. 10 0
      alien-entity/src/main/java/shop/alien/entity/store/StoreStaffConfig.java
  19. 73 0
      alien-entity/src/main/java/shop/alien/entity/store/StoreVerificationCode.java
  20. 75 0
      alien-entity/src/main/java/shop/alien/entity/store/UserActionRewardRule.java
  21. 6 0
      alien-entity/src/main/java/shop/alien/entity/store/dto/LawyerConsultationOrderDto.java
  22. 6 0
      alien-entity/src/main/java/shop/alien/entity/store/dto/PayStatusRequest.java
  23. 17 0
      alien-entity/src/main/java/shop/alien/entity/store/dto/StoreInfoDto.java
  24. 36 0
      alien-entity/src/main/java/shop/alien/entity/store/excelVo/BusinessSectionExcelVo.java
  25. 34 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/AiApproveStoreInfo.java
  26. 39 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/BathFacilityServiceCategoryVo.java
  27. 66 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/BathFacilityServiceVo.java
  28. 24 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/CouponAndEventVo.java
  29. 5 1
      alien-entity/src/main/java/shop/alien/entity/store/vo/LawyerConsultationOrderVO.java
  30. 43 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/RewardRuleTreeNodeVo.java
  31. 39 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/SportsEquipmentFacilityCategoryVo.java
  32. 61 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/SportsEquipmentFacilityVo.java
  33. 53 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreAlbumDetailVo.java
  34. 25 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreAlbumNameVo.java
  35. 33 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreCommentCountVo.java
  36. 16 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreInfoVo.java
  37. 9 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreMainInfoVo.java
  38. 46 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreMenuImportVo.java
  39. 29 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreOfficialAlbumImgVo.java
  40. 34 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StorePersonnelVo.java
  41. 101 0
      alien-entity/src/main/java/shop/alien/entity/storePlatform/StoreOperationalActivity.java
  42. 77 0
      alien-entity/src/main/java/shop/alien/entity/storePlatform/vo/StoreOperationalActivityDTO.java
  43. 58 0
      alien-entity/src/main/java/shop/alien/entity/storePlatform/vo/StoreOperationalActivityVO.java
  44. 17 0
      alien-entity/src/main/java/shop/alien/mapper/BathFacilityServiceMapper.java
  45. 5 2
      alien-entity/src/main/java/shop/alien/mapper/LawyerConsultationOrderMapper.java
  46. 65 2
      alien-entity/src/main/java/shop/alien/mapper/LifeUserOrderMapper.java
  47. 17 0
      alien-entity/src/main/java/shop/alien/mapper/RefundRecordMapper.java
  48. 12 0
      alien-entity/src/main/java/shop/alien/mapper/SecondAiTaskMapper.java
  49. 17 0
      alien-entity/src/main/java/shop/alien/mapper/SportsEquipmentFacilityMapper.java
  50. 28 0
      alien-entity/src/main/java/shop/alien/mapper/StoreCommentAppealMapper.java
  51. 54 0
      alien-entity/src/main/java/shop/alien/mapper/StoreInfoMapper.java
  52. 43 2
      alien-entity/src/main/java/shop/alien/mapper/StoreMenuMapper.java
  53. 44 0
      alien-entity/src/main/java/shop/alien/mapper/StorePersonnelMapper.java
  54. 13 0
      alien-entity/src/main/java/shop/alien/mapper/StoreVerificationCodeMapper.java
  55. 17 0
      alien-entity/src/main/java/shop/alien/mapper/UserActionRewardRuleMapper.java
  56. 17 0
      alien-entity/src/main/java/shop/alien/mapper/storePlantform/StoreOperationalActivityMapper.java
  57. 20 0
      alien-entity/src/main/resources/mapper/StoreVerificationCodeMapper.xml
  58. 32 0
      alien-entity/src/main/resources/mapper/storePlatform/StoreOperationalActivityMapper.xml
  59. 1 1
      alien-gateway/src/main/resources/bootstrap.yml
  60. 13 0
      alien-job/src/main/java/shop/alien/job/feign/AlienStoreFeign.java
  61. 4 0
      alien-job/src/main/java/shop/alien/job/feign/SecondGoodsFeign.java
  62. 217 0
      alien-job/src/main/java/shop/alien/job/second/AiCheckXxlJob.java
  63. 183 0
      alien-job/src/main/java/shop/alien/job/second/AiUserViolationJob.java
  64. 190 0
      alien-job/src/main/java/shop/alien/job/second/goodsCheckJob.java
  65. 445 10
      alien-job/src/main/java/shop/alien/job/store/AiTagJob.java
  66. 419 0
      alien-job/src/main/java/shop/alien/job/store/BadReviewAppealJob.java
  67. 30 7
      alien-job/src/main/java/shop/alien/job/store/LifeUserOrderJob.java
  68. 1 1
      alien-job/src/main/resources/bootstrap.yml
  69. 11 0
      alien-lawyer/src/main/java/shop/alien/lawyer/feign/AlienStoreFeign.java
  70. 0 1
      alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/LawyerClientConsultationOrderServiceImpl.java
  71. 7 3
      alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/LawyerConsultationOrderServiceImpl.java
  72. 20 0
      alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/LawyerUserViolationServiceImpl.java
  73. 63 25
      alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/OrderExpirationServiceImpl.java
  74. 2 31
      alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/OrderReviewServiceImpl.java
  75. 86 0
      alien-second/src/main/java/shop/alien/second/service/SecondGoodsAuditService.java
  76. 29 0
      alien-second/src/main/java/shop/alien/second/service/SecondGoodsNotificationService.java
  77. 18 0
      alien-second/src/main/java/shop/alien/second/service/SecondGoodsOperationRecordService.java
  78. 546 0
      alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsAuditServiceImpl.java
  79. 151 0
      alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsNotificationServiceImpl.java
  80. 127 0
      alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsOperationRecordServiceImpl.java
  81. 6 5
      alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsServiceImpl.java
  82. 146 0
      alien-second/src/main/java/shop/alien/second/util/AiTaskUtils.java
  83. 1 1
      alien-second/src/main/resources/bootstrap.yml
  84. 285 0
      alien-store-platform/doc/OPERATIONAL_ACTIVITY_README.md
  85. 1 1
      alien-store-platform/src/main/java/shop/alien/storeplatform/AlienStorePlatformApplication.java
  86. 178 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/controller/BusinessSectionController.java
  87. 63 4
      alien-store-platform/src/main/java/shop/alien/storeplatform/controller/LicenseController.java
  88. 1 1
      alien-store-platform/src/main/java/shop/alien/storeplatform/controller/LifeCouponPlatformController.java
  89. 148 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/controller/OperationalActivityController.java
  90. 72 13
      alien-store-platform/src/main/java/shop/alien/storeplatform/controller/StoreMenuPlatformController.java
  91. 189 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/controller/StorePlatformBarMenuController.java
  92. 186 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/controller/StorePlatformBathFacilityServiceController.java
  93. 187 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/controller/StorePlatformSportsEquipmentFacilityController.java
  94. 97 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/controller/StorePlatformStoreStaffConfigController.java
  95. 90 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/entity/StorePlatformBathFacility.java
  96. 82 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/entity/StorePlatformSportsEquipmentFacility.java
  97. 112 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/entity/StorePlatformStoreMenu.java
  98. 103 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/entity/StorePlatformStoreStaffConfig.java
  99. 7 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/feign/AlienStoreFeign.java
  100. 10 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/mapper/StorePlatformBathFacilityServiceMapper.java

+ 4 - 0
alien-entity/src/main/java/shop/alien/entity/second/SecondGoods.java

@@ -112,6 +112,10 @@ public class SecondGoods implements Serializable {
     @ApiModelProperty(value = "审核失败原因")
     private String failedReason;
 
+    @TableField("ai_task_id")
+    @ApiModelProperty(value = "ai_task_id")
+    private String aiTaskId;
+
     @TableField(value = "created_time", fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     @ApiModelProperty(value = "创建时间")

+ 25 - 0
alien-entity/src/main/java/shop/alien/entity/second/vo/StoreImgDTO.java

@@ -0,0 +1,25 @@
+package shop.alien.entity.second.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import shop.alien.entity.store.StoreImg;
+
+import java.util.Date;
+
+/**
+ * 上传图片vo
+ *
+ * @author ssk
+ * @version 1.0
+ * @date 2025/1/13 10:35
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+@JsonInclude
+public class StoreImgDTO extends StoreImg {
+
+    @JsonFormat(pattern = "yyyy/MM/dd", timezone = "GMT+8")
+    Date expirationTime;
+}

+ 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;
+}
+

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

@@ -175,5 +175,9 @@ public class LawyerConsultationOrder extends Model<LawyerConsultationOrder> {
     @ApiModelProperty(value = "退款申请处理动作:1-同意,2-拒绝")
     @TableField(exist = false)
     private String processAction;
+
+    @ApiModelProperty(value = "支付方式 1支付宝 2微信")
+    @TableField("pay_type")
+    private  String payType;
 }
 

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

@@ -6,6 +6,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
+import java.math.BigDecimal;
 import java.util.Date;
 
 /**
@@ -112,4 +113,32 @@ public class LifeUserDynamics {
     @ApiModelProperty(value = "启用状态0-启用,1-禁用")
     @TableField("enable_status")
     private Integer enableStatus;
+
+    @ApiModelProperty(value = "达人id")
+    @TableField("expert_id")
+    private Integer expertId;
+
+    @ApiModelProperty(value = "业务id")
+    @TableField("business_id")
+    private Integer businessId;
+
+    @ApiModelProperty(value = "转发量")
+    @TableField("transfer_count")
+    private Integer transferCount;
+
+    @ApiModelProperty(value = "达人动态实际浏览数")
+    @TableField("reality_count")
+    private Integer realityCount;
+
+    @ApiModelProperty(value = "是否审核(未审核:0,审核中:1,审核完成:2)")
+    @TableField("check_flag")
+    private Integer checkFlag;
+
+    @ApiModelProperty(value = "AI审核结果查询id")
+    @TableField("ai_task_id")
+    private String aiTaskId;
+
+    @ApiModelProperty(value = "审核失败原因")
+    @TableField("reason")
+    private String reason;
 }

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

@@ -131,6 +131,10 @@ public class LifeUserViolation extends Model<LifeUserViolation> {
     @TableField(value = "goods_id")
     private Integer goodsId;
 
+    @ApiModelProperty(value = "商品ID")
+    @TableField(value = "ai_task_id")
+    private String aiTaskId;
+
     @Override
     protected Serializable pkVal() {
         return this.id;

+ 154 - 0
alien-entity/src/main/java/shop/alien/entity/store/RefundRecord.java

@@ -0,0 +1,154 @@
+package shop.alien.entity.store;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+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 lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+/**
+ * <p>
+ * 退款记录表
+ * </p>
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@JsonInclude
+@ApiModel(value = "RefundRecord对象", description = "退款记录表")
+@TableName("refund_record")
+public class RefundRecord extends Model<RefundRecord> {
+
+    @ApiModelProperty(value = "主键")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty(value = "用户ID")
+    @TableField("user_id")
+    private Integer userId;
+
+    @ApiModelProperty(value = "商户订单号:商户系统生成的原交易订单唯一标识")
+    @TableField("out_trade_no")
+    private String outTradeNo;
+
+    @ApiModelProperty(value = "第三方支付订单号:微信支付订单号或支付宝交易号")
+    @TableField("transaction_id")
+    private String transactionId;
+
+    @ApiModelProperty(value = "商户退款单号:商户系统生成的退款单号")
+    @TableField("out_refund_no")
+    private String outRefundNo;
+
+    @ApiModelProperty(value = "第三方退款单号:微信退款单号或支付宝退款单号")
+    @TableField("refund_id")
+    private String refundId;
+
+    @ApiModelProperty(value = "支付类型:WECHAT_PAY-微信支付, ALIPAY-支付宝")
+    @TableField("pay_type")
+    private String payType;
+
+    @ApiModelProperty(value = "退款状态:SUCCESS-退款成功, CLOSED-退款关闭, PROCESSING-退款处理中, ABNORMAL-退款异常")
+    @TableField("refund_status")
+    private String refundStatus;
+
+    @ApiModelProperty(value = "订单总金额:单位分")
+    @TableField("total_amount")
+    private Long totalAmount;
+
+    @ApiModelProperty(value = "退款金额:单位分")
+    @TableField("refund_amount")
+    private Long refundAmount;
+
+    @ApiModelProperty(value = "实际退款金额:单位分,最终成功退回给用户的金额")
+    @TableField("actual_refund_amount")
+    private Long actualRefundAmount;
+
+    @ApiModelProperty(value = "退款币种:默认CNY")
+    @TableField("currency")
+    private String currency;
+
+    @ApiModelProperty(value = "退款原因")
+    @TableField("refund_reason")
+    private String refundReason;
+
+    @ApiModelProperty(value = "退款渠道:ORIGINAL-原路退回, BALANCE-退回余额, OTHER_BALANCE-其他余额, OTHER_BANKCARD-其他银行卡")
+    @TableField("refund_channel")
+    private String refundChannel;
+
+    @ApiModelProperty(value = "退款资金来源:AVAILABLE-可用余额, UNSETTLED-未结算资金")
+    @TableField("funds_account")
+    private String fundsAccount;
+
+    @ApiModelProperty(value = "退款创建时间:退款请求创建时间")
+    @TableField("refund_create_time")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date refundCreateTime;
+
+    @ApiModelProperty(value = "退款成功时间:退款成功完成时间")
+    @TableField("refund_success_time")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date refundSuccessTime;
+
+    @ApiModelProperty(value = "用户收到退款账户:退款到账的账户信息")
+    @TableField("user_received_account")
+    private String userReceivedAccount;
+
+    @ApiModelProperty(value = "退款详情:退款渠道明细列表(JSON格式)")
+    @TableField("refund_detail")
+    private String refundDetail;
+
+    @ApiModelProperty(value = "错误码:退款失败时的错误码")
+    @TableField("error_code")
+    private String errorCode;
+
+    @ApiModelProperty(value = "错误信息:退款失败时的错误描述")
+    @TableField("error_msg")
+    private String errorMsg;
+
+    @ApiModelProperty(value = "响应数据:第三方支付平台返回的完整响应数据(JSON格式)")
+    @TableField("response_data")
+    private String responseData;
+
+    @ApiModelProperty(value = "业务订单ID:关联的业务订单ID")
+    @TableField("order_id")
+    private String orderId;
+
+    @ApiModelProperty(value = "店铺ID")
+    @TableField("store_id")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "备注")
+    @TableField("remark")
+    private String remark;
+
+    @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;
+}
+

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

@@ -0,0 +1,66 @@
+package shop.alien.entity.store;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+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.util.Date;
+
+/**
+ * second_ai_task 表实体
+ */
+@Data
+@TableName("second_ai_task")
+@ApiModel(value = "SecondAiTask", description = "AI视频审核任务表")
+public class SecondAiTask implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty("主键ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty("数据ID")
+    @TableField("data_id")
+    private String dataId;
+
+    @ApiModelProperty("视频URL")
+    @TableField("video_url")
+    private String videoUrl;
+
+    @ApiModelProperty("任务ID")
+    @TableField("task_id")
+    private String taskId;
+
+    @ApiModelProperty("任务状态 SUBMITTED/PROCESSING/...")
+    @TableField("status")
+    private String status;
+
+    @ApiModelProperty("风险级别 none/low/medium/high")
+    @TableField("risk_level")
+    private String riskLevel;
+
+    @ApiModelProperty("审核结果(JSON)")
+    @TableField("result")
+    private String result;
+
+    @ApiModelProperty("重试次数")
+    @TableField("retry_count")
+    private Integer retryCount;
+
+    @ApiModelProperty("创建时间")
+    @TableField("create_time")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createTime;
+
+    @ApiModelProperty("更新时间")
+    @TableField("update_time")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updateTime;
+}

+ 86 - 0
alien-entity/src/main/java/shop/alien/entity/store/SportsEquipmentFacility.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("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;
+
+    @ApiModelProperty(value = "收费类型0-免费,1-收费")
+    @TableField("billing_type")
+    private Integer billingType;
+}
+

+ 12 - 0
alien-entity/src/main/java/shop/alien/entity/store/StoreClockIn.java

@@ -83,6 +83,18 @@ public class StoreClockIn extends Model<StoreClockIn> {
     @TableField(value = "updated_user_id", fill = FieldFill.INSERT_UPDATE)
     private Integer updatedUserId;
 
+    @ApiModelProperty(value = "是否审核(未审核:0,审核中:1,审核完成:2)")
+    @TableField("check_flag")
+    private Integer checkFlag;
+
+    @ApiModelProperty(value = "AI审核结果查询id")
+    @TableField("ai_task_id")
+    private String aiTaskId;
+
+    @ApiModelProperty(value = "审核失败原因")
+    @TableField("reason")
+    private String reason;
+
 
     @Override
     protected Serializable pkVal() {

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

@@ -20,6 +20,7 @@ import java.util.Date;
 @Data
 @JsonInclude
 @EqualsAndHashCode(callSuper = false)
+@TableName("store_comment")
 @ApiModel(value = "StoreComment对象", description = "评论表")
 public class StoreComment extends Model<StoreComment> {
 

+ 7 - 0
alien-entity/src/main/java/shop/alien/entity/store/StoreCommentAppeal.java

@@ -74,4 +74,11 @@ public class StoreCommentAppeal extends Model<StoreCommentAppeal> {
     @TableField("updated_user_id")
     private Integer updatedUserId;
 
+    @ApiModelProperty(value = "AI接口返回的ID")
+    @TableField("record_id")
+    private Integer recordId;
+
+    @ApiModelProperty(value = "申诉ai审批过程")
+    @TableField("appeal_ai_approval")
+    private String appealAiApproval;
 }

+ 9 - 0
alien-entity/src/main/java/shop/alien/entity/store/StoreDictionary.java

@@ -80,6 +80,15 @@ public class StoreDictionary extends Model<StoreDictionary> {
     @TableField(exist = false)
     private List<StoreDictionary> storeDictionaryList;
 
+    @ApiModelProperty(value = "是否隐藏, 0:不隐藏, 1:隐藏")
+    @TableField("hidden")
+    private Integer hidden;
+
+    @ApiModelProperty(value = "排序ID")
+    @TableField("sort_id")
+    private Integer sortId;
+
+
     @Override
     protected Serializable pkVal() {
         return this.id;

+ 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.食品经营许可证审核后状态, 28:运动器材设施图片, 29:洗浴设施及服务图片 30 酒水")
     @TableField("img_type")
     private Integer imgType;
 

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

@@ -234,4 +234,34 @@ public class StoreInfo {
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     @TableField("update_renew_contract_time")
     private Date  updateRenewContractTime;
+
+    @ApiModelProperty(value = "分类id(词典表 键为 business_classify)")
+    @TableField("business_classify")
+    private String businessClassify;
+
+    @ApiModelProperty(value = "分类名称")
+    @TableField("business_classify_name")
+    private String businessClassifyName;
+
+    @ApiModelProperty(value = "是否提供餐食 0 否 1 是")
+    @TableField("meal_provided")
+    private Integer mealProvided;
+
+    @ApiModelProperty(value = "娱乐经营许可证状态 字典 foodLicenceStatus")
+    @TableField("entertainment_licence_status")
+    private Integer entertainmentLicenceStatus;
+
+    @ApiModelProperty(value = "娱乐经营许可证失败原因")
+    @TableField("entertainment_licence_reason")
+    private String entertainmentLicenceReason;
+
+    @ApiModelProperty(value = "娱乐经营许可证到期时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @TableField("entertainment_licence_expiration_time")
+    private Date entertainmentLicenceExpirationTime;
+
+    @ApiModelProperty(value = "变更娱乐经营许可证提交时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @TableField("update_entertainment_licence_time")
+    private Date updateEntertainmentLicenceTime;
 }

+ 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("alcoholVolume")
+    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;
+}
+

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

@@ -27,33 +27,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;
 

+ 73 - 0
alien-entity/src/main/java/shop/alien/entity/store/StoreVerificationCode.java

@@ -0,0 +1,73 @@
+package shop.alien.entity.store;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 短信验证码记录
+ */
+@Data
+@TableName("store_verification_code")
+public class StoreVerificationCode extends Model<StoreVerificationCode> {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty("主键id")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty("业务类型 (0:登录,1:修改密码,2:注册,3:修改手机号,4:注销店铺,5:注销账号,6:忘记密码)")
+    @TableField("business_type")
+    private Integer businessType;
+
+    @ApiModelProperty("手机号")
+    @TableField("phone")
+    private String phone;
+
+    @ApiModelProperty("端区分(0:用户,1:商家,2:律师端)")
+    @TableField("app_type")
+    private Integer appType;
+
+    @ApiModelProperty("验证码")
+    @TableField("code")
+    private String code;
+
+    @ApiModelProperty("创建时间")
+    @TableField("created_time")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createdTime;
+
+    @ApiModelProperty("更新时间")
+    @TableField("updated_time")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updatedTime;
+
+    @ApiModelProperty("创建人ID")
+    @TableField("created_user_id")
+    private Integer createdUserId;
+
+    @ApiModelProperty("更新人ID")
+    @TableField("updated_user_id")
+    private Integer updatedUserId;
+
+    @ApiModelProperty("删除标志(0:正常,1:删除)")
+    @TableField("delete_flag")
+    @TableLogic
+    private Integer deleteFlag;
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+}
+

+ 75 - 0
alien-entity/src/main/java/shop/alien/entity/store/UserActionRewardRule.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-XX
+ */
+@Data
+@JsonInclude
+@TableName("user_action_reward_rule")
+@ApiModel(value = "UserActionRewardRule", description = "用户行为奖励规则配置表")
+public class UserActionRewardRule {
+
+    @ApiModelProperty(value = "主键")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty(value = "角色(如:当用户)")
+    @TableField("role")
+    private String role;
+
+    @ApiModelProperty(value = "行为(如:核销并评论、核销、打卡)")
+    @TableField("action")
+    private String action;
+
+    @ApiModelProperty(value = "奖励(如:优惠券、红包)")
+    @TableField("reward")
+    private String reward;
+
+    @ApiModelProperty(value = "状态:0-禁用,1-启用")
+    @TableField("status")
+    private Integer status;
+
+    @ApiModelProperty(value = "排序")
+    @TableField("sort_order")
+    private Integer sortOrder;
+
+    @ApiModelProperty(value = "备注")
+    @TableField("remark")
+    private String remark;
+
+    @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;
+
+    @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
+    @TableField("delete_flag")
+    @TableLogic
+    private Integer deleteFlag;
+}
+

+ 6 - 0
alien-entity/src/main/java/shop/alien/entity/store/dto/LawyerConsultationOrderDto.java

@@ -124,5 +124,11 @@ public class LawyerConsultationOrderDto extends Model<LawyerConsultationOrderDto
     @ApiModelProperty(value = "律师接单状态  0接单  1拒绝接单")
     @TableField("accept_orders_status")
     private  Integer acceptOrdersStatus;
+
+
+    @ApiModelProperty(value = "支付方式 1支付宝 2微信")
+    @TableField("pay_type")
+    private  String payType;
+
 }
 

+ 6 - 0
alien-entity/src/main/java/shop/alien/entity/store/dto/PayStatusRequest.java

@@ -26,5 +26,11 @@ public class PayStatusRequest implements Serializable {
 
     @ApiModelProperty(value = "订单状态, 0:待支付,1.待接单 2:进行中, 3:已完成, 4:已取消,5.已退款")
     private Integer orderStatus;
+
+    @ApiModelProperty(value = "支付宝或VX的str")
+    private String orderStr;
+    
+    @ApiModelProperty
+    private String alipayNo;
 }
 

+ 17 - 0
alien-entity/src/main/java/shop/alien/entity/store/dto/StoreInfoDto.java

@@ -179,4 +179,21 @@ public class StoreInfoDto {
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private Date foodLicenceExpirationTime;
+
+    @ApiModelProperty(value = "分类id(词典表 键为 business_classify)")
+    private  List<String> businessClassifyList;
+
+    @ApiModelProperty(value = "分类名称")
+    private String businessClassifyName;
+
+    @ApiModelProperty(value = "分类id(词典表 键为 business_classify)")
+    @TableField("business_classify")
+    private String businessClassify;
+
+    @ApiModelProperty(value = "是否提供餐食 0=不提供  1=提供")
+    @TableField("meal_provided")
+    private Integer mealProvided;
+
+    @ApiModelProperty(value = "娱乐经营许可证")
+    private List<String> entertainmentLicenseAddress;
 }

+ 36 - 0
alien-entity/src/main/java/shop/alien/entity/store/excelVo/BusinessSectionExcelVo.java

@@ -0,0 +1,36 @@
+package shop.alien.entity.store.excelVo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import shop.alien.entity.store.excelVo.util.ExcelHeader;
+
+/**
+ * 经营版块Excel导入导出对象
+ *
+ * @author ssk
+ * @since 2025-01-XX
+ */
+@Data
+@JsonInclude
+@ApiModel(value = "BusinessSectionExcelVo对象", description = "经营版块Excel导入导出对象")
+public class BusinessSectionExcelVo {
+
+    @ExcelHeader("经营板块")
+    @ApiModelProperty(value = "一级分类名称(必填,如果二级和三级为空,则创建一级分类)")
+    private String firstLevelName;
+
+    @ExcelHeader("经营种类")
+    @ApiModelProperty(value = "二级分类名称(可选,如果三级为空,则创建二级分类)")
+    private String secondLevelName;
+
+    @ExcelHeader("分类")
+    @ApiModelProperty(value = "三级分类名称(可选,如果填写则创建三级分类)")
+    private String thirdLevelName;
+
+    @ExcelHeader("状态")
+    @ApiModelProperty(value = "状态为显示隐藏,如不填默认显示")
+    private String hidden;
+}
+

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

@@ -0,0 +1,34 @@
+package shop.alien.entity.store.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 店铺审核 - AI 服务请求体
+ */
+@Data
+public class AiApproveStoreInfo {
+
+    @ApiModelProperty(value = "用户id")
+    private String userId;
+
+    @ApiModelProperty(value = "商户名称(公司/门店名称)")
+    private String merchant_name;
+
+    @ApiModelProperty(value = "经营范围 / 业务描述")
+    private String business_scope;
+
+    @ApiModelProperty(value = "联系人姓名")
+    private String contact_name;
+
+    @ApiModelProperty(value = "联系人手机号")
+    private String contact_phone;
+
+    @ApiModelProperty(value = "联系人邮箱")
+    private String contact_email;
+
+    @ApiModelProperty(value = "证照/资质门头照片列表")
+    private List<String> license_images;
+}

+ 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;
+}

+ 5 - 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;
@@ -276,5 +275,10 @@ public class LawyerConsultationOrderVO implements Serializable {
             return null;
         }
     }
+
+    @ApiModelProperty(value = "支付方式 1支付宝 2微信")
+    @TableField("pay_type")
+    private  String payType;
+
 }
 

+ 43 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/RewardRuleTreeNodeVo.java

@@ -0,0 +1,43 @@
+package shop.alien.entity.store.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 用户行为奖励规则树形节点VO
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Data
+@ApiModel(value = "RewardRuleTreeNodeVo", description = "用户行为奖励规则树形节点")
+public class RewardRuleTreeNodeVo {
+
+    @ApiModelProperty(value = "节点值")
+    private String value;
+
+    @ApiModelProperty(value = "节点标签")
+    private String label;
+
+    @ApiModelProperty(value = "是否禁用")
+    private Boolean disabled;
+
+    @ApiModelProperty(value = "子节点列表")
+    private List<RewardRuleTreeNodeVo> children;
+
+    public RewardRuleTreeNodeVo() {
+        this.children = new ArrayList<>();
+    }
+
+    public RewardRuleTreeNodeVo(String value, String label, Boolean disabled) {
+        this.value = value;
+        this.label = label;
+        this.disabled = disabled;
+        this.children = new ArrayList<>();
+    }
+}
+

+ 39 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/SportsEquipmentFacilityCategoryVo.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 = "SportsEquipmentFacilityCategoryVo对象", description = "运动器材设施分类汇总视图对象")
+public class SportsEquipmentFacilityCategoryVo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @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;
+}
+

+ 33 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/StoreCommentCountVo.java

@@ -0,0 +1,33 @@
+package shop.alien.entity.store.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * 评价计数VO
+ *
+ * @author ssk
+ * @version 1.0
+ * @date 2025/12/01
+ */
+@Data
+@JsonInclude
+public class StoreCommentCountVo {
+
+    @ApiModelProperty(value = "全部评价数")
+    private Integer totalCount;
+
+    @ApiModelProperty(value = "有图评价数")
+    private Integer imageCount;
+
+    @ApiModelProperty(value = "好评数")
+    private Integer goodCount;
+
+    @ApiModelProperty(value = "中评数")
+    private Integer midCount;
+
+    @ApiModelProperty(value = "差评数")
+    private Integer badCount;
+}
+

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

@@ -214,4 +214,20 @@ public class StoreInfoVo extends StoreInfo {
 
     @ApiModelProperty(value = "动态数量")
     private Integer dynamicsNum;
+
+    @ApiModelProperty(value = "是否提供餐食")
+    private Integer  mealsFlag;
+
+
+    @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;
 }

+ 9 - 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;
 
@@ -83,6 +89,9 @@ public class StoreMainInfoVo extends StoreInfo {
     @ApiModelProperty(value = "经营种类ids")
     private List<String> businessTypesList;
 
+    @ApiModelProperty(value = "分类DistIds")
+    private List<String> businessClassifyList;
+
     @ApiModelProperty(value = "到期时间")
     private String expirationDate;
 

+ 46 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/StoreMenuImportVo.java

@@ -0,0 +1,46 @@
+package shop.alien.entity.store.vo;
+
+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 shop.alien.entity.store.excelVo.util.ExcelImage;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 二期-门店菜单
+ *
+ * @author ssk
+ * @since 2024-12-05
+ */
+@Data
+@JsonInclude
+@ApiModel(value = "StoreMenuImportVo对象")
+public class StoreMenuImportVo {
+
+    @ApiModelProperty(value = "菜品名称")
+    private String dishName;
+
+    @ApiModelProperty(value = "价格")
+    private BigDecimal dishPrice;
+
+    @ApiModelProperty(value = "成本价")
+    private BigDecimal costPrice;
+
+//    @ApiModelProperty(value = "单位")
+//    private String dishesUnit;
+
+    @ApiModelProperty(value = "图片")
+    @ExcelImage
+    private String img;
+
+    @ApiModelProperty(value = "描述")
+    private String description;
+
+    @ApiModelProperty(value = "是否推荐")
+    private Integer dishType;
+}

+ 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;
+}
+

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

@@ -0,0 +1,101 @@
+package shop.alien.entity.storePlatform;
+
+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-11-26
+ */
+@Data
+@JsonInclude
+@TableName("store_operational_activity")
+@ApiModel(value = "StoreOperationalActivity对象", description = "运营活动表")
+public class StoreOperationalActivity {
+
+    @ApiModelProperty(value = "主键")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty(value = "商户ID")
+    @TableField("store_id")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "活动名称")
+    @TableField("activity_name")
+    private String activityName;
+
+    @ApiModelProperty(value = "活动宣传图URL")
+    @TableField("promotional_image")
+    private String promotionalImage;
+
+    @ApiModelProperty(value = "活动开始时间")
+    @TableField("start_time")
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    private Date startTime;
+
+    @ApiModelProperty(value = "活动结束时间")
+    @TableField("end_time")
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    private Date endTime;
+
+    @ApiModelProperty(value = "用户可参与次数,0表示不限制")
+    @TableField("participation_limit")
+    private Integer participationLimit;
+
+    @ApiModelProperty(value = "活动规则:VERIFY_AND_COMMENT-核销并评论, VERIFY-核销, CHECK_IN-打卡")
+    @TableField("activity_rule")
+    private String activityRule;
+
+    @ApiModelProperty(value = "奖励类型:COUPON-优惠券, RED_PACKET-红包")
+    @TableField("reward_type")
+    private String rewardType;
+
+    @ApiModelProperty(value = "优惠券ID,关联优惠券表")
+    @TableField("coupon_id")
+    private Integer couponId;
+
+    @ApiModelProperty(value = "优惠券发放数量")
+    @TableField("coupon_quantity")
+    private Integer couponQuantity;
+
+    @ApiModelProperty(value = "状态:0-禁用, 1-启用")
+    @TableField("status")
+    private Integer status;
+
+    @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.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;
+
+    @ApiModelProperty(value = "拒绝原因")
+    @TableField("approval_comments")
+    private String approvalComments;
+}
+

+ 77 - 0
alien-entity/src/main/java/shop/alien/entity/storePlatform/vo/StoreOperationalActivityDTO.java

@@ -0,0 +1,77 @@
+package shop.alien.entity.storePlatform.vo;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import shop.alien.entity.store.StoreImg;
+
+import java.util.Date;
+
+/**
+ * 运营活动 DTO
+ * 用于接收前端请求参数
+ *
+ * @author system
+ * @since 2025-11-26
+ */
+@Data
+@ApiModel(value = "StoreOperationalActivityDTO", description = "运营活动传输对象")
+public class StoreOperationalActivityDTO {
+
+    @ApiModelProperty(value = "主键ID(更新时必填)")
+    private Integer id;
+
+    @ApiModelProperty(value = "商户ID")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "活动名称", required = true)
+    private String activityName;
+
+    @ApiModelProperty(value = "活动宣传图URL")
+    private String promotionalImage;
+
+    @ApiModelProperty(value = "活动开始时间", required = true)
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    private Date startTime;
+
+    @ApiModelProperty(value = "活动结束时间", required = true)
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    private Date endTime;
+
+    @ApiModelProperty(value = "用户可参与次数,0表示不限制")
+    private Integer participationLimit;
+
+    @ApiModelProperty(value = "活动规则:VERIFY_AND_COMMENT-核销并评论, VERIFY-核销, CHECK_IN-打卡", required = true)
+    private String activityRule;
+
+    @ApiModelProperty(value = "奖励类型:COUPON-优惠券, RED_PACKET-红包")
+    private String rewardType;
+
+    @ApiModelProperty(value = "优惠券ID")
+    private Integer couponId;
+
+    @ApiModelProperty(value = "优惠券发放数量")
+    private Integer couponQuantity;
+
+    @ApiModelProperty(value = "状态:0-禁用, 1-启用")
+    private Integer status;
+
+    @ApiModelProperty(value = "拒绝原因")
+    private String approvalComments;
+
+    @ApiModelProperty(value = "活动标题图片")
+    private StoreImg activityTitleImg;
+
+    @ApiModelProperty(value = "活动详情图片")
+    private StoreImg activityDetailImg;
+
+    @ApiModelProperty(value = "页码")
+    private Integer pageNum;
+
+    @ApiModelProperty(value = "页数")
+    private Integer pageSize;
+
+}
+

+ 58 - 0
alien-entity/src/main/java/shop/alien/entity/storePlatform/vo/StoreOperationalActivityVO.java

@@ -0,0 +1,58 @@
+package shop.alien.entity.storePlatform.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 shop.alien.entity.storePlatform.StoreOperationalActivity;
+
+/**
+ * 运营活动 VO
+ * 用于返回给前端的数据对象
+ *
+ * @author system
+ * @since 2025-11-26
+ */
+@Data
+@JsonInclude
+@ApiModel(value = "StoreOperationalActivityVO", description = "运营活动返回对象")
+public class StoreOperationalActivityVO extends StoreOperationalActivity {
+
+    @ApiModelProperty(value = "活动状态名称")
+    private String statusName;
+
+    @ApiModelProperty(value = "活动规则名称")
+    private String activityRuleName;
+
+    @ApiModelProperty(value = "奖励类型名称")
+    private String rewardTypeName;
+
+    @ApiModelProperty(value = "优惠券名称")
+    private String couponName;
+
+    @ApiModelProperty(value = "商户名称")
+    private String storeName;
+
+    @ApiModelProperty(value = "活动状态:0-未开始, 1-进行中, 2-已结束")
+    private Integer activityStatus;
+
+    @ApiModelProperty(value = "已参与人数")
+    private Integer participationCount;
+
+    @ApiModelProperty(value = "剩余优惠券数量")
+    private Integer remainingCouponQuantity;
+
+    @ApiModelProperty(value = "活动标题图片")
+    private StoreImg activityTitleImg;
+
+    @ApiModelProperty(value = "活动详情图片")
+    private StoreImg activityDetailImg;
+
+    @ApiModelProperty(value = "活动标题图片")
+    private String activityTitleImgUrl;
+
+    @ApiModelProperty(value = "活动详情图片")
+    private String activityDetailImgUrl;
+}
+

+ 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> {
+
+}
+

+ 5 - 2
alien-entity/src/main/java/shop/alien/mapper/LawyerConsultationOrderMapper.java

@@ -98,7 +98,8 @@ public interface LawyerConsultationOrderMapper extends BaseMapper<LawyerConsulta
             "lawyer_earnings ," +
             "accept_orders_time ," +
             "reason_order_refusal ," +
-            "accept_orders_status " +
+            "accept_orders_status ," +
+            "pay_type " +
             ")"+
             "VALUES" +
             " (" +
@@ -130,7 +131,8 @@ public interface LawyerConsultationOrderMapper extends BaseMapper<LawyerConsulta
             "#{lawyerEarnings} ," +
             "#{acceptOrdersTime} ," +
             "#{reasonOrderRefusal} ," +
-            "#{acceptOrdersStatus}" +
+            "#{acceptOrdersStatus} ," +
+            "#{payType} " +
             ")")
             int insertOrder(LawyerConsultationOrderDto order);
 
@@ -396,6 +398,7 @@ public interface LawyerConsultationOrderMapper extends BaseMapper<LawyerConsulta
             "        lco.alipay_no,\n" +
             "        lco.order_str,\n" +
             "        lco.apply_refund_status,\n" +
+            "        lco.pay_type,\n" +
             "        CASE\n" +
             "        WHEN EXISTS (SELECT 1 FROM lawyer_order_review lor WHERE lor.order_id = lco.id) THEN '1'\n" +
             "        ELSE '2'\n" +

+ 65 - 2
alien-entity/src/main/java/shop/alien/mapper/LifeUserOrderMapper.java

@@ -32,7 +32,7 @@ public interface LifeUserOrderMapper extends BaseMapper<LifeUserOrder> {
 
     LifeUserOrderVo queryUserOrderDetail(@Param("orderId") String orderId,@Param("position") String position);
 
-    @Select("with total_coupon as(\n" +
+/*    @Select("with total_coupon as(\n" +
             "-- 团购\n" +
             "\tselect id coupon_id,2 coupon_type,lgbm.group_name coupon_name, SUBSTRING_INDEX(image_id, ',', 1) AS image_id,effective_date_type,effective_date_value \n" +
             "from life_group_buy_main lgbm \n" +
@@ -57,12 +57,75 @@ public interface LifeUserOrderMapper extends BaseMapper<LifeUserOrder> {
             "from life_user_order luo\n" +
             "left join store_info si on si.id = luo.store_id  -- 查询店铺相关 \n" +
             "left join life_user lu on lu.id = luo.user_id and lu.delete_flag = 0 -- 查询用户相关 \n" +
-            "left join order_coupon_middle ocm on ocm.order_id = luo.id \n" +
+            "left join order_coupon_middle ocm on ocm.order_id = luo.id and ocm.delete_flag = 0\n" +
             "left join total_coupon tc on tc.coupon_id = ocm.coupon_id and tc.coupon_type = luo.coupon_type\n" +
             "left join  store_img simg on simg.id = tc.image_id and simg.delete_flag = 0 \n" +
             "left join  store_comment sc on sc.business_id = luo.id and sc.delete_flag = 0 and sc.business_type = 5\n" +
             "left join life_discount_coupon_user ldcu on ldcu .id = luo.quan_id \n" +
             "left join life_discount_coupon ldc on ldc.id = ldcu.coupon_id \n" +
+            "${ew.customSqlSegment}")*/
+    @Select("with total_coupon as(\n" +
+            "-- 团购\n" +
+            "\tselect id coupon_id,2 coupon_type,lgbm.group_name coupon_name, SUBSTRING_INDEX(image_id, ',', 1) AS image_id,effective_date_type,effective_date_value \n" +
+            "\tfrom life_group_buy_main lgbm \n" +
+            "\tunion all\n" +
+            "-- 代金券\n" +
+            "\tselect id coupon_id,1 coupon_type,lc.name coupon_name, SUBSTRING_INDEX(image_path, ',', 1) AS image_id,0 effective_date_type,expiration_date effective_date_value \n" +
+            "\tfrom life_coupon lc \n" +
+            ")\n" +
+            "select \n" +
+            "    luo.id,\n" +
+            "    luo.buy_time,\n" +
+            "    luo.status,\n" +
+            "    luo.price,\n" +
+            "    luo.final_price,\n" +
+            "    luo.user_id,\n" +
+            "    luo.store_id,\n" +
+            "    luo.order_no,\n" +
+            "    luo.pay_time,\n" +
+            "    luo.cancel_time,\n" +
+            "    luo.finish_time,\n" +
+            "    luo.order_str,\n" +
+            "    luo.expert_order_id,\n" +
+            "    luo.order_appraise,\n" +
+            "    -- 店铺表列:用ANY_VALUE包裹(一个订单对应一个店铺,值唯一)\n" +
+            "    ANY_VALUE(si.store_name) as store_name,\n" +
+            "    ANY_VALUE(si.commission_rate) as commission_rate,\n" +
+            "    ANY_VALUE(si.business_section) as store_type,\n" +
+            "    ANY_VALUE(si.store_status) as store_status,\n" +
+            "    ANY_VALUE(si.business_status) as business_status,\n" +
+            "    -- 聚合列:优惠券数量(唯一聚合列,无需处理)\n" +
+            "    count(ocm.coupon_code) as coupon_count,\n" +
+            "    -- 图片表列:用ANY_VALUE包裹(一个优惠券对应一张图片,值唯一)\n" +
+            "    ANY_VALUE(simg.img_url) as img_url,\n" +
+            "    -- 用户表列:用ANY_VALUE包裹(一个订单对应一个用户,值唯一)\n" +
+            "    ANY_VALUE(lu.user_phone) as user_phone,\n" +
+            "    -- 评论状态:用ANY_VALUE包裹(一个订单最多一条评论,值唯一)\n" +
+            "    ANY_VALUE(IF(sc.id is null,false,true)) as hasComment,\n" +
+            "    -- 优惠券CTE列:拆解tc.*为具体列,用ANY_VALUE包裹\n" +
+            "    ANY_VALUE(tc.coupon_id) as coupon_id,\n" +
+            "    ANY_VALUE(tc.coupon_type) as coupon_type,\n" +
+            "    ANY_VALUE(tc.coupon_name) as coupon_name,\n" +
+            "    ANY_VALUE(tc.image_id) as tc_image_id,\n" +
+            "    ANY_VALUE(tc.effective_date_type) as effective_date_type,\n" +
+            "    ANY_VALUE(tc.effective_date_value) as effective_date_value,\n" +
+            "    -- 异常状态标识:用ANY_VALUE包裹\n" +
+            "    ANY_VALUE(CASE\n" +
+            "        WHEN si.delete_flag = 1 OR si.logout_flag = 1 THEN 1\n" +
+            "        ELSE 0\n" +
+            "    END) AS abnormalStateFlag,\n" +
+            "    -- 折扣券列:用ANY_VALUE包裹(一个订单对应一个折扣券,值唯一)\n" +
+            "    ANY_VALUE(ldc.nominal_value) as nominal_value,\n" +
+            "    ANY_VALUE(ldc.type) as type\n" +
+            "from life_user_order luo\n" +
+            "left join store_info si on si.id = luo.store_id  -- 查询店铺相关 \n" +
+            "left join life_user lu on lu.id = luo.user_id and lu.delete_flag = 0 -- 查询用户相关 \n" +
+            "left join order_coupon_middle ocm on ocm.order_id = luo.id \n" +
+            "left join total_coupon tc on tc.coupon_id = ocm.coupon_id and tc.coupon_type = luo.coupon_type\n" +
+            "left join store_img simg on simg.id = tc.image_id and simg.delete_flag = 0 \n" +
+            "left join store_comment sc on sc.business_id = luo.id and sc.delete_flag = 0 and sc.business_type = 5\n" +
+            "left join life_discount_coupon_user ldcu on ldcu.id = luo.quan_id \n" +
+            "left join life_discount_coupon ldc on ldc.id = ldcu.coupon_id \n" +
             "${ew.customSqlSegment}")
     IPage<LifeUserOrderVo> queryUserOrderList(IPage<LifeUserOrderVo> brandedPage,@Param(Constants.WRAPPER) QueryWrapper<LifeUserOrderVo> lifeUserOrderQueryWrapper);
 

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

@@ -0,0 +1,17 @@
+package shop.alien.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import shop.alien.entity.store.RefundRecord;
+
+/**
+ * <p>
+ * 退款记录表 Mapper 接口
+ * </p>
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+public interface RefundRecordMapper extends BaseMapper<RefundRecord> {
+
+}
+

+ 12 - 0
alien-entity/src/main/java/shop/alien/mapper/SecondAiTaskMapper.java

@@ -0,0 +1,12 @@
+package shop.alien.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import shop.alien.entity.store.SecondAiTask;
+
+/**
+ * second_ai_task Mapper
+ */
+@Mapper
+public interface SecondAiTaskMapper extends BaseMapper<SecondAiTask> {
+}

+ 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> {
+
+}
+

+ 28 - 0
alien-entity/src/main/java/shop/alien/mapper/StoreCommentAppealMapper.java

@@ -6,10 +6,12 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Constants;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
 import shop.alien.entity.store.StoreCommentAppeal;
 import shop.alien.entity.store.vo.StoreCommentAppealVo;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * 评论申诉表 Mapper 接口
@@ -63,4 +65,30 @@ public interface StoreCommentAppealMapper extends BaseMapper<StoreCommentAppeal>
             "left join store_user e on a.store_id = e.store_id and e.delete_flag = 0  ${ew.customSqlSegment}")
     StoreCommentAppealVo getCommentDetail(@Param(Constants.WRAPPER) QueryWrapper<StoreCommentAppealVo> queryWrapper);
 
+
+    /**
+     * 申诉列表
+     *
+     * @return List<Map < String, Object>>
+     */
+    @Select("SELECT sca.id, sca.appeal_reason, sca.appeal_status, sc.comment_content, si.img_url, sci.user_img_url, sc.id comment_id, sc.business_id " +
+            "FROM store_comment_appeal sca " +
+            "LEFT JOIN store_comment sc ON sca.comment_id = sc.id " +
+            "LEFT JOIN store_img si ON sca.img_id = si.id " +
+            "LEFT JOIN (SELECT sc.id id, si.img_url user_img_url FROM store_comment sc LEFT JOIN store_img si ON sc.img_id = si.id AND sc.delete_flag = 0) sci ON sci.id = sca.comment_id " +
+            "WHERE sca.appeal_status = 0 AND sca.delete_flag = 0")
+    List<Map<String, Object>> getAppealList();
+
+
+    @Select("SELECT sca.id, sca.appeal_status, sca.final_result, sca.comment_id, sca.record_id " +
+            "FROM store_comment_appeal sca " +
+            "WHERE sca.appeal_status = 0")
+    List<StoreCommentAppeal> getPendingAppeals();
+
+    @Update("UPDATE store_comment_appeal " +
+            "SET appeal_status = #{appealStatus}, final_result = #{finalResult} " +
+            "WHERE record_id = #{recordId}")
+    void updateByRecordId(@Param("recordId") Integer recordId,
+                          @Param("appealStatus") Integer appealStatus,
+                          @Param("finalResult") String finalResult);
 }

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

@@ -89,6 +89,34 @@ public interface StoreInfoMapper extends BaseMapper<StoreInfo> {
             "${ew.customSqlSegment}")
     IPage<StoreInfoVo> getStoreInfoVoPage(IPage<StoreInfoVo> page, @Param(Constants.WRAPPER) QueryWrapper<StoreInfoVo> queryWrapper);
 
+    /**
+     * web端-门店列表
+     *
+     * @param page         分页
+     * @param queryWrapper 查询条件
+     * @return IPage<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 " +
+            "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}")
+    IPage<StoreInfoVo> getNewStoreInfoVoPage(IPage<StoreInfoVo> page, @Param(Constants.WRAPPER) QueryWrapper<StoreInfoVo> queryWrapper);
+
     @Select("select info.store_name, user.phone, img.img_url " +
             "from store_info info " +
             "join store_user user on user.store_id = info.id " +
@@ -130,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);
 }

+ 43 - 2
alien-entity/src/main/java/shop/alien/mapper/StoreMenuMapper.java

@@ -28,11 +28,52 @@ 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}))")
-    List<StoreMenuVo> getStoreMenuList(@Param("storeId") Integer storeId, @Param("dishType") Integer dishType);
+            "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> getStoreMenuList(@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 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);
+}
+

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

@@ -0,0 +1,13 @@
+package shop.alien.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import shop.alien.entity.store.StoreVerificationCode;
+
+/**
+ * 短信验证码 Mapper
+ */
+@Mapper
+public interface StoreVerificationCodeMapper extends BaseMapper<StoreVerificationCode> {
+}
+

+ 17 - 0
alien-entity/src/main/java/shop/alien/mapper/UserActionRewardRuleMapper.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.UserActionRewardRule;
+
+/**
+ * 用户行为奖励规则配置表 Mapper 接口
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Mapper
+public interface UserActionRewardRuleMapper extends BaseMapper<UserActionRewardRule> {
+
+}
+

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

@@ -0,0 +1,17 @@
+package shop.alien.mapper.storePlantform;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import shop.alien.entity.storePlatform.StoreOperationalActivity;
+
+/**
+ * 运营活动 Mapper 接口
+ *
+ * @author system
+ * @since 2025-11-26
+ */
+@Mapper
+public interface StoreOperationalActivityMapper extends BaseMapper<StoreOperationalActivity> {
+
+}
+

+ 20 - 0
alien-entity/src/main/resources/mapper/StoreVerificationCodeMapper.xml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="shop.alien.mapper.StoreVerificationCodeMapper">
+
+    <resultMap id="BaseResultMap" type="shop.alien.entity.store.StoreVerificationCode">
+        <id column="id" property="id"/>
+        <result column="business_type" property="businessType"/>
+        <result column="phone" property="phone"/>
+        <result column="app_type" property="appType"/>
+        <result column="code" property="code"/>
+        <result column="created_time" property="createdTime"/>
+        <result column="updated_time" property="updatedTime"/>
+        <result column="created_user_id" property="createdUserId"/>
+        <result column="updated_user_id" property="updatedUserId"/>
+        <result column="delete_flag" property="deleteFlag"/>
+    </resultMap>
+
+</mapper>
+

+ 32 - 0
alien-entity/src/main/resources/mapper/storePlatform/StoreOperationalActivityMapper.xml

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="shop.alien.mapper.storePlantform.StoreOperationalActivityMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="shop.alien.entity.storePlatform.StoreOperationalActivity">
+        <id column="id" property="id" />
+        <result column="store_id" property="storeId" />
+        <result column="activity_name" property="activityName" />
+        <result column="promotional_image" property="promotionalImage" />
+        <result column="start_time" property="startTime" />
+        <result column="end_time" property="endTime" />
+        <result column="participation_limit" property="participationLimit" />
+        <result column="activity_rule" property="activityRule" />
+        <result column="reward_type" property="rewardType" />
+        <result column="coupon_id" property="couponId" />
+        <result column="coupon_quantity" property="couponQuantity" />
+        <result column="status" property="status" />
+        <result column="delete_flag" property="deleteFlag" />
+        <result column="created_time" property="createdTime" />
+        <result column="created_user_id" property="createdUserId" />
+        <result column="updated_time" property="updatedTime" />
+        <result column="updated_user_id" property="updatedUserId" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, store_id, activity_name, promotional_image, start_time, end_time, participation_limit, activity_rule, reward_type, coupon_id, coupon_quantity, status, delete_flag, created_time, created_user_id, updated_time, updated_user_id
+    </sql>
+
+</mapper>
+

+ 1 - 1
alien-gateway/src/main/resources/bootstrap.yml

@@ -1,3 +1,3 @@
 spring:
   profiles:
-    active: dev
+    active: test

+ 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);
+
 }

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

@@ -3,6 +3,7 @@ package shop.alien.job.feign;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestParam;
+import shop.alien.entity.second.SecondGoods;
 
 @FeignClient(name = "alien-second", url = "${feign.alienSecond.url}")
 public interface SecondGoodsFeign {
@@ -24,4 +25,7 @@ public interface SecondGoodsFeign {
      */
     @GetMapping("/video/moderation/processTask")
     boolean processTask(@RequestParam("taskId") String taskId);
+
+    @GetMapping("/secondGoods/approveAndListGoods")
+    boolean approveAndListGoods(SecondGoods goods);
 }

+ 217 - 0
alien-job/src/main/java/shop/alien/job/second/AiCheckXxlJob.java

@@ -0,0 +1,217 @@
+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.xxl.job.core.handler.annotation.XxlJob;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.http.*;
+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.mapper.second.SecondGoodsRecordMapper;
+import shop.alien.mapper.second.SecondRiskControlRecordMapper;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @author Lhaibo
+ * @date 2025/11/28
+ * @desc: xxl-job
+ * AI调用审核任务
+ * @since 1.0.0
+ */
+@Slf4j
+@Component
+@RequiredArgsConstructor
+public class AiCheckXxlJob {
+
+    // 添加RestTemplate用于HTTP调用
+    private final RestTemplate restTemplate;
+
+    private final LifeUserViolationMapper lifeUserViolationMapper;
+
+    private final StoreDictionaryMapper storeDictionaryMapper;
+
+    private final LifeUserMapper lifeUserMapper;
+
+    private final SecondGoodsRecordMapper secondGoodsRecordMapper;
+
+    private final SecondRiskControlRecordMapper secondRiskControlRecordMapper;
+
+    // 第三方接口地址 登录接口URL
+    @Value("${third-party-login.base-url}")
+    private String loginUrl;
+
+    //用户名
+    @Value("${third-party-user-name.base-url}")
+    private String userName;
+
+    //密码
+    @Value("${third-party-pass-word.base-url}")
+    private String passWord;
+
+    /**
+     * AI自动审核任务处理器
+     * <p>
+     * 定时任务方法,用于批量处理用户违规举报记录,通过AI接口进行自动审核。
+     * 主要流程:
+     * 1. 查询所有待处理的用户违规记录
+     * 2. 遍历每条记录,组装审核请求数据
+     * 3. 调用AI审核接口进行自动审核(当前代码中已准备请求体,待实现接口调用)
+     * </p>
+     *
+     * @author Lhaibo
+     * @date 2025/11/28
+     * @since 1.0.0
+     */
+    @XxlJob("aiCheckJobHandler")
+    public void aiCheckJobHandler() {
+        log.info("开始执行AI自动审核任务");
+
+        try {
+            log.info("登录Ai服务获取token..." + loginUrl);
+            //构建请求参数
+            MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
+            formData.add("username", "admin");    // 表单字段 1:用户名
+            formData.add("password", "123456");    // 表单字段 2:密码
+
+            //设置请求头
+            HttpHeaders headers = new HttpHeaders();
+            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+            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);
+            } catch (Exception e) {
+                log.error("类:PostMethod 方法:post", 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::getProcessingStatus, "5"));
+
+                    // 遍历每条违规记录,组装AI审核请求数据
+                    for (LifeUserViolation violation : lifeUserViolations) {
+                        // 初始化请求体Map
+                        Map<String, Object> requestBody = new HashMap<>();
+
+                        // 设置投诉记录ID
+                        requestBody.put("complaint_id", violation.getId());
+
+                        // 查询投诉类型字典信息
+                        StoreDictionary storeDictionary = storeDictionaryMapper.selectOne(new LambdaQueryWrapper<StoreDictionary>()
+                                .eq(StoreDictionary::getTypeName, violation.getDictId()).eq(StoreDictionary::getTypeName, violation.getDictType()));
+                        String complaint_type = "";
+                        if (storeDictionary != null) {
+                            // 设置投诉类型
+                            complaint_type = storeDictionary.getDictDetail();
+                        }
+                        requestBody.put("complaint_type", complaint_type);
+                        // 设置举报人信息
+                        requestBody.put("reporter_user_id", violation.getReportingUserId());
+                        requestBody.put("reporter_user_type", violation.getReportingUserType());
+                        requestBody.put("reporter_info", lifeUserMapper.selectById(violation.getReportingUserId()));
+
+                        // 查询被举报的商品记录
+                        SecondGoodsRecord secondGoodsRecord = secondGoodsRecordMapper.selectById(violation.getBusinessId());
+                        if (secondGoodsRecord != null) {
+                            // 设置被举报人信息
+                            requestBody.put("reported_user_id", secondGoodsRecord.getUserId());
+                            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("complaint_text", violation.getOtherReasonContent());
+
+                        // 设置证据图片数组(将逗号分隔的字符串转换为数组)
+                        requestBody.put("evidence_images", violation.getReportEvidenceImg() != null ? violation.getReportEvidenceImg().split(",") : new String[0]);
+
+                        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("http://192.168.2.78:9000/ai/auto-review/api/v1/product_complaint_record/submit", request, String.class);
+                            log.info("AI自动审核结果:{}", response.getBody());
+                        } catch (Exception e) {
+                            log.error("AI自动审核请求异常", e);
+                        }
+                    }
+                }
+            }
+        } catch (Exception e) {
+            log.error("AI自动审核任务执行异常", e);
+        }
+
+        log.info("AI自动审核任务执行完成");
+    }
+
+    /**
+     * 二手商品风控记录审核任务
+     * <p>
+     * 定时查询风控记录表中待处理的数据(risk_status = 0),
+     * 预留后续风控审核/处理逻辑(如调用 AI 服务、通知运营等)。
+     * </p>
+     */
+    @XxlJob("riskControlCheckJobHandler")
+    public void riskControlCheckJobHandler() {
+        log.info("开始执行二手商品风控记录审核任务");
+
+        try {
+            // 查询风控记录表中待处理的记录(risk_status = 0)
+            List<SecondRiskControlRecord> riskControlRecords = secondRiskControlRecordMapper.selectList(
+                    new LambdaQueryWrapper<SecondRiskControlRecord>()
+                            .eq(SecondRiskControlRecord::getRiskStatus, 0)
+            );
+
+            log.info("本次待处理风控记录数量:{}", riskControlRecords.size());
+
+            // 按 ruleType 和 businessId 进行分组,生成新的嵌套结构
+            List<Map<String, List<SecondRiskControlRecord>>> groupedByRuleAndBusiness =
+                    (List<Map<String, List<SecondRiskControlRecord>>>) riskControlRecords.stream()
+                            .collect(Collectors.groupingBy(
+                                    SecondRiskControlRecord::getRuleType,
+                                    Collectors.groupingBy(SecondRiskControlRecord::getBusinessId)
+                            )).values();
+
+            for (Map<String, List<SecondRiskControlRecord>> byRuleAndBusiness : groupedByRuleAndBusiness) {
+
+
+            }
+        } catch (Exception e) {
+            log.error("二手商品风控记录审核任务执行异常", e);
+        }
+
+        log.info("二手商品风控记录审核任务执行完成");
+    }
+}

+ 183 - 0
alien-job/src/main/java/shop/alien/job/second/AiUserViolationJob.java

@@ -0,0 +1,183 @@
+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.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.LifeUserViolation;
+import shop.alien.entity.store.SecondAiTask;
+import shop.alien.mapper.LifeUserViolationMapper;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Slf4j
+@Component
+@RequiredArgsConstructor
+public class AiUserViolationJob {
+
+    private final RestTemplate restTemplate;
+    private final LifeUserViolationMapper lifeUserViolationMapper;
+
+    @Value("${third-party-user-name.base-url}")
+    private String userName;
+
+    @Value("${third-party-pass-word.base-url}")
+    private String passWord;
+
+    private String loginUrl = "http://192.168.2.250:9000/ai/user-auth-core/api/v1/auth/login";
+
+    private String aiUserViolationCheckUrl = "http://192.168.2.250:9000/ai/auto-review/api/v1/user_complaint_record/result";
+
+    @XxlJob("getAiUserViolationResult")
+    public R<String> getAiUserViolationResult() {
+        String accessToken = fetchAiServiceToken();
+        if (!StringUtils.hasText(accessToken)) {
+            return R.fail("调用AI举报用户辅助系统 登录接口失败");
+        }
+        return getAiUserViolationCheck(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);
+
+        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);
+        } catch (Exception e) {
+            log.error("调用差评申诉辅助系统登录接口异常", e);
+        }
+        return null;
+    }
+
+    private R<String> getAiUserViolationCheck(String accessToken) {
+
+
+        HttpHeaders analyzeHeaders = new HttpHeaders();
+        analyzeHeaders.setContentType(MediaType.APPLICATION_JSON);
+        analyzeHeaders.set("Authorization", "Bearer " + accessToken);
+        // 查询所有状态为处理中的申诉
+        List<LifeUserViolation> pendingTasks = lifeUserViolationMapper.selectList(
+                new QueryWrapper<LifeUserViolation>()
+                        .eq("processing_status", "0")
+                        .isNotNull("ai_task_id")
+        );
+
+        // 循环调用查询结果接口
+        for (LifeUserViolation task : pendingTasks) {
+            String completedUrl = buildCompletedUrl(task.getAiTaskId());
+
+            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("AI举报用户审核提交成功, 返回: {}", analyzeBody);
+
+                    JSONObject analyzeJson = JSONObject.parseObject(analyzeBody);
+                    JSONObject dataJsonObj = analyzeJson.getJSONObject("data");
+
+                    if (dataJsonObj == null) {
+                        log.error("AI举报用户审核返回数据为空");
+                        R.fail("AI举报用户审核返回数据为空");
+                        continue;
+                    }
+
+                    // 获取task_id用于后续查询
+                    String taskId = dataJsonObj.getString("task_id");
+                    if (taskId == null) {
+                        log.error("AI举报用户审核返回task_id为空");
+                        R.fail("AI举报用户审核返回task_id为空");
+                        continue;
+                    }
+
+                    LifeUserViolation aiTask = new LifeUserViolation();
+                    aiTask.setAiTaskId(taskId);
+                    if (dataJsonObj.getString("status").equals("pending")) {
+                        R.fail("审核未结束");
+                        continue;
+                    }
+
+                    if (dataJsonObj.getString("status").equals("completed")) {
+                        if (dataJsonObj.getString("is_valid").equals("true")) {
+                            aiTask.setProcessingStatus("1");
+                            aiTask.setReportResult(dataJsonObj.getString("decision_reason"));
+                        } else {
+                            aiTask.setProcessingStatus("0");
+                            aiTask.setReportResult(dataJsonObj.getString("decision_reason"));
+                        }
+                    }
+
+                    QueryWrapper<LifeUserViolation> queryWrapper = new QueryWrapper<>();
+                    queryWrapper.eq("ai_task_id", taskId);
+                    LifeUserViolation lifeUserViolation = lifeUserViolationMapper.selectOne(queryWrapper);
+                    if (lifeUserViolation == null) {
+                        log.error("AI举报用户不存在");
+                        R.fail("AI举报用户不存在");
+                        continue;
+                    }
+                    lifeUserViolationMapper.update(aiTask, queryWrapper);
+
+                } else {
+                    if (analyzeResp != null) {
+                        log.error("调用AI举报用户审核接口失败, http状态: {}", analyzeResp.getStatusCode());
+                        R.fail("调用AI举报用户审核接口失败, http状态: " + analyzeResp.getStatusCode());
+                    }
+                }
+            } catch (Exception e) {
+                log.error("调用差评申述查询结果接口异常", e);
+            }
+        }
+        return R.success("调用AI举报用户审核结果接口完成");
+    }
+
+    private String buildCompletedUrl(String recordId) {
+        String baseUrl = aiUserViolationCheckUrl;
+        if (!StringUtils.hasText(baseUrl)) {
+            throw new IllegalStateException("ai举报用户接口地址未配置");
+        }
+        if (baseUrl.endsWith("/")) {
+            baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
+        }
+        // 构建新的URL格式: /api/v1/audit_task/getResult?task_id={recordId}
+        return baseUrl + "?task_id=" + recordId;
+    }
+}

+ 190 - 0
alien-job/src/main/java/shop/alien/job/second/goodsCheckJob.java

@@ -0,0 +1,190 @@
+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;
+
+    @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);
+
+        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);
+        } 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);
+        }
+        // 构建新的URL格式: /api/v1/audit_task/getResult?task_id={recordId}
+        return baseUrl + "?task_id=" + recordId;
+    }
+}

+ 445 - 10
alien-job/src/main/java/shop/alien/job/store/AiTagJob.java

@@ -2,31 +2,29 @@ package shop.alien.job.store;
 
 import com.alibaba.fastjson2.JSONArray;
 import com.alibaba.fastjson2.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 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.Value;
 import org.springframework.http.*;
+import org.springframework.http.client.ClientHttpRequestInterceptor;
 import org.springframework.stereotype.Component;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.util.MultiValueMap;
 import org.springframework.web.client.RestTemplate;
 import shop.alien.entity.result.R;
-import shop.alien.entity.store.StoreCommentSummary;
-import shop.alien.entity.store.StoreCommentSummaryInterest;
-import shop.alien.entity.store.TagsMain;
-import shop.alien.entity.store.TagsSynonym;
-import shop.alien.mapper.StoreCommentSummaryInterestMapper;
-import shop.alien.mapper.StoreCommentSummaryMapper;
-import shop.alien.mapper.TagsMainMapper;
-import shop.alien.mapper.TagsSynonymMapper;
+import shop.alien.entity.store.*;
+import shop.alien.entity.store.vo.AiApproveStoreInfo;
+import shop.alien.mapper.*;
 
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
+
+import static com.alipay.api.internal.util.AlipayUtils.getFileSuffix;
 
 /**
  * 调用AI标签数据服务类
@@ -49,6 +47,12 @@ public class AiTagJob {
 
     private final StoreCommentSummaryInterestMapper storeCommentSummaryInterestMapper;
 
+    private final LifeUserDynamicsMapper lifeUserDynamicsMapper;
+
+    private final StoreClockInMapper storeClockInMapper;
+
+    private final StoreInfoMapper storeInfoMapper;
+
     // 第三方接口地址 获取所有标签主表信息
     @Value("${third-party-tag.base-url}")
     private String tagMainUrl;
@@ -73,6 +77,13 @@ public class AiTagJob {
     @Value("${third-party-savetag.base-url}")
     private String saveTagUrl;
 
+    // 第三方接口地址 内容合规检测接口
+    @Value("${third-party-contentcheck.base-url}")
+    private String contentComplianceUrl;
+
+    @Value("${third-party-getresult.base-url}")
+    private String getResultUrl;
+
     //用户名
     @Value("${third-party-user-name.base-url}")
     private String userName;
@@ -567,6 +578,430 @@ public class AiTagJob {
         return R.success("任务执行失败 状态码" + responseEntity.getStatusCodeValue());
     }
 
+    /**
+     * 利用AI审核违规内容
+     */
+    @XxlJob("contentComplianceCheckTask")
+    public R<String> contentComplianceCheckTask() {
+        List<LifeUserDynamics> lifeUserDynamics = lifeUserDynamicsMapper.selectList(new LambdaQueryWrapper<LifeUserDynamics>()
+                .eq(LifeUserDynamics::getCheckFlag, 0).eq(LifeUserDynamics::getDeleteFlag, 0));
+
+        // 只依赖数据库字段即可判定待审核的动态,避免重复提交
+        // 常见图片后缀(可按需添加,如 .heic、.svg 等)
+        HashSet<String> IMAGE_SUFFIXES = new HashSet<>(Arrays.asList(
+                "jpg", "jpeg", "png", "gif", "bmp", "webp", "heic", "svg", "tiff"
+        ));
+        // 常见视频后缀(可按需添加,如 .avi、.flv 等)
+        HashSet<String> VIDEO_SUFFIXES = new HashSet<>(Arrays.asList(
+                "mp4", "mov", "mkv", "avi", "flv", "wmv", "mpeg", "mpg", "webm"
+        ));
+
+        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);
+        }
+        HttpHeaders aiHeaders = new HttpHeaders();
+        if (postForEntity != null && postForEntity.getStatusCodeValue() == 200) {
+            log.info("请求Ai服务登录成功 postForEntity.getBody()\t" + postForEntity.getBody());
+            String responseBody = postForEntity.getBody();
+            JSONObject jsonObject = JSONObject.parseObject(responseBody);
+            if (jsonObject != null) {
+                JSONObject dataJson = jsonObject.getJSONObject("data");
+                String accessToken = dataJson.getString("access_token");
+
+                aiHeaders.setContentType(MediaType.APPLICATION_JSON);
+                aiHeaders.set("Authorization", "Bearer " + accessToken);
+            }
+        }
+
+        List<StoreClockIn> storeClockIns = storeClockInMapper.selectList(new LambdaQueryWrapper<StoreClockIn>()
+                .eq(StoreClockIn::getDeleteFlag, 0).eq(StoreClockIn::getCheckFlag, 0));
+        for (StoreClockIn storeClockIn : storeClockIns) {
+            String imagePath = storeClockIn.getImgUrl() != null ? storeClockIn.getImgUrl() : "";
+            List<String> imageList = new ArrayList<>();
+            List<String> videoList = new ArrayList<>();
+            // 按分隔符拆分路径数组(处理连续分隔符如 ",," 产生的空字符串)
+            String[] allPaths = imagePath.split(",");
+            for (String path : allPaths) {
+                // 去除路径前后空格(避免 " a.jpg " 这类情况)
+                String trimmedPath = path.trim();
+                if (trimmedPath.isEmpty()) {
+                    continue; // 跳过空路径
+                }
+                // 获取文件后缀(忽略大小写)
+                // 找到最后一个 "." 的位置
+                int lastDotIndex = trimmedPath.lastIndexOf('.');
+                // 截取后缀(从 "." 后一位到结尾)
+                String suffix = trimmedPath.substring(lastDotIndex + 1);
+                // 分类添加到对应列表
+                if (IMAGE_SUFFIXES.contains(suffix)) {
+                    imageList.add(trimmedPath);
+                } else if (VIDEO_SUFFIXES.contains(suffix)) {
+                    videoList.add(trimmedPath);
+                }
+            }
+            // 对每一条动态逐条申请 token 并提交,避免批量失败导致重试逻辑复杂化
+            try {
+                Map<String, Object> jsonBody = new HashMap<>();
+                // text/img/video 三种维度一起传入 AI,便于一次完成合规审查
+                jsonBody.put("text", storeClockIn.getContent());
+                jsonBody.put("image_urls", imageList);
+                jsonBody.put("video_urls", videoList);
+
+                HttpEntity<Map<String, Object>> request = new HttpEntity<>(jsonBody, aiHeaders);
+                ResponseEntity<String> response = null;
+                try {
+                    response = restTemplate.postForEntity(contentComplianceUrl, request, String.class);
+                    if (response.getStatusCodeValue() != 200) {
+                        log.error("AI内容审核接口调用失败 http状态:" + response.getStatusCode());
+                    }
+                    JSONObject responseNode = JSONObject.parseObject(response.getBody());
+                    if (responseNode == null) {
+                        log.error("AI接口调用失败,响应内容为空");
+                    }
+                    Integer code = null;
+                    if (responseNode != null) {
+                        code = responseNode.getInteger("code");
+                        if (code == 200) {
+                            JSONObject dataNode = JSONObject.from(responseNode.get("data"));
+                            // 审核发起后仅标记 checkFlag=1 并保存任务号,等待回调或后续轮询更新
+                            StoreClockIn clockIn = new StoreClockIn();
+                            clockIn.setId(storeClockIn.getId());
+                            clockIn.setCheckFlag(1);
+                            clockIn.setAiTaskId(dataNode.get("task_id").toString());
+                            storeClockInMapper.updateById(clockIn);
+                            log.info("动态审核成功,AI返回内容: {}", response.getBody());
+                            XxlJobHelper.handleSuccess("动态内容审核任务执行成功");
+                        }
+                    } else {
+                        log.error("AI接口调用失败,错误码: " + code);
+                    }
+                } catch (Exception e) {
+                    log.error("调用AI内容审核接口失败", e);
+                }
+            } catch (RuntimeException ex) {
+                XxlJobHelper.handleFail("动态内容审核任务执行失败:" + ex.getMessage());
+                return R.fail("动态内容审核任务执行失败:" + ex.getMessage());
+            }
+        }
+
+        for (LifeUserDynamics lifeUserDynamic : lifeUserDynamics) {
+            String imagePath = lifeUserDynamic.getImagePath();
+            List<String> imageList = new ArrayList<>();
+            List<String> videoList = new ArrayList<>();
+            // 按分隔符拆分路径数组(处理连续分隔符如 ",," 产生的空字符串)
+            String[] allPaths = imagePath.split(",");
+            for (String path : allPaths) {
+                // 去除路径前后空格(避免 " a.jpg " 这类情况)
+                String trimmedPath = path.trim();
+                if (trimmedPath.isEmpty()) {
+                    continue; // 跳过空路径
+                }
+                // 获取文件后缀(忽略大小写)
+                // 找到最后一个 "." 的位置
+                int lastDotIndex = trimmedPath.lastIndexOf('.');
+                // 截取后缀(从 "." 后一位到结尾)
+                String suffix = trimmedPath.substring(lastDotIndex + 1);
+                // 分类添加到对应列表
+                if (IMAGE_SUFFIXES.contains(suffix)) {
+                    imageList.add(trimmedPath);
+                } else if (VIDEO_SUFFIXES.contains(suffix)) {
+                    videoList.add(trimmedPath);
+                }
+            }
+            try {
+                Map<String, Object> jsonBody = new HashMap<>();
+                // text/img/video 三种维度一起传入 AI,便于一次完成合规审查
+                jsonBody.put("text", lifeUserDynamic.getContext());
+                jsonBody.put("image_urls", imageList);
+                jsonBody.put("video_urls", videoList);
+
+                HttpEntity<Map<String, Object>> request = new HttpEntity<>(jsonBody, aiHeaders);
+                ResponseEntity<String> response = null;
+                try {
+                    response = restTemplate.postForEntity(contentComplianceUrl, request, String.class);
+                    if (response.getStatusCodeValue() != 200) {
+                        log.error("AI内容审核接口调用失败 http状态:" + response.getStatusCode());
+                    }
+                    JSONObject responseNode = JSONObject.parseObject(response.getBody());
+                    if (responseNode == null) {
+                        log.error("AI接口调用失败,响应内容为空");
+                    }
+                    Integer code = null;
+                    if (responseNode != null) {
+                        code = responseNode.getInteger("code");
+                        if (code == 200) {
+                            JSONObject dataNode = JSONObject.from(responseNode.get("data"));
+                            // 审核发起后仅标记 checkFlag=1 并保存任务号,等待回调或后续轮询更新
+                            LifeUserDynamics dynamics = new LifeUserDynamics();
+                            dynamics.setId(lifeUserDynamic.getId());
+                            dynamics.setCheckFlag(1);
+                            dynamics.setAiTaskId(dataNode.get("task_id").toString());
+                            lifeUserDynamicsMapper.updateById(dynamics);
+                            log.info("动态审核成功,AI返回内容: {}", response.getBody());
+                            XxlJobHelper.handleSuccess("动态内容审核任务执行成功");
+                        }
+                    } else {
+                        log.error("AI接口调用失败,错误码: " + code);
+                    }
+                } catch (Exception e) {
+                    log.error("调用AI内容审核接口失败", e);
+                }
+            } catch (RuntimeException ex) {
+                XxlJobHelper.handleFail("动态内容审核任务执行失败:" + ex.getMessage());
+                return R.fail("动态内容审核任务执行失败:" + ex.getMessage());
+            }
+        }
+        return R.success("动态内容审核任务执行成功");
+    }
+
+    /**
+     * 获取审核违规内容结果
+     */
+    @XxlJob("getCheckTask")
+    public R<String> getCheckTask() {
+        List<LifeUserDynamics> lifeUserDynamics = lifeUserDynamicsMapper.selectList(new LambdaQueryWrapper<LifeUserDynamics>()
+                .eq(LifeUserDynamics::getCheckFlag, 1).eq(LifeUserDynamics::getDeleteFlag, 0));
+        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);
+        }
+        RestTemplate restTemplateWithAuth = new RestTemplate();
+        if (postForEntity != null && postForEntity.getStatusCodeValue() == 200) {
+            log.info("请求Ai服务登录成功 postForEntity.getBody()\t" + postForEntity.getBody());
+            String responseBody = postForEntity.getBody();
+            JSONObject jsonObject = JSONObject.parseObject(responseBody);
+            if (jsonObject != null) {
+                JSONObject dataJson = jsonObject.getJSONObject("data");
+                String accessToken = dataJson.getString("access_token");
+                List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
+                interceptors.add((request, body, execution) -> {
+                    request.getHeaders().set("Authorization", "Bearer " + accessToken);
+                    return execution.execute(request, body);
+                });
+                restTemplateWithAuth.setInterceptors(interceptors);
+            }
+        }
+
+        List<StoreClockIn> storeClockIns = storeClockInMapper.selectList(new LambdaQueryWrapper<StoreClockIn>().eq(StoreClockIn::getCheckFlag, 1));
+        for (StoreClockIn storeClockIn : storeClockIns) {
+            // 针对已提交且未删除的动态轮询查询结果
+            try {
+                ResponseEntity<String> response = null;
+                try {
+                    response = restTemplateWithAuth.getForEntity(getResultUrl + "?task_id=" + storeClockIn.getAiTaskId(), String.class);
+                    if (response.getStatusCodeValue() != 200) {
+                        log.error("AI内容审核结果获取接口调用失败 http状态:" + response.getStatusCode());
+                    }
+                    JSONObject responseNode = JSONObject.parseObject(response.getBody());
+                    if (responseNode == null) {
+                        log.error("AI接口调用失败,响应内容为空");
+                    }
+                    Integer code = null;
+                    if (responseNode != null) {
+                        code = responseNode.getInteger("code");
+                        if (code == 200) {
+                            JSONObject dataNode = JSONObject.from(responseNode.get("data"));
+                            StoreClockIn clockIn = new StoreClockIn();
+                            clockIn.setId(storeClockIn.getId());
+                            if ("completed".equals(dataNode.get("status"))) {
+                                if (!(boolean) dataNode.get("is_compliant")) {
+                                    // 只要 AI 判定不合规,立即禁用动态并记录原因
+                                    clockIn.setDeleteFlag(1);
+                                    clockIn.setReason(String.valueOf(dataNode.get("failure_reason")));
+                                }
+                                clockIn.setCheckFlag(2);
+                                storeClockInMapper.updateById(clockIn);
+                                if (!(boolean) dataNode.get("is_compliant")) {
+                                    storeClockInMapper.deleteById(clockIn);
+                                }
+                                log.info("动态审核结果获取成功,AI返回内容: {}", response.getBody());
+                                XxlJobHelper.handleSuccess("动态内容审核任务结果获取执行成功");
+                            } else {
+                                log.info("动态审核未完成,AI返回内容: {}", response.getBody());
+                            }
+                        } else {
+                            log.error("AI接口调用失败,错误码: " + code);
+                        }
+                    }
+                } catch (Exception e) {
+                    log.error("调用AI内容审核结果获取接口失败", e);
+                }
+            } catch (RuntimeException ex) {
+                XxlJobHelper.handleFail("动态内容审核任务结果获取执行失败:" + ex.getMessage());
+                return R.fail("动态内容审核任务结果获取执行失败:" + ex.getMessage());
+            }
+        }
+
+        for (LifeUserDynamics lifeUserDynamic : lifeUserDynamics) {
+            // 针对已提交且未删除的动态轮询查询结果
+            try {
+                ResponseEntity<String> response = null;
+                try {
+                    response = restTemplateWithAuth.getForEntity(getResultUrl + "?task_id=" + lifeUserDynamic.getAiTaskId(), String.class);
+                    if (response.getStatusCodeValue() != 200) {
+                        log.error("AI内容审核结果获取接口调用失败 http状态:" + response.getStatusCode());
+                    }
+                    JSONObject responseNode = JSONObject.parseObject(response.getBody());
+                    if (responseNode == null) {
+                        log.error("AI接口调用失败,响应内容为空");
+                    }
+                    Integer code = null;
+                    if (responseNode != null) {
+                        code = responseNode.getInteger("code");
+                        if (code == 200) {
+                            JSONObject dataNode = JSONObject.from(responseNode.get("data"));
+                            LifeUserDynamics dynamics = new LifeUserDynamics();
+                            dynamics.setId(lifeUserDynamic.getId());
+                            if ("completed".equals(dataNode.get("status"))) {
+                                if (!(boolean) dataNode.get("is_compliant")) {
+                                    // 只要 AI 判定不合规,立即禁用动态并记录原因
+                                    dynamics.setEnableStatus(1);
+                                    dynamics.setReason(String.valueOf(dataNode.get("failure_reason")));
+                                }
+                                dynamics.setCheckFlag(2);
+                                lifeUserDynamicsMapper.updateById(dynamics);
+                                log.info("动态审核结果获取成功,AI返回内容: {}", response.getBody());
+                                XxlJobHelper.handleSuccess("动态内容审核任务结果获取执行成功");
+                            } else {
+                                log.info("动态审核未完成,AI返回内容: {}", response.getBody());
+                            }
+                        } else {
+                            log.error("AI接口调用失败,错误码: " + code);
+                        }
+                    }
+                } catch (Exception e) {
+                    log.error("调用AI内容审核结果获取接口失败", e);
+                }
+            } catch (RuntimeException ex) {
+                XxlJobHelper.handleFail("动态内容审核任务结果获取执行失败:" + ex.getMessage());
+                return R.fail("动态内容审核任务结果获取执行失败:" + ex.getMessage());
+            }
+        }
+        return R.success("动态内容审核任务结果获取执行成功");
+    }
+
+    /**
+     * 店铺AI审核任务
+     * <p>
+     * 定时查询 store_info 表中审核状态为 0(待审核)的门店,
+     * 后续可在此处调用 AI 审核接口进行自动审核。
+     * </p>
+     */
+    @XxlJob("aiApproveStoreInfoTask")
+    public R<String> aiApproveStoreInfoTask() {
+        log.info("开始执行店铺AI审核任务...");
+        try {
+            // 1. 查询待审核门店:store_application_status = 0 且 未删除
+            List<StoreInfo> pendingStores = storeInfoMapper.selectList(
+                    new LambdaQueryWrapper<StoreInfo>()
+                            .eq(StoreInfo::getStoreApplicationStatus, 0)
+                            .eq(StoreInfo::getDeleteFlag, 0)
+            );
+
+            if (pendingStores == null || pendingStores.isEmpty()) {
+                log.info("当前无待审核门店,任务结束。");
+                XxlJobHelper.handleSuccess("当前无待审核门店");
+                return R.success("当前无待审核门店");
+            }
+
+            log.info("本次待审核门店数量:{}", pendingStores.size());
+
+            // 2. 登录 AI 服务获取 token(如需调用 AI 审核接口,可在此处复用 token)
+            MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
+            formData.add("username", userName);
+            formData.add("password", passWord);
+
+            HttpHeaders loginHeaders = new HttpHeaders();
+            loginHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+            HttpEntity<MultiValueMap<String, String>> loginRequest = new HttpEntity<>(formData, loginHeaders);
+
+            ResponseEntity<String> loginResponse = null;
+            try {
+                log.info("请求Ai服务登录接口===================> {}", loginUrl);
+                loginResponse = restTemplate.postForEntity(loginUrl, loginRequest, String.class);
+            } catch (Exception e) {
+                log.error("请求AI服务登录接口失败", e);
+            }
+
+            String accessToken = null;
+            if (loginResponse != null && loginResponse.getStatusCodeValue() == 200) {
+                log.info("请求Ai服务登录成功 body={}", loginResponse.getBody());
+                String body = loginResponse.getBody();
+                if (body != null) {
+                    JSONObject jsonObject = JSONObject.parseObject(body);
+                    if (jsonObject != null) {
+                        JSONObject dataJson = jsonObject.getJSONObject("data");
+                        if (dataJson != null) {
+                            accessToken = dataJson.getString("access_token");
+                        }
+                    }
+                }
+            }
+
+            if (accessToken == null) {
+                log.error("获取AI服务 access_token 失败,终止店铺AI审核任务");
+                XxlJobHelper.handleFail("获取AI服务 access_token 失败");
+                return R.fail("获取AI服务 access_token 失败");
+            }
+
+            // 3. 遍历待审核门店,构建 AiApproveStoreInfo 并预留调用 AI 审核接口(具体字段后续补充)
+            HttpHeaders aiHeaders = new HttpHeaders();
+            aiHeaders.setContentType(MediaType.APPLICATION_JSON);
+            aiHeaders.set("Authorization", "Bearer " + accessToken);
+
+            for (StoreInfo storeInfo : pendingStores) {
+                AiApproveStoreInfo aiApproveStoreInfo = new AiApproveStoreInfo();
+
+                HttpEntity<AiApproveStoreInfo> request = new HttpEntity<>(aiApproveStoreInfo, aiHeaders);
+                ResponseEntity<String> response = null;
+                try {
+                    response = restTemplate.postForEntity("http://192.168.2.250:9000/ai/auto-review/api/v1/merchant-onboarding/applications", request, String.class);
+                    if (response.getStatusCodeValue() != 200) {
+                        log.error("店铺AI审核接口调用失败 storeId={}, http状态={}", storeInfo.getId(), response.getStatusCode());
+                        continue;
+                    }
+                    String respBody = response.getBody();
+                    log.info("店铺AI审核返回结果 storeId={}, body={}", storeInfo.getId(), respBody);
+                    // 如需根据 AI 返回结果更新 store_info 审核状态,可在此处解析 respBody 并更新 DB
+                } catch (Exception e) {
+                    log.error("调用店铺AI审核接口异常, storeId={}", storeInfo.getId(), e);
+                }
+            }
+
+            XxlJobHelper.handleSuccess("店铺AI审核任务执行完成");
+            return R.success("店铺AI审核任务执行完成");
+        } catch (Exception e) {
+            log.error("店铺AI审核任务执行异常", e);
+            XxlJobHelper.handleFail("店铺AI审核任务执行异常: " + e.getMessage());
+            return R.fail("店铺AI审核任务执行异常: " + e.getMessage());
+        }
+    }
+
+
+
     class AnalysisRequest {
         private String start_time;
         private String end_time;

+ 419 - 0
alien-job/src/main/java/shop/alien/job/store/BadReviewAppealJob.java

@@ -0,0 +1,419 @@
+package shop.alien.job.store;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+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.apache.commons.collections4.map.HashedMap;
+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.store.StoreComment;
+import shop.alien.entity.store.StoreCommentAppeal;
+import shop.alien.entity.result.R;
+import shop.alien.mapper.StoreCommentAppealMapper;
+import shop.alien.mapper.StoreCommentMapper;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 调用AI差评申诉辅助系统服务类
+ *
+ * @author fcw
+ * @date 2025/11/20 14:21
+ */
+@Slf4j
+@Component
+@RequiredArgsConstructor
+public class BadReviewAppealJob {
+
+    private final RestTemplate restTemplate;
+
+    private final StoreCommentAppealMapper storeCommentAppealMapper;
+
+    private final StoreCommentMapper storeCommentMapper;
+
+//    @Value("${third-party-login.base-url}")
+//    private String loginUrl;
+
+    private String loginUrl = "http://192.168.2.78:9000/ai/user-auth-core/api/v1/auth/login";
+
+
+    @Value("${third-party-user-name.base-url}")
+    private String userName;
+
+    @Value("${third-party-pass-word.base-url}")
+    private String passWord;
+
+    private String analyzeUrl = "http://192.168.2.78:9000/ai/auto-review/api/v1/analyze";
+
+    private String resultUrl = "http://192.168.2.78:9000/ai/auto-review";
+
+
+
+    /**
+     * 差评申述置信度分析接口地址
+     * 例如: http://192.168.2.250:9004/api/v1/analyze 或通过网关: http://192.168.2.250:9000/ai/auto_review/api/v1/analyze
+     */
+//    @Value("${bad-review-analyze.base-url}")
+//    private String analyzeUrl;
+
+    /**
+     * 调用AI服务获取Token
+     */
+    @XxlJob("getBadReviewAppealJob")
+    public R<String> getBadReviewAppealJob() {
+        String accessToken = fetchAiServiceToken();
+        if (!StringUtils.hasText(accessToken)) {
+            return R.fail("调用差评申诉辅助系统登录任务执行失败 返回异常");
+        }
+        return invokeAnalyzeTask(accessToken);
+    }
+
+
+    @XxlJob("getAppealCompletedResult")
+    public R<String> getAppealCompletedResult() {
+        String accessToken = fetchAiServiceToken();
+        if (!StringUtils.hasText(accessToken)) {
+            return R.fail("调用差评申诉辅助系统 登录接口失败");
+        }
+        return getNegativeReviewAppealCompletedResult(accessToken);
+    }
+
+    private R<String> getNegativeReviewAppealCompletedResult(String accessToken) {
+
+
+        HttpHeaders analyzeHeaders = new HttpHeaders();
+        analyzeHeaders.setContentType(MediaType.APPLICATION_JSON);
+        analyzeHeaders.set("Authorization", "Bearer " + accessToken);
+        // 查询所有状态为处理中的申诉
+        List<StoreCommentAppeal> pendingAppeals = storeCommentAppealMapper.getPendingAppeals();
+        // 循环调用查询结果接口
+        for (StoreCommentAppeal appeal : pendingAppeals) {
+            String completedUrl = buildCompletedUrl(appeal.getRecordId());
+
+            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 details = analyzeJson.getJSONObject("details");
+//                    String analysisStatus = details.get("analysis_status").toString();
+//                    if (analysisStatus.equals("pending")) {
+//                        log.error("差评申述置信度分析尚未完成");
+//                        R.fail("差评申述置信度分析尚未完成");
+//                        continue;
+//                    }
+                    JSONObject dataJsonObj = analyzeJson.getJSONObject("data");
+
+                    if (dataJsonObj == null) {
+                        log.error("差评申述置信度分析返回数据为空");
+                        R.fail("差评申述置信度分析返回数据为空");
+                        continue;
+                    }
+
+                    // 获取record_id用于后续查询
+                    Integer recordId = dataJsonObj.getInteger("id");
+                    if (recordId == null) {
+                        log.error("差评申述置信度分析返回record_id为空");
+                        R.fail("差评申述置信度分析返回record_id为空");
+                        continue;
+                    }
+
+                    StoreCommentAppeal sCommentAppeal = new StoreCommentAppeal();
+                    sCommentAppeal.setRecordId(appeal.getRecordId());
+                    // 判断得分大小
+                    if (dataJsonObj.getDouble("user_confidence") > dataJsonObj.getDouble("merchant_confidence")){
+                        sCommentAppeal.setAppealStatus(1);
+                        sCommentAppeal.setFinalResult("已驳回");
+                    } else {
+                        sCommentAppeal.setAppealStatus(2);
+                        sCommentAppeal.setFinalResult("已同意");
+                        //假删除评论
+                        StoreComment storeComment = new StoreComment();
+                        storeComment.setId(appeal.getCommentId());
+                        storeComment.setDeleteFlag(1);
+                        storeCommentMapper.updateById(storeComment);
+                    }
+                    sCommentAppeal.setAppealAiApproval(dataJsonObj.toJSONString());
+
+                    sCommentAppeal.setRecordId(recordId);
+                    storeCommentAppealMapper.updateByRecordId(appeal.getRecordId(),
+                            sCommentAppeal.getAppealStatus(),
+                            sCommentAppeal.getFinalResult());
+                } else {
+                    if (analyzeResp != null) {
+                        log.error("调用差评申述置信度分析接口失败, http状态: {}", analyzeResp.getStatusCode());
+                        R.fail("调用差评申述置信度分析接口失败, http状态: " + analyzeResp.getStatusCode());
+                    }
+                }
+            } catch (Exception e) {
+                log.error("调用差评申述查询结果接口异常", e);
+            }
+        }
+        return R.success("调用差评申述置信度分析结果接口完成");
+    }
+
+
+
+
+    private R<String> invokeAnalyzeTask(String token) {
+        log.info("开始调用差评申述置信度分析接口, url: {}", analyzeUrl);
+
+        HttpHeaders analyzeHeaders = new HttpHeaders();
+        analyzeHeaders.setContentType(MediaType.APPLICATION_JSON);
+        analyzeHeaders.set("Authorization", "Bearer " + token);
+
+        // 查询一段时间内的差评申述
+        // 循环插入
+        List<Map<String, Object>> appealList = storeCommentAppealMapper.getAppealList();
+
+        if (appealList == null || appealList.isEmpty()) {
+            log.info("没有需要处理的差评申述");
+            return R.success("没有需要处理的差评申述");
+        }
+
+        for (Map<String, Object> storeCommentAppeal : appealList) {
+            Map<String, Object> analyzeRequest = new HashedMap<>();
+
+            // 商家申诉材料
+            analyzeRequest.put("merchant_material",
+                    storeCommentAppeal.get("appeal_reason") == null ? "" : storeCommentAppeal.get("appeal_reason").toString());
+
+            // 用户差评内容
+            analyzeRequest.put("user_material",
+                    storeCommentAppeal.get("comment_content") == null ? "" : storeCommentAppeal.get("comment_content").toString());
+
+            // 商家图片:支持多张,转成 Base64 数组
+            List<String> merchantImages = new ArrayList<>();
+            String imgUrls = storeCommentAppeal.get("img_url") == null ? "" : storeCommentAppeal.get("img_url").toString();
+            if (StringUtils.hasText(imgUrls)) {
+                // 假设 img_url 是多个图片用逗号分隔的字符串
+                for (String imageUrl : imgUrls.split(",")) {
+                    String base64 = convertImageToBase64(imageUrl.trim());
+                    if (StringUtils.hasText(base64)) {
+                        merchantImages.add(base64);
+                    }
+                }
+            }
+            analyzeRequest.put("merchant_images", merchantImages);
+
+            // 用户图片:同理
+            List<String> userImages = new ArrayList<>();
+            String userImgUrls = storeCommentAppeal.get("user_img_url") == null ? "" : storeCommentAppeal.get("user_img_url").toString();
+            if (StringUtils.hasText(userImgUrls)) {
+                for (String imageUrl : userImgUrls.split(",")) {
+                    String base64 = convertImageToBase64(imageUrl.trim());
+                    if (StringUtils.hasText(base64)) {
+                        userImages.add(base64);
+                    }
+                }
+            }
+            analyzeRequest.put("user_images", userImages);
+
+            // 其他字段
+            analyzeRequest.put("case_id", storeCommentAppeal.get("comment_id") == null ? "" : storeCommentAppeal.get("comment_id").toString());
+            analyzeRequest.put("order_id", storeCommentAppeal.get("business_id") == null ? "" : storeCommentAppeal.get("business_id").toString());
+
+            HttpEntity<Map<String, Object>> analyzeEntity = new HttpEntity<>(analyzeRequest, analyzeHeaders);
+
+            ResponseEntity<String> analyzeResp = null;
+            try {
+                analyzeResp = restTemplate.postForEntity(analyzeUrl, analyzeEntity, String.class);
+            } catch (org.springframework.web.client.HttpServerErrorException.ServiceUnavailable e) {
+                log.error("调用差评申述置信度分析接口返回503 Service Unavailable错误: {}", e.getResponseBodyAsString());
+                continue;
+            } catch (Exception e) {
+                log.error("调用差评申述置信度分析接口异常", e);
+                continue;
+            }
+
+            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;
+                }
+
+                // 获取record_id用于后续查询
+                Integer recordId = dataJsonObj.getInteger("record_id");
+                if (recordId == null) {
+                    log.error("差评申述置信度分析返回record_id为空");
+                    R.fail("差评申述置信度分析返回record_id为空");
+                    continue;
+                }
+
+                //修改评论状态为"处理中"
+                StoreCommentAppeal sCommentAppeal = new StoreCommentAppeal();
+                sCommentAppeal.setId((Integer) storeCommentAppeal.get("id"));
+                sCommentAppeal.setAppealStatus(0);
+                sCommentAppeal.setRecordId(recordId);
+                storeCommentAppealMapper.updateById(sCommentAppeal);
+
+            } else {
+                if (analyzeResp != null) {
+                    log.error("调用差评申述置信度分析接口失败, http状态: {}", analyzeResp.getStatusCode());
+                    R.fail("调用差评申述置信度分析接口失败, http状态: " + analyzeResp.getStatusCode());
+                }
+            }
+        }
+        return R.success("调用差评申述置信度分析接口完成");
+    }
+
+    /**
+     * 将图片URL转换为Base64编码
+     *
+     * @param imageUrl 图片URL
+     * @return Base64编码字符串
+     */
+    private String convertImageToBase64(String imageUrl) {
+        // 1. 检查是否为空
+        if (!StringUtils.hasText(imageUrl)) {
+            log.warn("图片URL为空");
+            return "";
+        }
+
+        // 2. 对URL进行编码处理(解决特殊字符问题)
+        String encodedUrl = encodeImageUrl(imageUrl);
+
+        // 3. 验证URL格式
+        if (!isValidUrl(encodedUrl)) {
+            log.warn("无效的图片URL: {}", imageUrl);
+            return "";
+        }
+
+        try {
+            // 4. 下载图片并转换Base64
+            byte[] imageBytes = restTemplate.getForObject(encodedUrl, byte[].class);
+            if (imageBytes != null) {
+                return java.util.Base64.getEncoder().encodeToString(imageBytes);
+            }
+        } catch (org.springframework.web.client.HttpClientErrorException.NotFound e) {
+            log.warn("图片不存在 (404), URL: {}", imageUrl);
+            return "";
+        } catch (Exception e) {
+            log.error("图片转换为Base64失败, URL: {}", imageUrl, e);
+            return "";
+        }
+        return "";
+    }
+
+    // 新增方法:对URL中的特殊字符进行编码
+    private String encodeImageUrl(String imageUrl) {
+        try {
+            URI uri = new URI(imageUrl);
+            String scheme = uri.getScheme();
+            String host = uri.getHost();
+            String path = uri.getPath();
+            String query = uri.getQuery();
+
+            // 对路径中的特殊字符进行编码
+            String encodedPath = java.net.URLEncoder.encode(path, "UTF-8")
+                    .replace("%2F", "/")  // 保留斜杠
+                    .replace("+", "%20"); // 空格编码
+
+            StringBuilder encodedUrl = new StringBuilder();
+            encodedUrl.append(scheme).append("://").append(host).append(encodedPath);
+
+            if (query != null) {
+                encodedUrl.append("?").append(query);
+            }
+
+            return encodedUrl.toString();
+        } catch (Exception e) {
+            log.warn("URL编码失败,使用原始URL: {}", imageUrl);
+            return imageUrl;
+        }
+    }
+
+
+
+    // 辅助方法:验证URL格式合法性
+    private boolean isValidUrl(String url) {
+        try {
+            // 尝试构造URI,验证格式
+            new URI(url);
+            // 进一步检查是否以http/https开头(可选,根据业务需求)
+            return url.startsWith("http://") || url.startsWith("https://");
+        } catch (URISyntaxException e) {
+            return false;
+        }
+    }
+
+    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);
+
+        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);
+        } catch (Exception e) {
+            log.error("调用差评申诉辅助系统登录接口异常", e);
+        }
+        return null;
+    }
+
+    private String buildCompletedUrl(Integer recordId) {
+        String baseUrl = resultUrl;
+        if (!StringUtils.hasText(baseUrl)) {
+            throw new IllegalStateException("差评申述分析接口地址未配置");
+        }
+        if (baseUrl.endsWith("/")) {
+            baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
+        }
+        String completedBase = baseUrl.replace("/api/v1/analyze", "");
+        if (!completedBase.endsWith("/")) {
+            completedBase = completedBase + "/";
+        }
+        return completedBase + "api/v1/records/" + recordId + "/completed";
+    }
+
+}

+ 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 - 1
alien-job/src/main/resources/bootstrap.yml

@@ -1,3 +1,3 @@
 spring:
   profiles:
-    active: dev
+    active: test

+ 11 - 0
alien-lawyer/src/main/java/shop/alien/lawyer/feign/AlienStoreFeign.java

@@ -2,7 +2,12 @@ package shop.alien.lawyer.feign;
 
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestParam;
+import shop.alien.entity.result.R;
+
+import java.util.Map;
 
 /**
  * @author ssk
@@ -25,4 +30,10 @@ public interface AlienStoreFeign {
                          @RequestParam(value = "refundAmount") String refundAmount,
                          @RequestParam(value = "refundReason") String refundReason,
                          @RequestParam(value = "partialRefundCode") String partialRefundCode);
+
+    /**
+     * 微信/支付宝退款
+     */
+    @PostMapping("payment/refunds")
+    R paymentRefunds(@RequestBody Map<String, String> params);
 }

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

@@ -3,7 +3,6 @@ package shop.alien.lawyer.service.impl;
 import com.alibaba.fastjson2.JSON;
 import com.alibaba.fastjson2.JSONObject;
 import com.alibaba.nacos.common.utils.CollectionUtils;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;

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

@@ -33,10 +33,7 @@ import shop.alien.util.common.constant.LawyerStatusEnum;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
-
 import java.text.SimpleDateFormat;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -451,6 +448,7 @@ public class LawyerConsultationOrderServiceImpl extends ServiceImpl<LawyerConsul
         order.setAlipayNo(lawyerConsultationOrder.getAlipayNo());
         order.setOrderStr(lawyerConsultationOrder.getOrderStr());
         order.setPlaceId(lawyerConsultationOrder.getPlaceId());
+        order.setPayType(lawyerConsultationOrder.getPayType());
 
         // 设置订单状态
         order.setOrderStatus(0); // 待支付
@@ -541,6 +539,12 @@ public class LawyerConsultationOrderServiceImpl extends ServiceImpl<LawyerConsul
                 request.getOrderNumber(), request.getPaymentStatus(), request.getOrderStatus());
 
         LawyerConsultationOrderDto order = new LawyerConsultationOrderDto();
+        if (null != request.getOrderStr()){
+            order.setOrderStr(request.getOrderStr());
+        }
+        if (null != request.getAlipayNo()){
+            order.setAlipayNo(request.getAlipayNo());
+        }
         order.setOrderNumber(request.getOrderNumber());
         order.setPaymentStatus(request.getPaymentStatus());
         order.setOrderStatus(request.getOrderStatus());

+ 20 - 0
alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/LawyerUserViolationServiceImpl.java

@@ -1032,6 +1032,12 @@ public class LawyerUserViolationServiceImpl extends ServiceImpl<LawyerUserViolat
                } else {
                    log.warn("订单状态更新失败,订单编号:{}", violation.getOrderNumber());
                }
+            } else {
+                // 审批驳回
+                log.info("订单状态更新成功,订单编号:{}", violation.getOrderNumber());
+
+                // 构建并发送通知消息
+                sendApprovalNotifications(violation, processingStatus, reportResult);
             }
 
 
@@ -1232,6 +1238,20 @@ public class LawyerUserViolationServiceImpl extends ServiceImpl<LawyerUserViolat
             // 发送WebSocket消息
             sendWebSocketMessage(receiverId, lifeNotice);
 
+
+
+            // 创建并保存到账通知
+
+            String notificationInfo1 = "您的编号为" + violation.getOrderNumber() + "的订单,订单金额已原路返还至您的支付渠道,请查收";
+            LifeNotice lifeNotice1 = createLifeNotice(violation.getId(), receiverId,
+                    "退款到账通知", notificationInfo1);
+            lifeNoticeMapper.insert(lifeNotice1);
+
+            // 发送WebSocket消息
+            sendWebSocketMessage(receiverId, lifeNotice1);
+
+
+
             log.info("举报人通知发送成功,接收人ID:{}", receiverId);
 
         } catch (Exception e) {

+ 63 - 25
alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/OrderExpirationServiceImpl.java

@@ -9,23 +9,28 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.CommandLineRunner;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import shop.alien.entity.result.R;
 import shop.alien.entity.store.LawyerConsultationOrder;
 import shop.alien.entity.store.LifeNotice;
 import shop.alien.entity.store.vo.WebSocketVo;
 import shop.alien.lawyer.config.BaseRedisService;
 import shop.alien.lawyer.config.WebSocketProcess;
 import shop.alien.lawyer.controller.AliController;
+import shop.alien.lawyer.feign.AlienStoreFeign;
 import shop.alien.lawyer.listener.RedisKeyExpirationHandler;
 import shop.alien.lawyer.service.OrderExpirationService;
 import shop.alien.mapper.LawyerConsultationOrderMapper;
 import shop.alien.mapper.LifeNoticeMapper;
 import shop.alien.mapper.LifeUserMapper;
 import shop.alien.util.common.DateUtils;
+import shop.alien.util.common.constant.PaymentEnum;
 
 
 import javax.annotation.PostConstruct;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * 訂單過期處理服務實現類
@@ -51,6 +56,7 @@ public class OrderExpirationServiceImpl implements OrderExpirationService, Comma
     private final LifeNoticeMapper lifeNoticeMapper;
     private final LifeUserMapper lifeUserMapper;
     private final WebSocketProcess webSocketProcess;
+    private final AlienStoreFeign alienStoreFeign;
 
     /**
      * Redis key前綴:訂單支付超時
@@ -147,11 +153,6 @@ public class OrderExpirationServiceImpl implements OrderExpirationService, Comma
 
                 log.info("檢測到有訂單需要退款,訂單no: {}", orderNo);
 
-                // 處理訂單退款
-                aliController.processRefund(order.getAlipayNo(),  new BigDecimal(order.getOrderAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP).toString(), refundReason,"");
-
-                log.info("訂單退款成功,訂單no: {}", orderNo);
-
                 //通知
                 LifeNotice lifeNotice = buildUserLifeNotice(order, title, message);
                 WebSocketVo webSocketVo = buildWebSocketVo(lifeNotice);
@@ -161,11 +162,32 @@ public class OrderExpirationServiceImpl implements OrderExpirationService, Comma
 
                 log.info("系统通知发送成功,訂單no: {}", orderNo);
 
-                LawyerConsultationOrder update = new LawyerConsultationOrder();
-                update.setId(order.getId());
-                update.setOrderStatus(5);
-                orderMapper.updateById( update);
+                // 處理訂單退款
+                //aliController.processRefund(order.getAlipayNo(),  new BigDecimal(order.getOrderAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP).toString(), refundReason,"");
+
+                // 微信/支付宝退款
+                Map<String, String> paramMap = new HashMap<>();
+                refundParam(paramMap, order, refundReason);
+                R refunds = alienStoreFeign.paymentRefunds(paramMap);
+
+                if (refunds.getCode() == 200) {
+                    log.info("訂單退款成功,訂單no: {}", orderNo);
+
+                    //退款到账通知
+                    LifeNotice lifeNotice2 = buildUserLifeNotice(order, "退款到账通知", "您的编号为" + orderNo + "的订单,订单金额已原路返还至您的支付渠道,请查收。");
+                    WebSocketVo webSocketVo2 = buildWebSocketVo(lifeNotice2);
+                    lifeNotice2.setCreatedTime(DateUtils.calcMinute(lifeNotice2.getCreatedTime(), 2));
+
+                    lifeNoticeMapper.insert(lifeNotice2);
+                    webSocketProcess.sendMessage(lifeNotice2.getReceiverId(), JSONObject.from(webSocketVo2).toJSONString());
+
+                    log.info("系统通知发送成功,訂單no: {}", orderNo);
 
+                    LawyerConsultationOrder update = new LawyerConsultationOrder();
+                    update.setId(order.getId());
+                    update.setOrderStatus(5);
+                    orderMapper.updateById( update);
+                }
             }
             //申请退款 律师没处理
             if (expiredKey.contains(ORDER_REFUND_TIMEOUT_PREFIX)) {
@@ -179,30 +201,28 @@ public class OrderExpirationServiceImpl implements OrderExpirationService, Comma
 
                 log.info("檢測到有訂單需要退款,訂單no: {}", orderNo);
 
+                //同意退款通知
+                LifeNotice lifeNotice = buildUserLifeNotice(order, "同意退款通知", "您的编号为" + orderNo + "的订单,律师已同意您的退款申请,订单金额将在1-3个工作日原路返还,请注意查收。");
+                WebSocketVo webSocketVo = buildWebSocketVo(lifeNotice);
+
+                lifeNoticeMapper.insert(lifeNotice);
+                webSocketProcess.sendMessage(lifeNotice.getReceiverId(), JSONObject.from(webSocketVo).toJSONString());
+
                 // 處理訂單退款
-                String refundResult = aliController.processRefund(order.getAlipayNo(), new BigDecimal(order.getOrderAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP).toString(), refundReason, "");
+                //String refundResult = aliController.processRefund(order.getAlipayNo(), new BigDecimal(order.getOrderAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP).toString(), refundReason, "");
 
                 // 微信/支付宝退款
-                /*paramMap.put("payType", "1".equals(order.getPayType()) ? PaymentEnum.ALIPAY.getType() : PaymentEnum.WECHAT_PAY.getType());
-                paramMap.put("outTradeNo", order.getAlipayNo());
-                paramMap.put("refundReason", refundReason);
-                paramMap.put("refundAmount", new BigDecimal(order.getOrderAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP).toString());
-                R refunds = alienStoreFeign.paymentRefunds(paramMap);*/
+                Map<String, String> paramMap = new HashMap<>();
+                refundParam(paramMap, order, refundReason);
+                R refunds = alienStoreFeign.paymentRefunds(paramMap);
 
-                if ("调用成功".equals(refundResult)) {
+                if (refunds.getCode() == 200) {
                     log.info("訂單退款成功,訂單no: {}", orderNo);
 
-                    //同意退款通知
-                    LifeNotice lifeNotice = buildUserLifeNotice(order, "同意退款通知", "您的编号为" + orderNo + "的订单,律师已同意您的退款申请,订单金额将在1-3个工作日原路返还,请注意查收。");
-                    WebSocketVo webSocketVo = buildWebSocketVo(lifeNotice);
-
-                    lifeNoticeMapper.insert(lifeNotice);
-                    webSocketProcess.sendMessage(lifeNotice.getReceiverId(), JSONObject.from(webSocketVo).toJSONString());
-
                     //退款到账通知
                     LifeNotice lifeNotice2 = buildUserLifeNotice(order, "退款到账通知", "您的编号为" + orderNo + "的订单,订单金额已原路返还至您的支付渠道,请查收。");
-                    WebSocketVo webSocketVo2 = buildWebSocketVo(lifeNotice);
-                    lifeNotice2.setCreatedTime(DateUtils.calcMinute(lifeNotice.getCreatedTime(), 2));
+                    WebSocketVo webSocketVo2 = buildWebSocketVo(lifeNotice2);
+                    lifeNotice2.setCreatedTime(DateUtils.calcMinute(lifeNotice2.getCreatedTime(), 2));
 
                     lifeNoticeMapper.insert(lifeNotice2);
                     webSocketProcess.sendMessage(lifeNotice2.getReceiverId(), JSONObject.from(webSocketVo2).toJSONString());
@@ -221,6 +241,24 @@ public class OrderExpirationServiceImpl implements OrderExpirationService, Comma
         }
     }
 
+    private void refundParam(Map<String,String> paramMap,LawyerConsultationOrder order,String refundReason){
+        //支付宝
+        if ("1".equals(order.getPayType())) {
+            paramMap.put("payType", PaymentEnum.ALIPAY.getType());
+            paramMap.put("outTradeNo", order.getAlipayNo());
+            paramMap.put("refundReason", refundReason);
+            paramMap.put("refundAmount", new BigDecimal(order.getOrderAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP).toString());
+        }
+        //微信
+        if ("2".equals(order.getPayType())) {
+            paramMap.put("payType", PaymentEnum.WECHAT_PAY.getType());
+            paramMap.put("outTradeNo", order.getAlipayNo());
+            paramMap.put("reason", refundReason);
+            paramMap.put("refundAmount", order.getOrderAmount().toString());
+            paramMap.put("totalAmount", order.getOrderAmount().toString());
+        }
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void handleOrderPaymentTimeout(String orderNum) {

+ 2 - 31
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);
                     // 更新订单申诉状态失败不影响删除评价的操作
                 }
@@ -661,34 +661,5 @@ public class OrderReviewServiceImpl extends ServiceImpl<OrderReviewMapper, Order
             return R.fail("获取统计数据失败");
         }
     }
-
-    @Override
-    public R<OrderReviewVo> getOrderEvaluation(Integer orderId) {
-        log.info("OrderReviewServiceImpl.getOrderEvaluation?orderId={}", orderId);
-
-        if (orderId == null) {
-            return R.fail("订单ID不能为空");
-        }
-
-        OrderReviewVo reviewVo = orderReviewMapper.getOrderEvaluation(orderId);
-        if (reviewVo == null) {
-            return R.fail("该订单暂无评价");
-        }
-
-        // 处理评价图片:从JSON字符串解析为List
-        if (reviewVo.getReviewImagesJson() != null && !reviewVo.getReviewImagesJson().trim().isEmpty()) {
-            try {
-                List<String> images = JSON.parseArray(reviewVo.getReviewImagesJson(), String.class);
-                reviewVo.setReviewImages(images != null ? images : new ArrayList<>());
-            } catch (Exception e) {
-                log.warn("解析评价图片失败:{}", e.getMessage());
-                reviewVo.setReviewImages(new ArrayList<>());
-            }
-        } else {
-            reviewVo.setReviewImages(new ArrayList<>());
-        }
-
-        return R.data(reviewVo);
-    }
 }
 

+ 86 - 0
alien-second/src/main/java/shop/alien/second/service/SecondGoodsAuditService.java

@@ -0,0 +1,86 @@
+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;
+
+import java.util.List;
+
+/**
+ * 二手商品审核服务接口
+ * 负责商品的图片、文本、视频审核相关业务逻辑
+ */
+public interface SecondGoodsAuditService {
+
+    /**
+     * 执行内容审核(图片、文本和视频)
+     * @param goodsDTO 商品信息DTO
+     * @param goods 商品实体
+     * @throws Exception 审核过程中可能抛出的异常
+     */
+    void performContentReview(SecondGoodsVo goodsDTO, SecondGoods goods) throws Exception;
+
+    /**
+     * 执行图片审核
+     * @param goods 商品信息
+     * @param goodsDTO 商品DTO信息
+     * @return 审核结果,true表示通过,false表示不通过
+     * @throws Exception 审核过程中可能抛出的异常
+     */
+    boolean performImageReviews(SecondGoods goods, SecondGoodsVo goodsDTO) throws Exception;
+
+    /**
+     * 执行文本审核
+     * @param goods 商品信息
+     * @param goodsDTO 商品DTO信息
+     * @return 审核结果,true表示通过,false表示不通过
+     * @throws Exception 审核过程中可能抛出的异常
+     */
+    boolean performTextReview(SecondGoods goods, SecondGoodsVo goodsDTO) throws Exception;
+
+    /**
+     * 执行视频审核
+     * @param goods 商品信息
+     * @param goodsDTO 商品DTO信息
+     * @return 视频审核任务ID列表
+     */
+    List<String> performVideoReviews(SecondGoods goods, SecondGoodsVo goodsDTO);
+
+    /**
+     * 处理视频审核结果
+     * @param task 视频审核任务
+     */
+    void processVideoModerationResult(SecondVideoTask task);
+
+    /**
+     * 审核通过后上架商品
+     * @param goods 商品信息
+     */
+    void approveAndListGoods(SecondGoods goods);
+
+    /**
+     * 创建商品审核记录
+     * @param goods 商品信息
+     * @param failReason 审核失败原因
+     * @param goodsStatus 商品状态
+     */
+    void createGoodsAudit(SecondGoods goods, String failReason, Integer goodsStatus);
+
+    /**
+     * 从图片URL列表中提取视频URL
+     * @param imageUrls 图片URL列表
+     * @return 视频URL列表
+     */
+    List<String> extractVideoUrls(List<String> imageUrls);
+
+    /**
+     * 判断URL是否为视频地址
+     * @param url 输入URL
+     * @return 是否为视频地址
+     */
+    boolean isVideoUrl(String url);
+
+    boolean performSecondRoundReview(SecondGoods goods, SecondGoodsVo goodsDTO);
+}
+

+ 29 - 0
alien-second/src/main/java/shop/alien/second/service/SecondGoodsNotificationService.java

@@ -0,0 +1,29 @@
+package shop.alien.second.service;
+
+import shop.alien.entity.second.SecondGoods;
+
+/**
+ * 二手商品消息通知服务接口
+ * 负责商品相关的消息通知业务逻辑
+ */
+public interface SecondGoodsNotificationService {
+
+    /**
+     * 发送审核成功消息
+     * @param goods 商品信息
+     */
+    void sendMessage(SecondGoods goods);
+
+    /**
+     * 发送审核失败消息
+     * @param goods 商品信息
+     */
+    void sendFailedMsg(SecondGoods goods);
+
+    /**
+     * 发送商品下架消息
+     * @param goods 商品信息
+     */
+    void sendShelveMessage(SecondGoods goods);
+}
+

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

@@ -0,0 +1,18 @@
+package shop.alien.second.service;
+
+import shop.alien.entity.second.SecondGoods;
+
+/**
+ * 二手商品操作历史记录服务接口
+ * 负责记录商品的各种操作历史
+ */
+public interface SecondGoodsOperationRecordService {
+
+    /**
+     * 记录商品操作历史
+     * @param goods 商品信息
+     * @param operationName 操作名称
+     */
+    void recordGoodsOperation(SecondGoods goods, String operationName);
+}
+

+ 546 - 0
alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsAuditServiceImpl.java

@@ -0,0 +1,546 @@
+package shop.alien.second.service.impl;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+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.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+import shop.alien.entity.SecondVideoTask;
+import shop.alien.entity.second.SecondGoods;
+import shop.alien.entity.second.SecondGoodsAudit;
+import shop.alien.entity.second.SecondGoodsRecord;
+import shop.alien.entity.second.enums.SecondGoodsStatusEnum;
+import shop.alien.entity.second.vo.SecondGoodsVo;
+import shop.alien.entity.store.SecondAiTask;
+import shop.alien.entity.store.StoreImg;
+import shop.alien.mapper.SecondAiTaskMapper;
+import shop.alien.mapper.StoreImgMapper;
+import shop.alien.mapper.second.SecondGoodsAuditMapper;
+import shop.alien.mapper.second.SecondGoodsMapper;
+import shop.alien.mapper.second.SecondGoodsRecordMapper;
+import shop.alien.second.service.*;
+import shop.alien.second.util.AiTaskUtils;
+import shop.alien.util.common.Constants;
+import shop.alien.util.common.safe.ImageModerationResultVO;
+import shop.alien.util.common.safe.ImageModerationUtil;
+import shop.alien.util.common.safe.ImageReviewServiceEnum;
+import shop.alien.util.common.safe.TextModerationResultVO;
+import shop.alien.util.common.safe.TextModerationUtil;
+import shop.alien.util.common.safe.TextReviewServiceEnum;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 二手商品审核服务实现类
+ * 负责商品的图片、文本、视频审核相关业务逻辑
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class SecondGoodsAuditServiceImpl implements SecondGoodsAuditService {
+
+    private final SecondAiTaskMapper secondAiTaskMapper;
+    private final StoreImgMapper storeImgMapper;
+    /**
+     * 视频审核功能是否启用的配置项
+     */
+    @Value("${video.moderation.enabled}")
+    private boolean videoModerationEnabled;
+
+    /**
+     * 视频审核失败时是否阻塞商品发布的配置项
+     */
+    @Value("${video.moderation.block-on-failure}")
+    private boolean videoModerationBlockOnFailure;
+
+    /**
+     * 视频审核服务,用于处理商品中视频内容的审核
+     */
+    private final VideoModerationService videoModerationService;
+
+    /**
+     * 文本审核工具,用于审核商品标题、描述等文本内容
+     */
+    private final TextModerationUtil textModerationUtil;
+
+    /**
+     * 图片审核工具,用于审核商品图片内容
+     */
+    private final ImageModerationUtil imageModerationUtil;
+
+    /**
+     * 二手商品Mapper
+     */
+    private final SecondGoodsMapper secondGoodsMapper;
+
+    /**
+     * 二手商品审核Mapper
+     */
+    private final SecondGoodsAuditMapper secondGoodsAuditMapper;
+
+    /**
+     * 商品操作历史记录Mapper
+     */
+    private final SecondGoodsRecordMapper secondGoodsRecordMapper;
+
+    /**
+     * 消息通知服务
+     */
+    private final SecondGoodsNotificationService notificationService;
+
+    /**
+     * 操作历史记录服务
+     */
+    private final SecondGoodsOperationRecordService operationRecordService;
+
+    private final AiTaskUtils aiTaskUtil;
+
+    /**
+     * 执行内容审核
+     * @param goodsDTO 商品信息
+     * @param goods 商品实体
+     */
+    @Override
+    public void performContentReview(SecondGoodsVo goodsDTO, SecondGoods goods) throws Exception {
+        // 图片审核
+        boolean imageAuditResult = performImageReviews(goods, goodsDTO);
+        
+        // 审核失败,直接返回
+        if (!imageAuditResult) {
+            // 图片审核不通过,记录操作历史
+            operationRecordService.recordGoodsOperation(goods, "图片审核失败");
+            return;
+        }
+
+        // 文本审核
+        boolean textAuditResult = performTextReview(goods, goodsDTO);
+        
+        // 审核失败,直接返回
+        if (!textAuditResult) {
+            // 文本审核不通过,记录操作历史
+            operationRecordService.recordGoodsOperation(goods, "文本审核失败");
+            return;
+        }
+        
+        // 视频审核
+        List<String> taskIds = performVideoReviews(goods, goodsDTO);
+
+        // 如果成功提交了视频审核任务,设置商品状态为审核中
+        if (!taskIds.isEmpty()) {
+            goods.setGoodsStatus(SecondGoodsStatusEnum.UNDER_REVIEW.getCode()); // 审核中
+            goods.setVideoTaskId(taskIds.get(0)); // 保存第一个任务ID到商品表
+            goods.setFailedReason("");
+            secondGoodsMapper.updateById(goods);
+            // 审核中审核记录
+            createGoodsAudit(goods, "", Constants.AuditStatus.UNDER_REVIEW);
+        } else {
+            // 第二轮AI审核
+            boolean b = performSecondRoundReview(goods, goodsDTO);
+            if (!b) {
+                // 第二轮审核失败,记录操作历史
+                operationRecordService.recordGoodsOperation(goods, "第二轮审核失败");
+                goods.setGoodsStatus(2);
+                goods.setFailedReason("调用AI接口失败,未获取到task_id");
+                secondGoodsMapper.updateById(goods);
+            }
+        }
+        
+        // 审核通过后上架商品
+//        approveAndListGoods(goods);
+    }
+
+    // 第二轮审核(AI)
+    @Override
+    public boolean performSecondRoundReview(SecondGoods goods, SecondGoodsVo goodsDTO) {
+        try {
+            // 参数校验
+            if (goodsDTO == null || CollectionUtil.isEmpty(goodsDTO.getImgUrl())) {
+                log.warn("Second round review skipped: empty image URLs for goods id={}",
+                        goods != null ? goods.getId() : "unknown");
+                return false;
+            }
+
+            // 获取访问令牌
+            String accessToken = aiTaskUtil.getAccessToken();
+            if (StringUtils.isEmpty(accessToken)) {
+                log.error("Failed to obtain access token for second round review, goods id={}", goods.getId());
+                return false;
+            }
+
+            // 创建AI任务
+            String taskId = aiTaskUtil.createTask(accessToken, goods.getDescription(), goodsDTO.getImgUrl());
+            if (StringUtils.isEmpty(taskId)) {
+                log.warn("Failed to create AI task for second round review, goods id={}", goods.getId());
+                return false;
+            }
+            goods.setAiTaskId(taskId);
+            goods.setGoodsStatus(SecondGoodsStatusEnum.UNDER_REVIEW.getCode());
+            secondGoodsMapper.updateById(goods);
+
+            // 保存任务信息
+            SecondAiTask secondAiTask = new SecondAiTask();
+            secondAiTask.setTaskId(taskId);
+            secondAiTask.setStatus("PROCESSING");
+            Date currentTime = new Date();
+            secondAiTask.setCreateTime(currentTime);
+            secondAiTask.setUpdateTime(currentTime);
+            secondAiTaskMapper.insert(secondAiTask);
+
+            log.info("Successfully created second round AI review task, taskId={}, goodsId={}",
+                    taskId, goods.getId());
+            return true;
+        } catch (Exception e) {
+            log.error("Error during second round review for goods id={}",
+                    goods != null ? goods.getId() : "unknown", e);
+            return false;
+        }
+    }
+
+
+    /**
+     * 执行图片审核
+     * @param goods 商品信息
+     * @param goodsDTO 商品DTO信息
+     * @return 审核结果
+     */
+    @Override
+    public boolean performImageReviews(SecondGoods goods, SecondGoodsVo goodsDTO) throws Exception {
+        // 图片审核(循环处理)
+        List<String> imageUrls = goodsDTO.getImgUrl();
+        // 根据imageUrls过滤不是图片的url
+        imageUrls = imageUrls.stream()
+                .filter(url -> url.toLowerCase().endsWith(".jpg") 
+                        || url.toLowerCase().endsWith(".png") 
+                        || url.toLowerCase().endsWith(".jpeg") 
+                        || url.toLowerCase().endsWith(".gif"))
+                .collect(Collectors.toList());
+        
+        // 图片审核
+        if (imageUrls != null && !imageUrls.isEmpty()) {
+            for (String imageUrl : imageUrls) {
+                List<String> imgServicesList = Lists.newArrayList();
+                // 内容治理检测 + AIGC图片风险检测
+                imgServicesList.add(ImageReviewServiceEnum.TONALITY_IMPROVE.getService());
+                imgServicesList.add(ImageReviewServiceEnum.AIGC_CHECK.getService());
+                
+                ImageModerationResultVO response = imageModerationUtil.productPublishCheck(imageUrl, imgServicesList);
+                if ("high".equals(response.getRiskLevel())) {
+                    // 图片审核不通过或存在高风险
+                    goods.setGoodsStatus(SecondGoodsStatusEnum.REVIEW_FAILED.getCode()); // 审核失败
+                    String failReason = "图片审核不通过:图片中包含" + 
+                            (response.getDescriptions() != null ? response.getDescriptions() : "高风险内容");
+                    goods.setFailedReason(failReason);
+                    // 插入审核记录
+                    createGoodsAudit(goods, failReason, Constants.AuditStatus.FAILED);
+                    // 发送审核失败消息
+                    notificationService.sendFailedMsg(goods);
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * 执行文本审核
+     * @param goods 商品信息
+     * @param goodsDTO 商品DTO信息
+     * @return 审核结果
+     */
+    @Override
+    public boolean performTextReview(SecondGoods goods, SecondGoodsVo goodsDTO) throws Exception {
+        List<String> servicesList = Lists.newArrayList();
+        servicesList.add(TextReviewServiceEnum.AD_COMPLIANCE_DETECTION_PRO.getService());
+        servicesList.add(TextReviewServiceEnum.LLM_QUERY_MODERATION.getService());
+        
+        // 使用商品发布场景的审核服务
+        String test = goodsDTO.getDescription() + goodsDTO.getTitle() + goods.getLabel() + goods.getTopic();
+        TextModerationResultVO textCheckResult = textModerationUtil.invokeFunction(test, servicesList);
+
+        if ("high".equals(textCheckResult.getRiskLevel())) {
+            // 文本审核不通过或存在高风险
+            goods.setGoodsStatus(SecondGoodsStatusEnum.REVIEW_FAILED.getCode()); // 审核失败
+            String failReason = "文本审核不通过:" + 
+                    (textCheckResult.getRiskWords() != null ? textCheckResult.getRiskWords() : "存在高风险内容");
+            goods.setFailedReason(failReason);
+            // 插入审核记录
+            createGoodsAudit(goods, failReason, Constants.AuditStatus.FAILED);
+            // 发送审核失败消息
+            notificationService.sendFailedMsg(goods);
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 执行视频审核
+     * @param goods 商品信息
+     * @param goodsDTO 商品DTO信息
+     * @return 审核结果
+     */
+    @Override
+    public List<String> performVideoReviews(SecondGoods goods, SecondGoodsVo goodsDTO) {
+        List<String> videoUrls = extractVideoUrls(goodsDTO.getImgUrl());
+        List<String> taskIds = new ArrayList<>();
+        
+        // 视频审核
+        if (videoModerationEnabled) {
+            if (!videoUrls.isEmpty()) {
+                // 提交视频审核任务
+                for (String videoUrl : videoUrls) {
+                    try {
+                        String taskId = videoModerationService.submitVideoModerationTask(videoUrl);
+                        taskIds.add(taskId);
+                    } catch (Exception e) {
+                        log.error("提交视频审核任务失败,视频URL: {}", videoUrl, e);
+                        if (videoModerationBlockOnFailure) {
+                            // 视频审核提交失败,设置为审核失败状态
+                            goods.setGoodsStatus(SecondGoodsStatusEnum.REVIEW_FAILED.getCode());
+                            goods.setFailedReason("视频审核提交失败: " + e.getMessage());
+                            createGoodsAudit(goods, "视频审核提交失败", Constants.AuditStatus.FAILED);
+                            notificationService.sendFailedMsg(goods);
+                        }
+                    }
+                }
+            }
+        }
+        return taskIds;
+    }
+
+    /**
+     * 处理视频审核结果
+     * @param task 视频审核任务
+     */
+    @Override
+    public void processVideoModerationResult(SecondVideoTask task) {
+        try {
+            // 查找关联的商品
+            QueryWrapper<SecondGoods> queryWrapper = new QueryWrapper<>();
+            queryWrapper.eq("video_task_id", task.getTaskId());
+            SecondGoods goods = secondGoodsMapper.selectOne(queryWrapper);
+            
+            if (goods == null) {
+                log.warn("未找到关联的商品,任务ID: {}", task.getTaskId());
+                return;
+            }
+
+
+            // 根据审核结果更新商品状态
+            if ("none".equals(task.getRiskLevel())) {
+                QueryWrapper<StoreImg> imgQueryWrapper = new QueryWrapper<>();
+                imgQueryWrapper.eq("store_id", goods.getId());
+                imgQueryWrapper.eq("img_type", 19);
+                List<StoreImg> storeImgs = storeImgMapper.selectList(imgQueryWrapper);
+                List<String> imgUrls = storeImgs.stream()
+                        .map(StoreImg::getImgUrl)
+                        .filter(imgUrl -> StringUtils.hasText(imgUrl))
+                        .collect(Collectors.toList());
+
+                SecondGoodsVo goodsDTO = new SecondGoodsVo();
+                goodsDTO.setImgUrl(imgUrls);
+
+                // 开始第二轮审核
+                boolean b = performSecondRoundReview(goods, goodsDTO);
+
+                // 审核通过
+//                approveAndListGoods(goods);
+            } else {
+                // 审核不通过
+                goods.setGoodsStatus(SecondGoodsStatusEnum.REVIEW_FAILED.getCode());
+                
+                // 解析审核结果,生成具体的失败原因
+                String failedReason = parseVideoModerationFailureReason(task);
+                goods.setFailedReason(failedReason);
+                secondGoodsMapper.updateById(goods);
+                
+                // 更新审核记录
+                createGoodsAudit(goods, failedReason, Constants.AuditStatus.FAILED);
+
+                // 记录操作历史
+                operationRecordService.recordGoodsOperation(goods, "视频审核失败");
+                // 发送审核失败消息
+                notificationService.sendFailedMsg(goods);
+            }
+        } catch (Exception e) {
+            log.error("处理视频审核结果时发生异常,任务ID: {}", task.getTaskId(), e);
+        }
+    }
+
+    /**
+     * 审核通过后上架商品
+     * @param goods 商品信息
+     */
+    @Override
+    public void approveAndListGoods(SecondGoods goods) {
+        boolean isNotified = false;
+        try {
+            // 如果所有审核都通过,设置为上架状态
+            goods.setGoodsStatus(SecondGoodsStatusEnum.LISTED.getCode()); // 上架
+            goods.setFailedReason("");
+            goods.setReleaseTime(new Date()); // 上架时间
+            secondGoodsMapper.updateById(goods);
+            // 插入审核记录
+            createGoodsAudit(goods, "", Constants.AuditStatus.PASSED);
+            // 发送审核成功消息
+            notificationService.sendMessage(goods);
+            isNotified = true; // 标记通知已发送
+            
+            // 上架 记录商品操作历史
+            String operationName = "";
+            QueryWrapper<SecondGoodsRecord> queryWrapper = new QueryWrapper<>();
+            queryWrapper.eq("goods_id", goods.getId());
+            List<SecondGoodsRecord> recordList = secondGoodsRecordMapper.selectList(queryWrapper);
+            if (CollectionUtil.isNotEmpty(recordList)) {
+                operationName = "重新发布";
+            } else {
+                operationName = "首次发布";
+            }
+            operationRecordService.recordGoodsOperation(goods, operationName);
+        } catch (Exception e) {
+            log.error("商品上架过程中发生异常,执行回滚", e);
+            // 如果通知已发送但后续操作失败,需要补偿
+            if (isNotified) {
+                // 发送补偿消息,比如撤销通知或标记为异常状态
+            }
+            throw e;
+        }
+    }
+
+    /**
+     * 创建商品审核记录
+     * @param goods 商品信息
+     * @param failReason 审核失败原因
+     * @param goodsStatus 商品状态
+     */
+    @Override
+    public void createGoodsAudit(SecondGoods goods, String failReason, Integer goodsStatus) {
+        // 保存审核结果
+        secondGoodsMapper.updateById(goods);
+        // 插入审核记录
+        SecondGoodsAudit auditRecord = new SecondGoodsAudit();
+        auditRecord.setGoodsId(goods.getId());
+        auditRecord.setGoodsStatus(goodsStatus); // 审核状态
+        if (Constants.AuditStatus.FAILED.equals(goodsStatus)) {
+            auditRecord.setFailedReason(failReason);
+        }
+        auditRecord.setCreatedUserId(goods.getUserId());
+        auditRecord.setUpdatedUserId(goods.getUserId());
+        auditRecord.setCreatedTime(new Date());
+        auditRecord.setUpdatedTime(new Date());
+        secondGoodsAuditMapper.insert(auditRecord);
+        goods.setAuditRecordId(auditRecord.getId());
+    }
+
+    /**
+     * 从图片URL列表中提取视频URL
+     * @param imageUrls 图片URL列表
+     * @return 视频URL列表
+     */
+    @Override
+    public List<String> extractVideoUrls(List<String> imageUrls) {
+        if (CollectionUtil.isEmpty(imageUrls)) {
+            return Collections.emptyList();
+        }
+        
+        List<String> videoUrls = new ArrayList<>();
+        for (String url : imageUrls) {
+            if (isVideoUrl(url)) {
+                videoUrls.add(url);
+            }
+        }
+        return videoUrls;
+    }
+
+    /**
+     * 判断URL是否为视频地址
+     * @param url 输入URL
+     * @return 是否为视频地址
+     */
+    @Override
+    public boolean isVideoUrl(String url) {
+        if (url == null) return false;
+        url = url.toLowerCase();
+        return url.endsWith(".mp4") ||
+                url.endsWith(".avi") ||
+                url.endsWith(".mov") ||
+                url.endsWith(".flv") ||
+                url.endsWith(".wmv") ||
+                url.endsWith(".mkv");
+    }
+
+    /**
+     * 解析视频审核失败原因
+     * @param task 视频审核任务
+     * @return 失败原因
+     */
+    private String parseVideoModerationFailureReason(SecondVideoTask task) {
+        StringBuilder reasonBuilder = new StringBuilder("视频审核不通过,风险等级: " + task.getRiskLevel());
+        
+        try {
+            // 解析审核结果JSON
+            JSONObject resultJson = JSON.parseObject(task.getResult());
+            if (resultJson != null && resultJson.containsKey("data")) {
+                JSONObject data = resultJson.getJSONObject("data");
+                
+                // 处理帧结果(视频画面)
+                if (data.containsKey("FrameResult")) {
+                    JSONObject frameResult = data.getJSONObject("FrameResult");
+                    if (frameResult != null && frameResult.containsKey("FrameSummarys")) {
+                        JSONArray frameSummarys = frameResult.getJSONArray("FrameSummarys");
+                        if (frameSummarys != null && !frameSummarys.isEmpty()) {
+                            reasonBuilder.append("。检测到违规内容:");
+                            for (int i = 0; i < frameSummarys.size(); i++) {
+                                JSONObject summary = frameSummarys.getJSONObject(i);
+                                String label = summary.getString("Label");
+                                String description = summary.getString("Description");
+                                Integer labelSum = summary.getInteger("LabelSum");
+                                
+                                if (label != null && !label.isEmpty()) {
+                                    reasonBuilder.append("[").append(description != null ? description : label)
+                                            .append("]出现").append(labelSum != null ? labelSum : 1).append("次;");
+                                }
+                            }
+                        }
+                    }
+                }
+                
+                // 处理音频结果
+                if (data.containsKey("AudioResult")) {
+                    JSONObject audioResult = data.getJSONObject("AudioResult");
+                    if (audioResult != null && audioResult.containsKey("AudioSummarys")) {
+                        JSONArray audioSummarys = audioResult.getJSONArray("AudioSummarys");
+                        if (audioSummarys != null && !audioSummarys.isEmpty()) {
+                            reasonBuilder.append("。检测到违规音频:");
+                            for (int i = 0; i < audioSummarys.size(); i++) {
+                                JSONObject summary = audioSummarys.getJSONObject(i);
+                                String label = summary.getString("Label");
+                                String description = summary.getString("Description");
+                                Integer labelSum = summary.getInteger("LabelSum");
+                                
+                                if (label != null && !label.isEmpty()) {
+                                    reasonBuilder.append("[").append(description != null ? description : label)
+                                            .append("]出现").append(labelSum != null ? labelSum : 1).append("次;");
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        } catch (Exception e) {
+            log.warn("解析视频审核结果失败,使用默认原因,任务ID: {}", task.getTaskId(), e);
+        }
+        
+        return reasonBuilder.toString();
+    }
+}
+

+ 151 - 0
alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsNotificationServiceImpl.java

@@ -0,0 +1,151 @@
+package shop.alien.second.service.impl;
+
+import com.alibaba.fastjson2.JSONObject;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import shop.alien.entity.second.SecondGoods;
+import shop.alien.entity.store.LifeNotice;
+import shop.alien.entity.store.LifeUser;
+import shop.alien.entity.store.vo.WebSocketVo;
+import shop.alien.mapper.LifeNoticeMapper;
+import shop.alien.mapper.LifeUserMapper;
+import shop.alien.second.feign.AlienStoreFeign;
+import shop.alien.second.service.SecondGoodsNotificationService;
+import shop.alien.util.common.Constants;
+
+/**
+ * 二手商品消息通知服务实现类
+ * 负责商品相关的消息通知业务逻辑
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class SecondGoodsNotificationServiceImpl implements SecondGoodsNotificationService {
+
+    /**
+     * 用户信息Mapper
+     */
+    private final LifeUserMapper lifeUserMapper;
+
+    /**
+     * 公告Mapper
+     */
+    private final LifeNoticeMapper lifeNoticeMapper;
+
+    /**
+     * 店铺服务Feign接口
+     */
+    private final AlienStoreFeign alienStoreFeign;
+
+    /**
+     * 发送审核成功消息
+     * @param goods 商品信息
+     */
+    @Override
+    public void sendMessage(SecondGoods goods) {
+        // 根据 goods.getUserId() 获取用户信息
+        LifeUser lifeUser = lifeUserMapper.selectById(goods.getUserId());
+        String phone = lifeUser.getUserPhone();
+        
+        // 调取feign接口 发送消息 life_notice表
+        LifeNotice lifeNotice = new LifeNotice();
+        lifeNotice.setSenderId("system");
+        lifeNotice.setReceiverId("user_" + phone);
+        lifeNotice.setBusinessId(goods.getAuditRecordId());
+        lifeNotice.setTitle("商品审核通知");
+        
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put("goodsId", goods.getId());
+        jsonObject.put("status", "true");
+        jsonObject.put("message", "恭喜您的商品已发布成功。");
+        lifeNotice.setContext(jsonObject.toJSONString());
+        lifeNotice.setNoticeType(Constants.Notice.SYSTEM_NOTICE); // 系统通知
+        lifeNotice.setIsRead(0);
+        lifeNoticeMapper.insert(lifeNotice);
+        
+        sendNotice("user_" + phone, lifeNotice);
+    }
+
+    /**
+     * 发送审核失败消息
+     * @param goods 商品信息
+     */
+    @Override
+    public void sendFailedMsg(SecondGoods goods) {
+        // 根据 goods.getUserId() 获取用户信息
+        LifeUser lifeUser = lifeUserMapper.selectById(goods.getUserId());
+        String phone = lifeUser.getUserPhone();
+        
+        // 调取feign接口 发送消息 life_notice表
+        LifeNotice lifeNotice = new LifeNotice();
+        lifeNotice.setSenderId("system");
+        lifeNotice.setReceiverId("user_" + phone);
+        lifeNotice.setBusinessId(goods.getAuditRecordId());
+        lifeNotice.setTitle("商品审核通知");
+
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put("goodsId", goods.getId());
+        jsonObject.put("status", "false");
+        jsonObject.put("message", "抱歉您的商品发布失败,图片或文字存在违规行为,请您修改后重新发布。");
+        lifeNotice.setContext(jsonObject.toJSONString());
+        lifeNotice.setNoticeType(Constants.Notice.SYSTEM_NOTICE); // 系统通知
+        lifeNotice.setIsRead(0);
+        lifeNoticeMapper.insert(lifeNotice);
+        
+        sendNotice("user_" + phone, lifeNotice);
+    }
+
+    /**
+     * 发送商品下架消息
+     * @param goods 商品信息
+     */
+    @Override
+    public void sendShelveMessage(SecondGoods goods) {
+        try {
+            // 根据 goods.getUserId() 获取用户信息
+            LifeUser lifeUser = lifeUserMapper.selectById(goods.getUserId());
+            String phone = lifeUser.getUserPhone();
+            
+            // 调取feign接口 发送消息 life_notice表
+            LifeNotice lifeNotice = new LifeNotice();
+            lifeNotice.setSenderId("system");
+            lifeNotice.setReceiverId("user_" + phone);
+            lifeNotice.setBusinessId(goods.getId());
+            lifeNotice.setTitle("商品下架通知");
+            
+            JSONObject jsonObject = new JSONObject();
+            jsonObject.put("goodsId", goods.getId());
+            jsonObject.put("message", "您的商品:" + goods.getTitle() + " 已下架");
+            lifeNotice.setContext(jsonObject.toJSONString());
+            lifeNotice.setNoticeType(Constants.Notice.SYSTEM_NOTICE); // 系统通知
+            lifeNotice.setIsRead(0);
+            lifeNoticeMapper.insert(lifeNotice);
+            
+            sendNotice("user_" + phone, lifeNotice);
+        } catch (Exception e) {
+            log.error("发送消息通知失败,goods: {}", goods, e);
+        }
+    }
+
+    /**
+     * 发送通知消息
+     * @param receiverId 接收者ID
+     * @param lifeNotice 通知内容
+     */
+    private void sendNotice(String receiverId, LifeNotice lifeNotice) {
+        try {
+            WebSocketVo webSocketVo = new WebSocketVo();
+            webSocketVo.setSenderId("system");
+            webSocketVo.setReceiverId(receiverId);
+            webSocketVo.setCategory("notice");
+            webSocketVo.setNoticeType("1");
+            webSocketVo.setIsRead(0);
+            webSocketVo.setText(JSONObject.from(lifeNotice).toJSONString());
+            alienStoreFeign.sendMsgToClientByPhoneId(receiverId, JSONObject.from(webSocketVo).toJSONString());
+        } catch (Exception e) {
+            log.error("发送消息通知失败,receiverId: {}", receiverId, e);
+        }
+    }
+}
+

+ 127 - 0
alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsOperationRecordServiceImpl.java

@@ -0,0 +1,127 @@
+package shop.alien.second.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import shop.alien.entity.second.SecondGoods;
+import shop.alien.entity.second.SecondGoodsRecord;
+import shop.alien.entity.store.StoreImg;
+import shop.alien.mapper.StoreImgMapper;
+import shop.alien.mapper.second.SecondGoodsRecordMapper;
+import shop.alien.second.service.SecondGoodsOperationRecordService;
+import shop.alien.util.common.Constants;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 二手商品操作历史记录服务实现类
+ * 负责记录商品的各种操作历史
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class SecondGoodsOperationRecordServiceImpl implements SecondGoodsOperationRecordService {
+
+    /**
+     * 商品操作历史记录Mapper
+     */
+    private final SecondGoodsRecordMapper secondGoodsRecordMapper;
+
+    /**
+     * 店铺图片Mapper
+     */
+    private final StoreImgMapper storeImgMapper;
+
+    /**
+     * 记录商品操作历史
+     * @param goods 商品信息
+     * @param operationName 操作名称
+     */
+    @Override
+    public void recordGoodsOperation(SecondGoods goods, String operationName) {
+        try {
+            log.warn("开始创建操作历史: {},{} ", goods, operationName);
+            SecondGoodsRecord record = new SecondGoodsRecord();
+            record.setOperationName(operationName);
+            record.setGoodsId(goods.getId());
+            record.setUserId(goods.getUserId());
+            record.setTitle(goods.getTitle());
+            record.setDescription(goods.getDescription());
+            
+            // 价格转换
+            if (goods.getAmount() != null) {
+                record.setPrice(goods.getAmount());
+            } else if (goods.getPrice() != null && !goods.getPrice().isEmpty()) {
+                try {
+                    record.setPrice(new BigDecimal(goods.getPrice()));
+                } catch (Exception e) {
+                    log.warn("转换商品价格时出错: {}", e.getMessage());
+                }
+            }
+            
+            record.setPosition(goods.getPosition());
+            record.setLikeCount(goods.getLikeCount());
+            record.setCollectCount(goods.getCollectCount());
+            record.setCategoryOneId(goods.getCategoryOneId());
+            record.setCategoryTwoId(goods.getCategoryTwoId());
+            record.setLabel(goods.getLabel());
+            record.setTopic(goods.getTopic());
+            record.setTradeId(goods.getTradeId());
+            record.setReleaseTime(goods.getReleaseTime());
+            record.setGoodsStatus(goods.getGoodsStatus());
+            record.setFailedReason(goods.getFailedReason());
+            record.setHomeImage(goods.getHomeImage());
+            record.setVideoTaskId(goods.getVideoTaskId());
+            record.setVideoFirstFrame(goods.getVideoFirstFrame());
+            record.setDeleteFlag(goods.getDeleteFlag());
+            record.setCreatedTime(goods.getCreatedTime());
+            record.setCreatedUserId(goods.getCreatedUserId());
+            record.setUpdatedTime(goods.getUpdatedTime());
+            record.setUpdatedUserId(goods.getUpdatedUserId());
+            record.setAddressText(goods.getAddressText());
+            
+            secondGoodsRecordMapper.insert(record);
+            log.warn("创建操作历史结束: {} ", record);
+            
+            // 保存图片信息
+            saveRecordGoodsImages(record);
+        } catch (Exception e) {
+            log.error("记录商品操作历史时发生异常", e);
+        }
+    }
+
+    /**
+     * 保存二手商品记录图片类型信息
+     * @param record 保存后的商品记录
+     */
+    private void saveRecordGoodsImages(SecondGoodsRecord record) {
+        log.info("创建操作历图片史开始: {} ", record);
+        // 获取商品图片列表
+        QueryWrapper<StoreImg> query = new QueryWrapper<>();
+        query.lambda().eq(StoreImg::getStoreId, record.getGoodsId())
+                .eq(StoreImg::getImgType, Constants.ImageType.SECOND_HAND_GOODS);
+        List<StoreImg> storeImgs = storeImgMapper.selectList(query);
+        
+        // 保存前先把原有的删除
+        storeImgs.forEach(storeImgModel -> {
+            StoreImg storeImg = new StoreImg();
+            storeImg.setStoreId(record.getId());
+            storeImg.setImgType(Constants.ImageType.SECOND_HAND_RECORD);
+            storeImg.setImgSort(storeImgModel.getImgSort());
+            storeImg.setImgDescription("二手商品记录图片类型");
+            storeImg.setDeleteFlag(Constants.DeleteFlag.NOT_DELETED);
+            storeImg.setCreatedTime(new Date());
+            storeImg.setUpdatedTime(new Date());
+            storeImg.setCreatedUserId(1);
+            storeImg.setUpdatedUserId(1);
+            storeImg.setImgUrl(storeImgModel.getImgUrl());
+            // 保存图片 插入store_img数据库
+            storeImgMapper.insert(storeImg);
+            log.info("创建操作历图片结束: {} ", storeImg);
+        });
+    }
+}
+

+ 6 - 5
alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsServiceImpl.java

@@ -30,10 +30,7 @@ import shop.alien.entity.store.vo.WebSocketVo;
 import shop.alien.mapper.*;
 import shop.alien.mapper.second.*;
 import shop.alien.second.feign.AlienStoreFeign;
-import shop.alien.second.service.PlatformSecondTradeService;
-import shop.alien.second.service.RiskControlService;
-import shop.alien.second.service.SecondGoodsService;
-import shop.alien.second.service.VideoModerationService;
+import shop.alien.second.service.*;
 import shop.alien.util.common.Constants;
 import shop.alien.util.common.VideoUtils;
 import shop.alien.util.common.safe.*;
@@ -166,6 +163,8 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
      */
     private final RiskControlService riskControlService;
 
+    private final SecondGoodsAuditService secondGoodsAuditService;
+
     /**
      * 获取商品操作记录详情(管理后台使用)
      * @param recordId 商品操作记录ID
@@ -794,7 +793,9 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
             return;
         }
         // 审核通过后上架商品
-        approveAndListGoods(goods);
+//        approveAndListGoods(goods);
+        // 开始第二轮审核
+        boolean b = secondGoodsAuditService.performSecondRoundReview(goods, goodsDTO);
 
         // 检查用户是否在24小时内发布同类商品超过阈值
         if (!checkUserPublishSameCategoryLimit(goods)) {

+ 146 - 0
alien-second/src/main/java/shop/alien/second/util/AiTaskUtils.java

@@ -0,0 +1,146 @@
+package shop.alien.second.util;
+
+import com.alibaba.fastjson2.JSONObject;
+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.StoreCommentAppeal;
+
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+@Component
+@RequiredArgsConstructor
+public class AiTaskUtils {
+
+    private final RestTemplate restTemplate;
+
+//    @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 auditTaskUrl = "http://192.168.2.250:9000/ai/auto-review/api/v1/audit_task/product";
+
+
+
+    private String auditTaskResultUrl = "http://192.168.2.250:9000/ai/task-core/api/v1/audit_task/getResult";
+
+    /**
+     * 登录 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, String text, List<String> img_urls) {
+        log.info("创建Ai服务任务...{}", auditTaskUrl);
+
+        HttpHeaders analyzeHeaders = new HttpHeaders();
+        analyzeHeaders.setContentType(MediaType.APPLICATION_JSON);
+        analyzeHeaders.set("Authorization", "Bearer " + accessToken);
+
+        Map<String, Object> analyzeRequest = new HashedMap<>();
+        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(auditTaskUrl, 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;
+    }
+}

+ 1 - 1
alien-second/src/main/resources/bootstrap.yml

@@ -1,3 +1,3 @@
 spring:
   profiles:
-    active: dev
+    active: test

+ 285 - 0
alien-store-platform/doc/OPERATIONAL_ACTIVITY_README.md

@@ -0,0 +1,285 @@
+# 运营活动管理模块
+
+## 功能说明
+
+本模块用于管理商户的运营活动,支持活动的创建、查询、更新和删除操作。活动可以设置参与规则、奖励类型、优惠券等信息。
+
+---
+
+## 数据库表结构
+
+### store_operational_activity 表
+
+```sql
+CREATE TABLE `store_operational_activity` (
+    `id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
+    `store_id` int NULL COMMENT '商户ID',
+    `activity_name` VARCHAR(100) NOT NULL COMMENT '活动名称',
+    `promotional_image` VARCHAR(500) DEFAULT NULL COMMENT '活动宣传图URL',
+    `start_time` DATETIME NOT NULL COMMENT '活动开始时间',
+    `end_time` DATETIME NOT NULL COMMENT '活动结束时间',
+    `participation_limit` int DEFAULT 0 COMMENT '用户可参与次数,0表示不限制',
+    `activity_rule` VARCHAR(50) NOT NULL COMMENT '活动规则:VERIFY_AND_COMMENT-核销并评论, VERIFY-核销, CHECK_IN-打卡',
+    `reward_type` VARCHAR(50) DEFAULT NULL COMMENT '奖励类型:COUPON-优惠券, RED_PACKET-红包',
+    `coupon_id` int DEFAULT NULL COMMENT '优惠券ID,关联优惠券表',
+    `coupon_quantity` int DEFAULT NULL COMMENT '优惠券发放数量',
+    `status` int DEFAULT 1 COMMENT '状态:0-禁用, 1-启用',
+    `delete_flag` int NOT NULL DEFAULT '0' COMMENT '删除标记, 0:未删除, 1:已删除',
+    `created_time` datetime(1) NOT NULL COMMENT '创建时间',
+    `created_user_id` int DEFAULT NULL COMMENT '创建人ID',
+    `updated_time` datetime DEFAULT NULL COMMENT '修改时间',
+    `updated_user_id` int DEFAULT NULL COMMENT '修改人ID',
+    PRIMARY KEY (`id`),
+    INDEX `idx_activity_time` (`start_time`, `end_time`),
+    INDEX `idx_status` (`status`, `delete_flag`),
+    INDEX `idx_coupon_id` (`coupon_id`),
+    INDEX `idx_create_time` (`created_time`)
+) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='运营活动表';
+```
+
+---
+
+## 文件清单
+
+### 1. Entity(实体类)
+**路径**: `alien-entity/src/main/java/shop/alien/entity/store/StoreOperationalActivity.java`
+
+**功能**: 运营活动实体类,对应数据库表 `store_operational_activity`
+
+**主要字段**:
+- `id`: 主键
+- `storeId`: 商户ID
+- `activityName`: 活动名称
+- `promotionalImage`: 活动宣传图URL
+- `startTime`: 活动开始时间
+- `endTime`: 活动结束时间
+- `participationLimit`: 用户可参与次数(0表示不限制)
+- `activityRule`: 活动规则(VERIFY_AND_COMMENT-核销并评论, VERIFY-核销, CHECK_IN-打卡)
+- `rewardType`: 奖励类型(COUPON-优惠券, RED_PACKET-红包)
+- `couponId`: 优惠券ID
+- `couponQuantity`: 优惠券发放数量
+- `status`: 状态(0-禁用, 1-启用)
+- `deleteFlag`: 删除标记(逻辑删除)
+- `createdTime`: 创建时间(自动填充)
+- `createdUserId`: 创建人ID
+- `updatedTime`: 修改时间(自动填充)
+- `updatedUserId`: 修改人ID
+
+---
+
+### 2. DTO(数据传输对象)
+**路径**: `alien-entity/src/main/java/shop/alien/entity/store/vo/StoreOperationalActivityDTO.java`
+
+**功能**: 用于接收前端请求参数,包含参数校验
+
+**校验规则**:
+- `activityName`: 必填,不能为空
+- `startTime`: 必填,不能为空
+- `endTime`: 必填,不能为空
+- `activityRule`: 必填,不能为空
+- 其他字段可选
+
+---
+
+### 3. VO(视图对象)
+**路径**: `alien-entity/src/main/java/shop/alien/entity/store/vo/StoreOperationalActivityVO.java`
+
+**功能**: 用于返回给前端的数据对象,继承自实体类并扩展了额外字段
+
+**扩展字段**:
+- `statusName`: 状态名称
+- `activityRuleName`: 活动规则名称
+- `rewardTypeName`: 奖励类型名称
+- `couponName`: 优惠券名称
+- `storeName`: 商户名称
+- `activityStatus`: 活动状态(0-未开始, 1-进行中, 2-已结束)
+- `participationCount`: 已参与人数
+- `remainingCouponQuantity`: 剩余优惠券数量
+
+---
+
+### 4. Mapper(数据访问层)
+**路径**: `alien-entity/src/main/java/shop/alien/mapper/StoreOperationalActivityMapper.java`
+
+**功能**: 继承 MyBatis-Plus 的 `BaseMapper`,提供基础 CRUD 操作
+
+---
+
+### 5. Mapper XML(映射文件)
+**路径**: `alien-entity/src/main/resources/mapper/StoreOperationalActivityMapper.xml`
+
+**功能**: MyBatis 映射配置文件,定义结果集映射和通用 SQL
+
+---
+
+### 6. Service(服务接口)
+**路径**: `alien-store-platform/src/main/java/shop/alien/storeplatform/service/OperationalActivityService.java`
+
+**功能**: 定义运营活动业务逻辑接口
+
+**方法列表**:
+- `createActivity(StoreOperationalActivityDTO dto)`: 创建运营活动
+- `updateActivity(StoreOperationalActivityDTO dto)`: 更新运营活动
+- `deleteActivity(Integer id)`: 删除运营活动(逻辑删除)
+- `getActivityById(Integer id)`: 根据ID获取活动详情
+- `getActivityListByStoreId(Integer storeId)`: 根据商户ID获取活动列表
+- `getActivityPage(Integer current, Integer size, Integer storeId, Integer status)`: 分页查询活动列表
+- `updateActivityStatus(Integer id, Integer status)`: 启用/禁用活动
+- `getOngoingActivities(Integer storeId)`: 获取进行中的活动列表
+
+---
+
+### 7. ServiceImpl(服务实现类)
+**路径**: `alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/OperationalActivityServiceImpl.java`
+
+**功能**: 实现运营活动业务逻辑
+
+**核心功能**:
+- 活动的增删改查
+- 实体与VO对象的转换
+- 活动状态的自动判断(未开始/进行中/已结束)
+- 活动规则和奖励类型的中文名称转换
+
+---
+
+### 8. Controller(控制器)
+**路径**: `alien-store-platform/src/main/java/shop/alien/storeplatform/controller/OperationalActivityController.java`
+
+**功能**: 提供运营活动管理的 REST API 接口
+
+**API 列表**:
+
+#### 8.1 创建运营活动
+- **接口**: `POST /operationalActivity/create`
+- **参数**: StoreOperationalActivityDTO(JSON)
+- **返回**: R<String>
+
+#### 8.2 更新运营活动
+- **接口**: `POST /operationalActivity/update`
+- **参数**: StoreOperationalActivityDTO(JSON)
+- **返回**: R<String>
+
+#### 8.3 删除运营活动
+- **接口**: `DELETE /operationalActivity/delete`
+- **参数**: id(活动ID)
+- **返回**: R<String>
+
+#### 8.4 根据ID获取活动详情
+- **接口**: `GET /operationalActivity/detail`
+- **参数**: id(活动ID)
+- **返回**: R<StoreOperationalActivityVO>
+
+#### 8.5 根据商户ID获取活动列表
+- **接口**: `GET /operationalActivity/list`
+- **参数**: storeId(商户ID)
+- **返回**: R<List<StoreOperationalActivityVO>>
+
+#### 8.6 分页查询活动列表
+- **接口**: `GET /operationalActivity/page`
+- **参数**: 
+  - current(当前页,默认1)
+  - size(每页大小,默认10)
+  - storeId(商户ID,可选)
+  - status(状态,可选)
+- **返回**: R<IPage<StoreOperationalActivityVO>>
+
+#### 8.7 启用/禁用活动
+- **接口**: `POST /operationalActivity/updateStatus`
+- **参数**: 
+  - id(活动ID)
+  - status(状态:0-禁用, 1-启用)
+- **返回**: R<String>
+
+#### 8.8 获取进行中的活动列表
+- **接口**: `GET /operationalActivity/ongoing`
+- **参数**: storeId(商户ID)
+- **返回**: R<List<StoreOperationalActivityVO>>
+
+---
+
+## 使用示例
+
+### 创建活动
+
+```json
+POST /operationalActivity/create
+
+{
+  "storeId": 1,
+  "activityName": "双十一优惠活动",
+  "promotionalImage": "https://example.com/image.jpg",
+  "startTime": "2025-11-11 00:00:00",
+  "endTime": "2025-11-11 23:59:59",
+  "participationLimit": 1,
+  "activityRule": "VERIFY_AND_COMMENT",
+  "rewardType": "COUPON",
+  "couponId": 100,
+  "couponQuantity": 1000,
+  "status": 1
+}
+```
+
+### 查询活动列表
+
+```
+GET /operationalActivity/list?storeId=1
+```
+
+### 分页查询
+
+```
+GET /operationalActivity/page?current=1&size=10&storeId=1&status=1
+```
+
+---
+
+## 数据字典
+
+### 活动规则(activity_rule)
+- `VERIFY_AND_COMMENT`: 核销并评论
+- `VERIFY`: 核销
+- `CHECK_IN`: 打卡
+
+### 奖励类型(reward_type)
+- `COUPON`: 优惠券
+- `RED_PACKET`: 红包
+
+### 活动状态(status)
+- `0`: 禁用
+- `1`: 启用
+
+### 活动进行状态(activityStatus)
+- `0`: 未开始
+- `1`: 进行中
+- `2`: 已结束
+
+---
+
+## 注意事项
+
+1. **时间校验**: 创建活动时,需要确保结束时间晚于开始时间
+2. **逻辑删除**: 删除操作为逻辑删除,不会真正删除数据
+3. **状态管理**: 活动状态由系统根据当前时间自动判断
+4. **参数校验**: DTO 中包含必填项校验,需要确保必填字段不为空
+5. **优惠券关联**: 如果奖励类型为优惠券,需要填写 couponId 和 couponQuantity
+
+---
+
+## 扩展建议
+
+1. **用户参与记录**: 可以创建用户参与活动记录表,跟踪用户参与情况
+2. **活动统计**: 添加活动效果统计功能,如参与人数、发放优惠券数量等
+3. **活动审核**: 添加活动审核流程,确保活动内容合规
+4. **活动推送**: 集成消息推送功能,在活动开始时通知用户
+5. **活动模板**: 提供常用活动模板,简化活动创建流程
+
+---
+
+## 更新日志
+
+### 2025-11-26
+- 初始版本发布
+- 实现基础的增删改查功能
+- 支持活动状态管理
+- 支持分页查询
+

+ 1 - 1
alien-store-platform/src/main/java/shop/alien/storeplatform/AlienStorePlatformApplication.java

@@ -16,7 +16,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
         "shop.alien.config.properties",
         "shop.alien.config.redis"})
 @EnableSwaggerBootstrapUI
-@MapperScan({"shop.alien.mapper"})
+@MapperScan({"shop.alien.mapper", "shop.alien.storeplatform.mapper"})
 @SpringBootApplication
 @EnableFeignClients(basePackages = "shop.alien.storeplatform.feign")
 @EnableScheduling

+ 178 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/controller/BusinessSectionController.java

@@ -0,0 +1,178 @@
+package shop.alien.storeplatform.controller;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiOperationSupport;
+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.vo.StoreDictionaryVo;
+import shop.alien.storeplatform.service.BusinessSectionService;
+
+import java.util.List;
+
+/**
+ * 经营板块管理控制器(平台端)
+ * 提供经营板块的三级分类查询接口
+ * 
+ * <p>业务说明:
+ * <ul>
+ *   <li>一级分类:经营板块(特色美食、酒店/民宿、KTV等)</li>
+ *   <li>二级分类:各板块下的子分类</li>
+ *   <li>三级分类:各二级分类下的细分类</li>
+ * </ul>
+ * </p>
+ *
+ * @author alien-cloud
+ * @date 2025-12-01
+ */
+@Api(tags = {"商户平台-经营板块管理"})
+@Slf4j
+@CrossOrigin
+@RestController
+@RequestMapping("/businessSection")
+@RequiredArgsConstructor
+public class BusinessSectionController {
+
+    private final BusinessSectionService businessSectionService;
+
+    /**
+     * 查询经营板块一级分类列表
+     * 返回所有一级分类(特色美食、酒店/民宿、KTV、洗浴汗蒸等)
+     *
+     * @return R<List<StoreDictionaryVo>> 一级分类列表
+     * @author alien-cloud
+     * @date 2025-12-01
+     */
+    @ApiOperation("查询经营板块一级分类列表")
+    @ApiOperationSupport(order = 1)
+    @GetMapping("/getFirstLevelList")
+    public R<List<StoreDictionaryVo>> getFirstLevelList() {
+        log.info("BusinessSectionController.getFirstLevelList - 查询一级分类列表");
+        try {
+            List<StoreDictionaryVo> result = businessSectionService.getFirstLevelList();
+            log.info("BusinessSectionController.getFirstLevelList - 查询成功,共 {} 条数据", result.size());
+            return R.data(result);
+        } catch (Exception e) {
+            log.error("BusinessSectionController.getFirstLevelList ERROR: {}", e.getMessage(), e);
+            return R.fail("查询失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 查询经营板块二级分类列表
+     * 根据一级分类ID查询对应的二级分类
+     *
+     * @param parentDictId 一级分类的字典ID(dict_id)
+     * @return R<List<StoreDictionaryVo>> 二级分类列表
+     * @author alien-cloud
+     * @date 2025-12-01
+     */
+    @ApiOperation("查询经营板块二级分类列表")
+    @ApiOperationSupport(order = 2)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "parentDictId", value = "一级分类字典ID(如:1-特色美食,2-酒店/民宿)", 
+                    dataType = "String", paramType = "query", required = true, example = "1")
+    })
+    @GetMapping("/getSecondLevelList")
+    public R<List<StoreDictionaryVo>> getSecondLevelList(
+            @RequestParam("parentDictId") String parentDictId) {
+        log.info("BusinessSectionController.getSecondLevelList - 查询二级分类列表,parentDictId={}", parentDictId);
+        try {
+            List<StoreDictionaryVo> result = businessSectionService.getSecondLevelList(parentDictId);
+            log.info("BusinessSectionController.getSecondLevelList - 查询成功,共 {} 条数据", result.size());
+            return R.data(result);
+        } catch (Exception e) {
+            log.error("BusinessSectionController.getSecondLevelList ERROR: parentDictId={}, error={}", 
+                    parentDictId, e.getMessage(), e);
+            return R.fail("查询失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 查询经营板块三级分类列表
+     * 根据二级分类ID查询对应的三级分类
+     *
+     * @param parentDictId 二级分类的字典ID(dict_id)
+     * @return R<List<StoreDictionaryVo>> 三级分类列表
+     * @author alien-cloud
+     * @date 2025-12-01
+     */
+    @ApiOperation("查询经营板块三级分类列表")
+    @ApiOperationSupport(order = 3)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "parentDictId", value = "二级分类字典ID", 
+                    dataType = "String", paramType = "query", required = true, example = "11")
+    })
+    @GetMapping("/getThirdLevelList")
+    public R<List<StoreDictionaryVo>> getThirdLevelList(
+            @RequestParam("parentDictId") String parentDictId) {
+        log.info("BusinessSectionController.getThirdLevelList - 查询三级分类列表,parentDictId={}", parentDictId);
+        try {
+            List<StoreDictionaryVo> result = businessSectionService.getThirdLevelList(parentDictId);
+            log.info("BusinessSectionController.getThirdLevelList - 查询成功,共 {} 条数据", result.size());
+            return R.data(result);
+        } catch (Exception e) {
+            log.error("BusinessSectionController.getThirdLevelList ERROR: parentDictId={}, error={}", 
+                    parentDictId, e.getMessage(), e);
+            return R.fail("查询失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 查询经营板块树形结构(三级联动)
+     * 返回完整的三级分类树形结构,包含所有层级的子节点
+     *
+     * @return R<List<StoreDictionaryVo>> 树形结构数据(包含一级、二级、三级)
+     * @author alien-cloud
+     * @date 2025-12-01
+     */
+    @ApiOperation("查询经营板块树形结构(三级联动)")
+    @ApiOperationSupport(order = 4)
+    @GetMapping("/getTreeStructure")
+    public R<List<StoreDictionaryVo>> getTreeStructure() {
+        log.info("BusinessSectionController.getTreeStructure - 查询三级树形结构");
+        try {
+            List<StoreDictionaryVo> result = businessSectionService.getTreeStructure();
+            log.info("BusinessSectionController.getTreeStructure - 查询成功");
+            return R.data(result);
+        } catch (Exception e) {
+            log.error("BusinessSectionController.getTreeStructure ERROR: {}", e.getMessage(), e);
+            return R.fail("查询失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 根据字典ID查询完整路径
+     * 返回从一级到当前级别的完整分类路径
+     *
+     * @param dictId 字典ID
+     * @return R<List<StoreDictionaryVo>> 分类路径(从一级到当前级)
+     * @author alien-cloud
+     * @date 2025-12-01
+     */
+    @ApiOperation("根据字典ID查询完整路径")
+    @ApiOperationSupport(order = 5)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "dictId", value = "字典ID", 
+                    dataType = "String", paramType = "query", required = true, example = "1")
+    })
+    @GetMapping("/getFullPath")
+    public R<List<StoreDictionaryVo>> getFullPath(
+            @RequestParam("dictId") String dictId) {
+        log.info("BusinessSectionController.getFullPath - 查询完整路径,dictId={}", dictId);
+        try {
+            List<StoreDictionaryVo> result = businessSectionService.getFullPath(dictId);
+            log.info("BusinessSectionController.getFullPath - 查询成功");
+            return R.data(result);
+        } catch (Exception e) {
+            log.error("BusinessSectionController.getFullPath ERROR: dictId={}, error={}", 
+                    dictId, e.getMessage(), e);
+            return R.fail("查询失败:" + e.getMessage());
+        }
+    }
+}
+

+ 63 - 4
alien-store-platform/src/main/java/shop/alien/storeplatform/controller/LicenseController.java

@@ -5,8 +5,10 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.*;
 import shop.alien.entity.result.R;
+import shop.alien.entity.second.vo.StoreImgDTO;
 import shop.alien.entity.store.StoreImg;
 import shop.alien.entity.store.WebAudit;
+import shop.alien.entity.store.vo.StoreImgVo;
 import shop.alien.entity.storePlatform.vo.StoreLicenseHistoryDto;
 import shop.alien.entity.storePlatform.vo.StoreLicenseHistoryVO;
 import shop.alien.mapper.WebAuditMapper;
@@ -49,9 +51,9 @@ public class LicenseController {
             @ApiImplicitParam(name = "id", value = "城市", dataType = "Integer", paramType = "query", required = false)
     })
     @GetMapping("/queryContractList")
-    public R<List<StoreImg>> queryContractList(Integer id) {
+    public R<List<StoreImgDTO>> queryContractList(Integer id) {
         log.info("LicenseController.queryContractList?id={}", id);
-        List<StoreImg> result = licenseService.getContractList(id);
+        List<StoreImgDTO> result = licenseService.getContractList(id);
         return R.data(result);
     }
 
@@ -61,9 +63,9 @@ public class LicenseController {
             @ApiImplicitParam(name = "id", value = "城市", dataType = "Integer", paramType = "query", required = false)
     })
     @GetMapping("/queryFoodLicenceList")
-    public R<List<StoreImg>> queryFoodLicenceList(Integer id) {
+    public R<List<StoreImgDTO>> queryFoodLicenceList(Integer id) {
         log.info("LicenseController.queryFoodLicenceList?id={}", id);
-        List<StoreImg> result = licenseService.getFoodLicenceList(id);
+        List<StoreImgDTO> result = licenseService.getFoodLicenceList(id);
         return R.data(result);
     }
 
@@ -145,6 +147,63 @@ public class LicenseController {
             return R.fail(e.getMessage());
         }
     }
+
+    @ApiOperation("获取娱乐经营许可证图片信息")
+    @ApiOperationSupport(order = 1)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "Integer", value = "城市", dataType = "String", paramType = "query", required = false)
+    })
+    @GetMapping("/queryEntertainmentLicenseList")
+    public R<List<StoreImgDTO>> queryEntertainmentLicenseList(Integer id) {
+        log.info("LicenseController.queryEntertainmentLicenseList?id={}", id);
+        List<StoreImgDTO> result = licenseService.getEntertainmentLicenseList(id);
+        return R.data(result);
+    }
+
+
+    @ApiOperation(value = "门店装修-修改娱乐经营许可证")
+    @PostMapping("/uploadEntertainmentLicence")
+    public R<String> uploadEntertainmentLicence(@RequestBody StoreImg storeImg) {
+        log.info("StoreInfoController.uploadEntertainmentLicence?storeImg={}", storeImg);
+        int num = licenseService.uploadEntertainmentLicence(storeImg);
+        if (num > 0) {
+            WebAudit webAudit = new WebAudit();
+            webAudit.setStoreInfoId(storeImg.getStoreId().toString());
+            webAudit.setType("8");
+            webAudit.setStatus("0");
+            webAudit.setContent("娱乐经营许可证");
+            webAuditMapper.insert(webAudit);
+            return R.success("娱乐经营许可证图片添加成功");
+        }
+        return R.fail("娱乐经营许可证图片添加失败");
+    }
+
+    @ApiOperation("根据商户ID获取经营许可证历史记录")
+    @ApiOperationSupport(order = 3)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "商户ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/queryEntertainmentByStatusList")
+    public R<List<StoreLicenseHistoryDto>> queryEntertainmentByStatusList(@RequestParam("storeId") Integer storeId) {
+        log.info("LicenseController.queryLicenceByStatusList: storeId={}", storeId);
+        try {
+            List<StoreLicenseHistoryDto> result = licenseService.queryEntertainmentByStatusList(storeId);
+            return R.data(result);
+        } catch (Exception e) {
+            log.error("LicenseController.queryLicenceByStatusList ERROR: {}", e.getMessage(), e);
+            return R.fail(e.getMessage());
+        }
+    }
+
+    @ApiOperation(value = "门店装修-娱乐经营许可证状态")
+    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "门店id", dataType = "int", paramType = "query", required = true)})
+    @GetMapping("/queryStoreEntertainmentStatus")
+    public R<Map<String, Object>> queryStoreEntertainmentStatus(int id) {
+        log.info("StoreInfoController.getStoreFoodLicenceStatus?id={}", id);
+        return R.data(licenseService.getStoreEntertainmentStatus(id));
+    }
+
+
 }
 
 

+ 1 - 1
alien-store-platform/src/main/java/shop/alien/storeplatform/controller/LifeCouponPlatformController.java

@@ -257,7 +257,7 @@ public class LifeCouponPlatformController {
                                                       @RequestBody LifeCouponPlatformVo lifeCouponPlatformVo) {
         log.info("LifeCouponController.getCouponList?lifeCouponPlatformVo={}", lifeCouponPlatformVo);
         if (StringUtils.isBlank(lifeCouponPlatformVo.getStoreId())) {
-            return R.data(null, "当前用户未入!!!");
+            return R.data(null, "当前用户未入!!!");
         }
         DiscountCouponPlatformVo vo = new DiscountCouponPlatformVo();
         if (lifeCouponPlatformVo.getCouponType() == 1) {

+ 148 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/controller/OperationalActivityController.java

@@ -0,0 +1,148 @@
+package shop.alien.storeplatform.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import io.swagger.annotations.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.entity.storePlatform.vo.StoreOperationalActivityDTO;
+import shop.alien.entity.storePlatform.vo.StoreOperationalActivityVO;
+import shop.alien.storeplatform.service.OperationalActivityService;
+
+import java.util.List;
+
+/**
+ * 运营活动管理控制器
+ *
+ * @author system
+ * @since 2025-11-26
+ */
+@Slf4j
+@Api(tags = {"商家端-运营活动管理"})
+@ApiSort(10)
+@CrossOrigin
+@RestController
+@RequestMapping("/operationalActivity")
+@RequiredArgsConstructor
+public class OperationalActivityController {
+
+    private final OperationalActivityService activityService;
+
+    @ApiOperation("创建运营活动")
+    @ApiOperationSupport(order = 1)
+    @PostMapping("/create")
+    public R<String> createActivity(@RequestBody StoreOperationalActivityDTO dto) {
+        log.info("OperationalActivityController.createActivity: dto={}", dto);
+        try {
+            int result = activityService.createActivity(dto);
+            if (result > 0) {
+                return R.success("活动创建成功");
+            }
+            return R.fail("活动创建失败");
+        } catch (Exception e) {
+            log.error("OperationalActivityController.createActivity ERROR: {}", e.getMessage(), e);
+            return R.fail(e.getMessage());
+        }
+    }
+
+    @ApiOperation("更新运营活动")
+    @ApiOperationSupport(order = 2)
+    @PostMapping("/update")
+    public R<String> updateActivity(@RequestBody StoreOperationalActivityDTO dto) {
+        log.info("OperationalActivityController.updateActivity: dto={}", dto);
+        try {
+            int result = activityService.updateActivity(dto);
+            if (result > 0) {
+                return R.success("活动更新成功");
+            }
+            return R.fail("活动更新失败");
+        } catch (Exception e) {
+            log.error("OperationalActivityController.updateActivity ERROR: {}", e.getMessage(), e);
+            return R.fail(e.getMessage());
+        }
+    }
+
+    @ApiOperation("删除运营活动")
+    @ApiOperationSupport(order = 3)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "活动ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/delete")
+    public R<String> deleteActivity(@RequestParam("id") Integer id) {
+        log.info("OperationalActivityController.deleteActivity: id={}", id);
+        try {
+            int result = activityService.deleteActivity(id);
+            if (result > 0) {
+                return R.success("活动删除成功");
+            }
+            return R.fail("活动删除失败");
+        } catch (Exception e) {
+            log.error("OperationalActivityController.deleteActivity ERROR: {}", e.getMessage(), e);
+            return R.fail(e.getMessage());
+        }
+    }
+
+    @ApiOperation("根据ID获取活动详情")
+    @ApiOperationSupport(order = 4)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "活动ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/queryActivityById")
+    public R<StoreOperationalActivityVO> queryActivityById(@RequestParam("id") Integer id) {
+        log.info("OperationalActivityController.getActivityById: id={}", id);
+        try {
+            StoreOperationalActivityVO result = activityService.queryActivityById(id);
+            return R.data(result);
+        } catch (Exception e) {
+            log.error("OperationalActivityController.getActivityById ERROR: {}", e.getMessage(), e);
+            return R.fail(e.getMessage());
+        }
+    }
+
+    @ApiOperation("根据商户ID获取活动列表")
+    @ApiOperationSupport(order = 5)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "商户ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @PostMapping("/queryActivityList")
+    public R<IPage<StoreOperationalActivityVO>> queryActivityList(@RequestBody StoreOperationalActivityDTO dto) {
+        log.info("OperationalActivityController.queryActivityList: storeId={}, status={}, activityName={}", dto.getStoreId(), dto.getStatus(), dto.getActivityName());
+        try {
+            if (dto.getStoreId() == null || dto.getStoreId() <= 0) {
+                 return R.data(null, "暂无承载数据!!!");
+            }
+            IPage<StoreOperationalActivityVO> result = activityService.queryActivityList( dto.getStoreId(), dto.getStatus(), dto.getActivityName(), dto.getPageNum(), dto.getPageSize());
+            return R.data(result);
+        } catch (Exception e) {
+            log.error("OperationalActivityController.qeryActivityList ERROR: {}", e.getMessage(), e);
+            return R.fail(e.getMessage());
+        }
+    }
+
+
+    @ApiOperation("启用/禁用活动")
+    @ApiOperationSupport(order = 7)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "活动ID", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "status", value = "状态:0-禁用, 1-启用", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/updateStatus")
+    public R<String> updateActivityStatus(
+            @RequestParam("id") Integer id,
+            @RequestParam("status") Integer status) {
+        log.info("OperationalActivityController.updateActivityStatus: id={}, status={}", id, status);
+        try {
+            int result = activityService.updateActivityStatus(id, status);
+            if (result > 0) {
+                return R.success("状态更新成功");
+            }
+            return R.fail("状态更新失败");
+        } catch (Exception e) {
+            log.error("OperationalActivityController.updateActivityStatus ERROR: {}", e.getMessage(), e);
+            return R.fail(e.getMessage());
+        }
+    }
+}
+

+ 72 - 13
alien-store-platform/src/main/java/shop/alien/storeplatform/controller/StoreMenuPlatformController.java

@@ -1,25 +1,23 @@
 package shop.alien.storeplatform.controller;
 
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiImplicitParam;
-import io.swagger.annotations.ApiImplicitParams;
-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.CrossOrigin;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 import shop.alien.entity.result.R;
 import shop.alien.entity.store.StoreMenu;
 import shop.alien.entity.store.vo.StoreMenuVo;
 import shop.alien.storeplatform.service.StoreMenuPlatformService;
+import shop.alien.storeplatform.vo.ExcelImportVo;
 
+import javax.servlet.http.HttpServletResponse;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
 import java.util.List;
 
 /**
@@ -125,6 +123,67 @@ public class StoreMenuPlatformController {
         log.info("StoreMenuController.getMenuLikeStatus?userId={}&menuId={}", userId, menuId);
         return R.data(storeMenuService.getMenuLikeStatus(userId, menuId));
     }
+
+    @ApiOperation("Excel导入门店菜单")
+    @ApiOperationSupport(order = 9)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "file", value = "Excel文件", dataType = "file", paramType = "form", required = true),
+            @ApiImplicitParam(name = "storeId", value = "门店id", dataType = "Integer", paramType = "query", required = true)
+    })
+    @PostMapping("/importMenu")
+    public R<String> importMenu(ExcelImportVo vo) {
+        log.info("StoreMenuPlatformController.importMenu?storeId={}", vo.getStoreId());
+        return storeMenuService.importMenuFromExcel(vo.getFile(), vo.getStoreId());
+    }
+
+    @ApiOperation("下载美食导入模板")
+    @ApiOperationSupport(order = 10)
+    @GetMapping("/downloadTemplate")
+    public void downloadTemplate(HttpServletResponse response) {
+        log.info("StoreMenuPlatformController.downloadTemplate");
+        InputStream inputStream = null;
+        OutputStream outputStream = null;
+        
+        try {
+            // 从resources/templates目录读取模板文件
+            Resource resource = new ClassPathResource("templates/美食导入模板.xlsx");
+            inputStream = resource.getInputStream();
+            
+            // 设置响应头
+            response.reset();
+            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+            response.setCharacterEncoding("utf-8");
+            
+            String fileName = "美食导入模板.xlsx";
+            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString()).replaceAll("\\+", "%20");
+            response.setHeader("Content-Disposition", "attachment;filename=\"" + encodedFileName + "\";filename*=utf-8''" + encodedFileName);
+            
+            // 输出文件流
+            outputStream = response.getOutputStream();
+            byte[] buffer = new byte[1024];
+            int length;
+            while ((length = inputStream.read(buffer)) > 0) {
+                outputStream.write(buffer, 0, length);
+            }
+            outputStream.flush();
+            
+            log.info("美食导入模板下载成功");
+        } catch (Exception e) {
+            log.error("下载美食导入模板失败", e);
+            throw new RuntimeException("下载模板失败:" + e.getMessage());
+        } finally {
+            try {
+                if (inputStream != null) {
+                    inputStream.close();
+                }
+                if (outputStream != null) {
+                    outputStream.close();
+                }
+            } catch (Exception e) {
+                log.error("关闭流失败", e);
+            }
+        }
+    }
 }
 
 

+ 189 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/controller/StorePlatformBarMenuController.java

@@ -0,0 +1,189 @@
+package shop.alien.storeplatform.controller;
+
+import io.swagger.annotations.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import shop.alien.entity.result.R;
+import shop.alien.storeplatform.entity.StorePlatformStoreMenu;
+import shop.alien.storeplatform.service.StorePlatformBarMenuService;
+import shop.alien.storeplatform.vo.ExcelImportVo;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+/**
+ * 商户平台-酒吧菜单Controller
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Slf4j
+@Api(tags = {"商户平台-酒吧菜单"})
+@ApiSort(4)
+@CrossOrigin
+@RestController
+@RequestMapping("/barMenu")
+@RequiredArgsConstructor
+public class StorePlatformBarMenuController {
+
+    private final StorePlatformBarMenuService barMenuService;
+
+    @ApiOperation("根据ID查询菜单")
+    @ApiOperationSupport(order = 1)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "菜单ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/getById")
+    public R<StorePlatformStoreMenu> getById(@RequestParam("id") Integer id) {
+        log.info("StorePlatformBarMenuController.getById id={}", id);
+        StorePlatformStoreMenu menu = barMenuService.getById(id);
+        if (menu == null) {
+            return R.fail("菜单不存在");
+        }
+        return R.data(menu);
+    }
+
+    @ApiOperation("根据门店ID查询菜单列表")
+    @ApiOperationSupport(order = 2)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/getListByStoreId")
+    public R<List<StorePlatformStoreMenu>> getListByStoreId(@RequestParam("storeId") Integer storeId) {
+        log.info("StorePlatformBarMenuController.getListByStoreId storeId={}", storeId);
+        List<StorePlatformStoreMenu> list = barMenuService.getListByStoreId(storeId);
+        return R.data(list);
+    }
+
+    @ApiOperation("根据门店ID和菜单类型查询菜单列表")
+    @ApiOperationSupport(order = 3)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "dishMenuType", value = "菜单类型:1-菜单,2-酒水", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "dishType", value = "是否推荐, 0:非推荐, 1:推荐", dataType = "String", paramType = "query")
+    })
+    @GetMapping("/getListByStoreIdAndType")
+    public R<List<StorePlatformStoreMenu>> getListByStoreIdAndType(
+            @RequestParam("storeId") Integer storeId,
+            @RequestParam(value = "dishMenuType", required = false) String dishMenuType,
+            @RequestParam(value = "dishType", required = false) String dishType) {
+        log.info("StorePlatformBarMenuController.getListByStoreIdAndType storeId={}, dishMenuType={}, dishType={}", storeId, dishMenuType, dishType);
+        List<StorePlatformStoreMenu> list = barMenuService.getListByStoreIdAndType(storeId, dishMenuType, dishType);
+        return R.data(list);
+    }
+
+    @ApiOperation("新增菜单")
+    @ApiOperationSupport(order = 4)
+    @PostMapping("/save")
+    public R<StorePlatformStoreMenu> save(@RequestBody StorePlatformStoreMenu storeMenu) {
+        log.info("StorePlatformBarMenuController.save storeMenu={}", storeMenu);
+        return barMenuService.saveMenu(storeMenu);
+    }
+
+    @ApiOperation("修改菜单")
+    @ApiOperationSupport(order = 5)
+    @PostMapping("/update")
+    public R<StorePlatformStoreMenu> update(@RequestBody StorePlatformStoreMenu storeMenu) {
+        log.info("StorePlatformBarMenuController.update storeMenu={}", storeMenu);
+        return barMenuService.updateMenu(storeMenu);
+    }
+
+    @ApiOperation("新增或修改菜单")
+    @ApiOperationSupport(order = 6)
+    @PostMapping("/saveOrUpdate")
+    public R<StorePlatformStoreMenu> saveOrUpdate(@RequestBody StorePlatformStoreMenu storeMenu) {
+        log.info("StorePlatformBarMenuController.saveOrUpdate storeMenu={}", storeMenu);
+        return barMenuService.saveOrUpdateMenu(storeMenu);
+    }
+
+    @ApiOperation("删除菜单")
+    @ApiOperationSupport(order = 7)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "菜单ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/delete")
+    public R<String> delete(@RequestParam("id") Integer id) {
+        log.info("StorePlatformBarMenuController.delete id={}", id);
+        return barMenuService.deleteMenu(id);
+    }
+
+    @ApiOperation("批量删除菜单")
+    @ApiOperationSupport(order = 8)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "ids", value = "菜单ID列表", dataType = "List", paramType = "query", required = true)
+    })
+    @GetMapping("/deleteBatch")
+    public R<String> deleteBatch(@RequestParam("ids") List<Integer> ids) {
+        log.info("StorePlatformBarMenuController.deleteBatch ids={}", ids);
+        return barMenuService.deleteMenuBatch(ids);
+    }
+
+    @ApiOperation("Excel导入酒吧菜单")
+    @ApiOperationSupport(order = 9)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "file", value = "Excel文件", dataType = "file", paramType = "form", required = true),
+            @ApiImplicitParam(name = "storeId", value = "门店id", dataType = "Integer", paramType = "query", required = true)
+    })
+    @PostMapping("/importMenu")
+    public R<String> importMenu(ExcelImportVo vo) {
+        log.info("StorePlatformBarMenuController.importMenu storeId={}", vo.getStoreId());
+        return barMenuService.importMenuFromExcel(vo.getFile(), vo.getStoreId());
+    }
+
+    @ApiOperation("下载酒水餐食导入模板")
+    @ApiOperationSupport(order = 10)
+    @GetMapping("/downloadTemplate")
+    public void downloadTemplate(HttpServletResponse response) {
+        log.info("StoreMenuPlatformController.downloadTemplate");
+        InputStream inputStream = null;
+        OutputStream outputStream = null;
+
+        try {
+            // 从resources/templates目录读取模板文件
+            Resource resource = new ClassPathResource("templates/酒水餐食导入模板.xlsx");
+            inputStream = resource.getInputStream();
+
+            // 设置响应头
+            response.reset();
+            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+            response.setCharacterEncoding("utf-8");
+
+            String fileName = "酒水餐食导入模板.xlsx";
+            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString()).replaceAll("\\+", "%20");
+            response.setHeader("Content-Disposition", "attachment;filename=\"" + encodedFileName + "\";filename*=utf-8''" + encodedFileName);
+
+            // 输出文件流
+            outputStream = response.getOutputStream();
+            byte[] buffer = new byte[1024];
+            int length;
+            while ((length = inputStream.read(buffer)) > 0) {
+                outputStream.write(buffer, 0, length);
+            }
+            outputStream.flush();
+
+            log.info("酒水餐食导入模板下载成功");
+        } catch (Exception e) {
+            log.error("下载酒水餐食导入模板失败", e);
+            throw new RuntimeException("下载模板失败:" + e.getMessage());
+        } finally {
+            try {
+                if (inputStream != null) {
+                    inputStream.close();
+                }
+                if (outputStream != null) {
+                    outputStream.close();
+                }
+            } catch (Exception e) {
+                log.error("关闭流失败", e);
+            }
+        }
+    }
+}

+ 186 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/controller/StorePlatformBathFacilityServiceController.java

@@ -0,0 +1,186 @@
+package shop.alien.storeplatform.controller;
+
+import io.swagger.annotations.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import shop.alien.entity.result.R;
+import shop.alien.storeplatform.entity.StorePlatformBathFacility;
+import shop.alien.storeplatform.service.StorePlatformBathFacilityService;
+import shop.alien.storeplatform.vo.ExcelImportVo;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+/**
+ * 商户平台-洗浴设施及服务Controller
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Slf4j
+@Api(tags = {"商户平台-洗浴汗蒸"})
+@ApiSort(4)
+@CrossOrigin
+@RestController
+@RequestMapping("/bathFacilityService")
+@RequiredArgsConstructor
+public class StorePlatformBathFacilityServiceController {
+
+    private final StorePlatformBathFacilityService facilityService;
+
+    @ApiOperation("根据ID查询设施")
+    @ApiOperationSupport(order = 1)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "设施ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/getById")
+    public R<StorePlatformBathFacility> getById(@RequestParam("id") Integer id) {
+        log.info("StorePlatformBathFacilityServiceController.getById id={}", id);
+        StorePlatformBathFacility facility = facilityService.getById(id);
+        if (facility == null) {
+            return R.fail("设施不存在");
+        }
+        return R.data(facility);
+    }
+
+    @ApiOperation("根据门店ID查询设施列表")
+    @ApiOperationSupport(order = 2)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/getListByStoreId")
+    public R<List<StorePlatformBathFacility>> getListByStoreId(@RequestParam("storeId") Integer storeId) {
+        log.info("StorePlatformBathFacilityServiceController.getListByStoreId storeId={}", storeId);
+        List<StorePlatformBathFacility> list = facilityService.getListByStoreId(storeId);
+        return R.data(list);
+    }
+
+    @ApiOperation("根据门店ID和区域分类查询设施列表")
+    @ApiOperationSupport(order = 3)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "facilityCategory", value = "区域分类(1:洗浴区, 2:汗蒸区, 3:休闲区, 4:餐饮区)", dataType = "Integer", paramType = "query")
+    })
+    @GetMapping("/getListByStoreIdAndCategory")
+    public R<List<StorePlatformBathFacility>> getListByStoreIdAndCategory(@RequestParam("storeId") Integer storeId,
+                                                                         @RequestParam(value = "facilityCategory", required = false) Integer facilityCategory) {
+        log.info("StorePlatformBathFacilityServiceController.getListByStoreIdAndCategory storeId={}, facilityCategory={}", storeId, facilityCategory);
+        List<StorePlatformBathFacility> list = facilityService.getListByStoreIdAndCategory(storeId, facilityCategory);
+        return R.data(list);
+    }
+
+    @ApiOperation("新增设施")
+    @ApiOperationSupport(order = 4)
+    @PostMapping("/save")
+    public R<StorePlatformBathFacility> save(@RequestBody StorePlatformBathFacility facility) {
+        log.info("StorePlatformBathFacilityServiceController.save facility={}", facility);
+        return facilityService.saveFacility(facility);
+    }
+
+    @ApiOperation("修改设施")
+    @ApiOperationSupport(order = 5)
+    @PostMapping("/update")
+    public R<StorePlatformBathFacility> update(@RequestBody StorePlatformBathFacility facility) {
+        log.info("StorePlatformBathFacilityServiceController.update facility={}", facility);
+        return facilityService.updateFacility(facility);
+    }
+
+    @ApiOperation("新增或修改设施")
+    @ApiOperationSupport(order = 6)
+    @PostMapping("/saveOrUpdate")
+    public R<StorePlatformBathFacility> saveOrUpdate(@RequestBody StorePlatformBathFacility facility) {
+        log.info("StorePlatformBathFacilityServiceController.saveOrUpdate facility={}", facility);
+        return facilityService.saveOrUpdateFacility(facility);
+    }
+
+    @ApiOperation("删除设施")
+    @ApiOperationSupport(order = 7)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "设施ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/delete")
+    public R<String> delete(@RequestParam("id") Integer id) {
+        log.info("StorePlatformBathFacilityServiceController.delete id={}", id);
+        return facilityService.deleteFacility(id);
+    }
+
+    @ApiOperation("批量删除设施")
+    @ApiOperationSupport(order = 8)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "ids", value = "设施ID列表", dataType = "List", paramType = "query", required = true)
+    })
+    @GetMapping("/deleteBatch")
+    public R<String> deleteBatch(@RequestParam("ids") List<Integer> ids) {
+        log.info("StorePlatformBathFacilityServiceController.deleteBatch ids={}", ids);
+        return facilityService.deleteFacilityBatch(ids);
+    }
+
+    @ApiOperation("Excel导入洗浴汗蒸设施")
+    @ApiOperationSupport(order = 9)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "file", value = "Excel文件", dataType = "file", paramType = "form", required = true),
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @PostMapping("/importFacility")
+    public R<String> importFacility(ExcelImportVo vo) {
+        log.info("StorePlatformBathFacilityServiceController.importFacility storeId={}", vo.getStoreId());
+        return facilityService.importFacilityFromExcel(vo.getFile(), vo.getStoreId());
+    }
+
+    @ApiOperation("下载洗浴汗蒸导入模板")
+    @ApiOperationSupport(order = 10)
+    @GetMapping("/downloadTemplate")
+    public void downloadTemplate(HttpServletResponse response) {
+        log.info("StorePlatformBathFacilityServiceController.downloadTemplate");
+        InputStream inputStream = null;
+        OutputStream outputStream = null;
+
+        try {
+            // 从resources/templates目录读取模板文件
+            Resource resource = new ClassPathResource("templates/洗浴汗蒸导入模板.xlsx");
+            inputStream = resource.getInputStream();
+
+            // 设置响应头
+            response.reset();
+            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+            response.setCharacterEncoding("utf-8");
+
+            String fileName = "洗浴汗蒸导入模板.xlsx";
+            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString()).replaceAll("\\+", "%20");
+            response.setHeader("Content-Disposition", "attachment;filename=\"" + encodedFileName + "\";filename*=utf-8''" + encodedFileName);
+
+            // 输出文件流
+            outputStream = response.getOutputStream();
+            byte[] buffer = new byte[1024];
+            int length;
+            while ((length = inputStream.read(buffer)) > 0) {
+                outputStream.write(buffer, 0, length);
+            }
+            outputStream.flush();
+
+            log.info("洗浴汗蒸导入模板下载成功");
+        } catch (Exception e) {
+            log.error("下载洗浴汗蒸导入模板失败", e);
+            throw new RuntimeException("下载模板失败:" + e.getMessage());
+        } finally {
+            try {
+                if (inputStream != null) {
+                    inputStream.close();
+                }
+                if (outputStream != null) {
+                    outputStream.close();
+                }
+            } catch (Exception e) {
+                log.error("关闭流失败", e);
+            }
+        }
+    }
+}

+ 187 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/controller/StorePlatformSportsEquipmentFacilityController.java

@@ -0,0 +1,187 @@
+package shop.alien.storeplatform.controller;
+
+import io.swagger.annotations.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import shop.alien.entity.result.R;
+import shop.alien.storeplatform.entity.StorePlatformSportsEquipmentFacility;
+import shop.alien.storeplatform.service.StorePlatformSportsEquipmentFacilityService;
+import shop.alien.storeplatform.vo.ExcelImportVo;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+/**
+ * 商户平台-运动器材设施Controller
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Slf4j
+@Api(tags = {"商户平台-运动健身-设施器材"})
+@ApiSort(1)
+@CrossOrigin
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("/sportsEquipmentFacility")
+public class StorePlatformSportsEquipmentFacilityController {
+
+    private final StorePlatformSportsEquipmentFacilityService facilityService;
+
+    @ApiOperation("根据ID查询设施")
+    @ApiOperationSupport(order = 1)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "设施ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/getById")
+    public R<StorePlatformSportsEquipmentFacility> getById(@RequestParam("id") Integer id) {
+        log.info("StorePlatformSportsEquipmentFacilityController.getById id={}", id);
+        StorePlatformSportsEquipmentFacility facility = facilityService.getById(id);
+        if (facility == null) {
+            return R.fail("设施不存在");
+        }
+        return R.data(facility);
+    }
+
+    @ApiOperation("根据门店ID查询设施列表")
+    @ApiOperationSupport(order = 2)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/getListByStoreId")
+    public R<List<StorePlatformSportsEquipmentFacility>> getListByStoreId(@RequestParam("storeId") Integer storeId) {
+        log.info("StorePlatformSportsEquipmentFacilityController.getListByStoreId storeId={}", storeId);
+        List<StorePlatformSportsEquipmentFacility> list = facilityService.getListByStoreId(storeId);
+        return R.data(list);
+    }
+
+    @ApiOperation("根据门店ID和设施分类查询设施列表")
+    @ApiOperationSupport(order = 3)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "facilityCategory", value = "设施分类(1:有氧区, 2:力量区, 3:单功能机械区)", dataType = "Integer", paramType = "query")
+    })
+    @GetMapping("/getListByStoreIdAndCategory")
+    public R<List<StorePlatformSportsEquipmentFacility>> getListByStoreIdAndCategory(@RequestParam("storeId") Integer storeId,
+                                                                                     @RequestParam(value = "facilityCategory", required = false) Integer facilityCategory) {
+        log.info("StorePlatformSportsEquipmentFacilityController.getListByStoreIdAndCategory storeId={}, facilityCategory={}", storeId, facilityCategory);
+        List<StorePlatformSportsEquipmentFacility> list = facilityService.getListByStoreIdAndCategory(storeId, facilityCategory);
+        return R.data(list);
+    }
+
+    @ApiOperation("新增设施")
+    @ApiOperationSupport(order = 4)
+    @PostMapping("/save")
+    public R<String> save(@RequestBody StorePlatformSportsEquipmentFacility facility) {
+        log.info("StorePlatformSportsEquipmentFacilityController.save facility={}", facility);
+        return facilityService.saveFacility(facility);
+    }
+
+    @ApiOperation("修改设施")
+    @ApiOperationSupport(order = 5)
+    @PostMapping("/update")
+    public R<String> update(@RequestBody StorePlatformSportsEquipmentFacility facility) {
+        log.info("StorePlatformSportsEquipmentFacilityController.update facility={}", facility);
+        return facilityService.updateFacility(facility);
+    }
+
+    @ApiOperation("新增或修改设施")
+    @ApiOperationSupport(order = 6)
+    @PostMapping("/saveOrUpdate")
+    public R<String> saveOrUpdate(@RequestBody StorePlatformSportsEquipmentFacility facility) {
+        log.info("StorePlatformSportsEquipmentFacilityController.saveOrUpdate facility={}", facility);
+        return facilityService.saveOrUpdateFacility(facility);
+    }
+
+    @ApiOperation("删除设施")
+    @ApiOperationSupport(order = 7)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "设施ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/delete")
+    public R<String> delete(@RequestParam("id") Integer id) {
+        log.info("StorePlatformSportsEquipmentFacilityController.delete id={}", id);
+        return facilityService.deleteFacility(id);
+    }
+
+    @ApiOperation("批量删除设施")
+    @ApiOperationSupport(order = 8)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "ids", value = "设施ID列表", dataType = "List", paramType = "query", required = true)
+    })
+    @GetMapping("/deleteBatch")
+    public R<String> deleteBatch(@RequestParam("ids") List<Integer> ids) {
+        log.info("StorePlatformSportsEquipmentFacilityController.deleteBatch ids={}", ids);
+        return facilityService.deleteFacilityBatch(ids);
+    }
+
+    @ApiOperation("Excel导入运动健身设施")
+    @ApiOperationSupport(order = 9)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "file", value = "Excel文件", dataType = "file", paramType = "form", required = true),
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @PostMapping("/importFacility")
+    public R<String> importFacility(ExcelImportVo vo) {
+        log.info("StorePlatformSportsEquipmentFacilityController.importFacility storeId={}", vo.getStoreId());
+        return facilityService.importFacilityFromExcel(vo.getFile(), vo.getStoreId());
+    }
+
+    @ApiOperation("下载运动健身导入模板")
+    @ApiOperationSupport(order = 10)
+    @GetMapping("/downloadTemplate")
+    public void downloadTemplate(HttpServletResponse response) {
+        log.info("StoreMenuPlatformController.downloadTemplate");
+        InputStream inputStream = null;
+        OutputStream outputStream = null;
+
+        try {
+            // 从resources/templates目录读取模板文件
+            Resource resource = new ClassPathResource("templates/运动健身导入模板.xlsx");
+            inputStream = resource.getInputStream();
+
+            // 设置响应头
+            response.reset();
+            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+            response.setCharacterEncoding("utf-8");
+
+            String fileName = "运动健身导入模板.xlsx";
+            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString()).replaceAll("\\+", "%20");
+            response.setHeader("Content-Disposition", "attachment;filename=\"" + encodedFileName + "\";filename*=utf-8''" + encodedFileName);
+
+            // 输出文件流
+            outputStream = response.getOutputStream();
+            byte[] buffer = new byte[1024];
+            int length;
+            while ((length = inputStream.read(buffer)) > 0) {
+                outputStream.write(buffer, 0, length);
+            }
+            outputStream.flush();
+
+            log.info("运动健身导入模板下载成功");
+        } catch (Exception e) {
+            log.error("下载运动健身导入模板失败", e);
+            throw new RuntimeException("下载模板失败:" + e.getMessage());
+        } finally {
+            try {
+                if (inputStream != null) {
+                    inputStream.close();
+                }
+                if (outputStream != null) {
+                    outputStream.close();
+                }
+            } catch (Exception e) {
+                log.error("关闭流失败", e);
+            }
+        }
+    }
+}

+ 97 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/controller/StorePlatformStoreStaffConfigController.java

@@ -0,0 +1,97 @@
+package shop.alien.storeplatform.controller;
+
+import io.swagger.annotations.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.storeplatform.entity.StorePlatformStoreStaffConfig;
+import shop.alien.storeplatform.service.StorePlatformStoreStaffConfigService;
+
+import java.util.List;
+
+@Slf4j
+@Api(tags = {"商户平台-运动健身-人员配置"})
+@ApiSort(1)
+@CrossOrigin
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("/storeStaffConfig")
+public class StorePlatformStoreStaffConfigController {
+
+    private final StorePlatformStoreStaffConfigService staffConfigService;
+
+    @ApiOperation("根据ID查询员工")
+    @ApiOperationSupport(order = 1)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "员工ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/getById")
+    public R<StorePlatformStoreStaffConfig> getById(@RequestParam("id") Integer id) {
+        log.info("StorePlatformStoreStaffConfigController.getById id={}", id);
+        StorePlatformStoreStaffConfig staffConfig = staffConfigService.getById(id);
+        if (staffConfig == null) {
+            return R.fail("员工不存在");
+        }
+        return R.data(staffConfig);
+    }
+
+    @ApiOperation("根据门店ID查询员工列表")
+    @ApiOperationSupport(order = 2)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/getListByStoreId")
+    public R<List<StorePlatformStoreStaffConfig>> getListByStoreId(@RequestParam("storeId") Integer storeId) {
+        log.info("StorePlatformStoreStaffConfigController.getListByStoreId storeId={}", storeId);
+        List<StorePlatformStoreStaffConfig> list = staffConfigService.getListByStoreId(storeId);
+        return R.data(list);
+    }
+
+    @ApiOperation("新增员工")
+    @ApiOperationSupport(order = 3)
+    @PostMapping("/save")
+    public R<String> save(@RequestBody StorePlatformStoreStaffConfig staffConfig) {
+        log.info("StorePlatformStoreStaffConfigController.save staffConfig={}", staffConfig);
+        return staffConfigService.saveStaff(staffConfig);
+    }
+
+    @ApiOperation("修改员工")
+    @ApiOperationSupport(order = 4)
+    @PostMapping("/update")
+    public R<String> update(@RequestBody StorePlatformStoreStaffConfig staffConfig) {
+        log.info("StorePlatformStoreStaffConfigController.update staffConfig={}", staffConfig);
+        return staffConfigService.updateStaff(staffConfig);
+    }
+
+    @ApiOperation("新增或修改员工")
+    @ApiOperationSupport(order = 5)
+    @PostMapping("/saveOrUpdate")
+    public R<String> saveOrUpdate(@RequestBody StorePlatformStoreStaffConfig staffConfig) {
+        log.info("StorePlatformStoreStaffConfigController.saveOrUpdate staffConfig={}", staffConfig);
+        return staffConfigService.saveOrUpdateStaff(staffConfig);
+    }
+
+    @ApiOperation("删除员工")
+    @ApiOperationSupport(order = 6)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "员工ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/delete")
+    public R<String> delete(@RequestParam("id") Integer id) {
+        log.info("StorePlatformStoreStaffConfigController.delete id={}", id);
+        return staffConfigService.deleteStaff(id);
+    }
+
+    @ApiOperation("批量删除员工")
+    @ApiOperationSupport(order = 7)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "ids", value = "员工ID列表", dataType = "List", paramType = "query", required = true)
+    })
+    @GetMapping("/deleteBatch")
+    public R<String> deleteBatch(@RequestParam("ids") List<Integer> ids) {
+        log.info("StorePlatformStoreStaffConfigController.deleteBatch ids={}", ids);
+        return staffConfigService.deleteStaffBatch(ids);
+    }
+}

+ 90 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/entity/StorePlatformBathFacility.java

@@ -0,0 +1,90 @@
+package shop.alien.storeplatform.entity;
+
+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 StorePlatformBathFacility 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;
+
+    @ApiModelProperty(value = "图片id")
+    @TableField(exist = false)
+    private String imgUrl;
+}
+

+ 82 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/entity/StorePlatformSportsEquipmentFacility.java

@@ -0,0 +1,82 @@
+package shop.alien.storeplatform.entity;
+
+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 StorePlatformSportsEquipmentFacility 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;
+}
+

+ 112 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/entity/StorePlatformStoreMenu.java

@@ -0,0 +1,112 @@
+package shop.alien.storeplatform.entity;
+
+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.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 二期-门店菜单
+ *
+ * @author ssk
+ * @since 2024-12-05
+ */
+@Data
+@JsonInclude
+@TableName("store_menu")
+@ApiModel(value = "StoreMenu对象", description = "门店菜单")
+public class StorePlatformStoreMenu {
+
+    @ApiModelProperty(value = "主键")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty(value = "门店id")
+    @TableField("store_id")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "图片id")
+    @TableField("img_id")
+    private Integer imgId;
+
+    @ApiModelProperty(value = "图片id")
+    @TableField(exist = false)
+    private String imgUrl;
+
+    @ApiModelProperty(value = "菜单类型:1-菜单,2-酒水")
+    @TableField("dish_menu_type")
+    private Integer dishMenuType;
+
+    @ApiModelProperty(value = "名称")
+    @TableField("dish_name")
+    private String dishName;
+
+    @ApiModelProperty(value = "价格")
+    @TableField("dish_price")
+    private BigDecimal dishPrice;
+
+    @ApiModelProperty(value = "是否推荐, 0:非推荐, 1:推荐")
+    @TableField("dish_type")
+    private Integer dishType;
+
+    @ApiModelProperty(value = "点赞数")
+    @TableField("like_count")
+    private Integer likeCount;
+
+    @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;
+
+    @ApiModelProperty(value = "单位")
+    @TableField("dishes_unit")
+    private String dishesUnit;
+
+    @ApiModelProperty(value = "成本价")
+    @TableField("cost_price")
+    private BigDecimal costPrice;
+
+    @ApiModelProperty(value = "排序")
+    @TableField("sort")
+    private int sort;
+
+    @ApiModelProperty(value = "描述")
+    @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;
+
+}

+ 103 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/entity/StorePlatformStoreStaffConfig.java

@@ -0,0 +1,103 @@
+package shop.alien.storeplatform.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+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 lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+/**
+ * @Author: fcw
+ * @CreateTime: 2025-04-11
+ * @Description: 员工管理
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@JsonInclude
+@TableName("store_staff_config")
+@ApiModel(value = "StoreStaffConfig对象", description = "员工管理")
+public class StorePlatformStoreStaffConfig extends Model<StorePlatformStoreStaffConfig> {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "主键id")
+    @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;
+
+    @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.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;
+
+    @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;
+}

+ 7 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/feign/AlienStoreFeign.java

@@ -2,8 +2,12 @@ package shop.alien.storeplatform.feign;
 
 import com.alibaba.fastjson.JSONObject;
 import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.http.MediaType;
 import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RequestPart;
+import org.springframework.web.multipart.MultipartFile;
 
 @FeignClient(url = "${feign.alienStore.url}", name = "alien-store")
 public interface AlienStoreFeign {
@@ -13,4 +17,7 @@ public interface AlienStoreFeign {
             @RequestParam(value = "messageReceiverId") String messageReceiverId,
             @RequestParam(value = "webSocketVoStr") String webSocketVoStr);
 
+    @PostMapping(value = "/file/uploadMore", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+    JSONObject uploadFile(@RequestPart("multipartRequest") MultipartFile multipartRequest);
+
 }

+ 10 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/mapper/StorePlatformBathFacilityServiceMapper.java

@@ -0,0 +1,10 @@
+package shop.alien.storeplatform.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import shop.alien.storeplatform.entity.StorePlatformBathFacility;
+
+
+@Mapper
+public interface StorePlatformBathFacilityServiceMapper extends BaseMapper<StorePlatformBathFacility> {
+}

Some files were not shown because too many files changed in this diff