Browse Source

Merge remote-tracking branch 'origin/master'

lyx 2 weeks ago
parent
commit
cf6a714724
60 changed files with 2300 additions and 710 deletions
  1. 6 0
      alien-config/pom.xml
  2. 4 0
      alien-config/src/main/java/shop/alien/config/databases/MyBatisFieldHandler.java
  3. 85 0
      alien-entity/src/main/java/shop/alien/entity/second/SecondComplaint.java
  4. 20 0
      alien-entity/src/main/java/shop/alien/entity/second/vo/SecondCommentVo.java
  5. 73 2
      alien-entity/src/main/java/shop/alien/entity/second/vo/SecondGoodsRecommendVo.java
  6. 69 0
      alien-entity/src/main/java/shop/alien/entity/store/LifeMessageNotDisturb.java
  7. 12 0
      alien-entity/src/main/java/shop/alien/entity/store/LifeUserViolation.java
  8. 12 0
      alien-entity/src/main/java/shop/alien/entity/store/StoreUser.java
  9. 35 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/LifeCouponStatusVo.java
  10. 3 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/LifeMessageVo.java
  11. 6 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreUserVo.java
  12. 9 0
      alien-entity/src/main/java/shop/alien/mapper/LifeBlacklistMapper.java
  13. 16 0
      alien-entity/src/main/java/shop/alien/mapper/LifeMessageNotDisturbMapper.java
  14. 6 0
      alien-entity/src/main/java/shop/alien/mapper/LifeNoticeMapper.java
  15. 17 0
      alien-entity/src/main/java/shop/alien/mapper/second/SecondComplaintMapper.java
  16. 4 1
      alien-entity/src/main/java/shop/alien/mapper/second/SecondRecommendMapper.java
  17. 12 0
      alien-entity/src/main/java/shop/alien/mapper/second/SecondShieldMapper.java
  18. 44 11
      alien-entity/src/main/resources/mapper/second/SecondGoodsInfoMapper.xml
  19. 1 1
      alien-second/src/main/java/shop/alien/second/controller/SecondGoodsCategoryController.java
  20. 101 2
      alien-second/src/main/java/shop/alien/second/controller/SecondGoodsController.java
  21. 11 45
      alien-second/src/main/java/shop/alien/second/controller/SecondRecommendController.java
  22. 58 0
      alien-second/src/main/java/shop/alien/second/controller/SecondShieldController.java
  23. 1 1
      alien-second/src/main/java/shop/alien/second/service/SecondGoodsCategoryService.java
  24. 1 1
      alien-second/src/main/java/shop/alien/second/service/SecondGoodsService.java
  25. 27 4
      alien-second/src/main/java/shop/alien/second/service/SecondRecommendService.java
  26. 9 2
      alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsCategoryServiceImpl.java
  27. 27 13
      alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsServiceImpl.java
  28. 154 112
      alien-second/src/main/java/shop/alien/second/service/impl/SecondRecommendServiceImpl.java
  29. 1 1
      alien-store/src/main/java/shop/alien/store/config/WebSocketProcess.java
  30. 7 5
      alien-store/src/main/java/shop/alien/store/controller/LifeCollectController.java
  31. 19 4
      alien-store/src/main/java/shop/alien/store/controller/LifeCouponController.java
  32. 18 0
      alien-store/src/main/java/shop/alien/store/controller/LifeDiscountCouponController.java
  33. 47 39
      alien-store/src/main/java/shop/alien/store/controller/LifeMessageController.java
  34. 43 0
      alien-store/src/main/java/shop/alien/store/controller/LifeMessageNotDisturbController.java
  35. 1 1
      alien-store/src/main/java/shop/alien/store/controller/StoreCommentController.java
  36. 7 2
      alien-store/src/main/java/shop/alien/store/controller/StoreInfoController.java
  37. 40 26
      alien-store/src/main/java/shop/alien/store/controller/StoreUserController.java
  38. 5 0
      alien-store/src/main/java/shop/alien/store/service/LifeCouponService.java
  39. 5 0
      alien-store/src/main/java/shop/alien/store/service/LifeDiscountCouponService.java
  40. 18 0
      alien-store/src/main/java/shop/alien/store/service/LifeMessageNotDisturbService.java
  41. 9 8
      alien-store/src/main/java/shop/alien/store/service/LifeMessageService.java
  42. 6 0
      alien-store/src/main/java/shop/alien/store/service/LifeStoreService.java
  43. 1 1
      alien-store/src/main/java/shop/alien/store/service/StoreInfoService.java
  44. 26 7
      alien-store/src/main/java/shop/alien/store/service/StoreUserService.java
  45. 34 4
      alien-store/src/main/java/shop/alien/store/service/impl/LifeCouponServiceImpl.java
  46. 32 0
      alien-store/src/main/java/shop/alien/store/service/impl/LifeDiscountCouponServiceImpl.java
  47. 42 0
      alien-store/src/main/java/shop/alien/store/service/impl/LifeMessageNotDisturbServiceImpl.java
  48. 319 236
      alien-store/src/main/java/shop/alien/store/service/impl/LifeMessageServiceImpl.java
  49. 1 1
      alien-store/src/main/java/shop/alien/store/service/impl/StoreCommentServiceImpl.java
  50. 19 12
      alien-store/src/main/java/shop/alien/store/service/impl/StoreInfoServiceImpl.java
  51. 244 27
      alien-store/src/main/java/shop/alien/store/service/impl/StoreUserServiceImpl.java
  52. 4 0
      alien-store/src/main/java/shop/alien/store/util/ali/AliSms.java
  53. 44 0
      alien-util/src/main/java/shop/alien/util/common/safe/DeepseekClient.java
  54. 18 0
      alien-util/src/main/java/shop/alien/util/common/safe/ImageModerationResultVO.java
  55. 112 29
      alien-util/src/main/java/shop/alien/util/common/safe/ImageModerationUtil.java
  56. 1 0
      alien-util/src/main/java/shop/alien/util/common/safe/ImageReviewServiceEnum.java
  57. 120 0
      alien-util/src/main/java/shop/alien/util/common/safe/ImageUrlDemo.java
  58. 0 10
      alien-util/src/main/java/shop/alien/util/common/safe/TextModerationResultVO.java
  59. 189 87
      alien-util/src/main/java/shop/alien/util/common/safe/TextModerationUtil.java
  60. 45 15
      alien-util/src/main/java/shop/alien/util/common/safe/TextReviewServiceEnum.java

+ 6 - 0
alien-config/pom.xml

@@ -65,6 +65,12 @@
             <artifactId>mybatis-plus-extension</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>shop.alien</groupId>
+            <artifactId>alien-util</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+
     </dependencies>
     <build>
         <plugins>

+ 4 - 0
alien-config/src/main/java/shop/alien/config/databases/MyBatisFieldHandler.java

@@ -3,8 +3,10 @@ package shop.alien.config.databases;
 import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
 import org.apache.ibatis.reflection.MetaObject;
 import org.springframework.stereotype.Component;
+import shop.alien.util.common.JwtUtil;
 
 import java.util.Date;
+import java.util.Objects;
 
 /**
  * Mybatis日期填充
@@ -25,6 +27,7 @@ public class MyBatisFieldHandler implements MetaObjectHandler {
     public void insertFill(MetaObject metaObject) {
         //字段为实体类名, 不是表字段名
         this.setFieldValByName("createdTime", new Date(), metaObject);
+        this.setFieldValByName("createdUserId", Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId"), metaObject);
     }
 
     /**
@@ -36,5 +39,6 @@ public class MyBatisFieldHandler implements MetaObjectHandler {
     public void updateFill(MetaObject metaObject) {
         //字段为实体类名, 不是表字段名
         this.setFieldValByName("updatedTime", new Date(), metaObject);
+        this.setFieldValByName("updatedUserId", Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId"), metaObject);
     }
 }

+ 85 - 0
alien-entity/src/main/java/shop/alien/entity/second/SecondComplaint.java

@@ -0,0 +1,85 @@
+package shop.alien.entity.second;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author ssk
+ * @since 2025-07-09
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value="SecondComplaint对象", description="")
+public class SecondComplaint extends Model<SecondComplaint> {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "主键id")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty(value = "用户id")
+    @TableField("user_id")
+    private Integer userId;
+
+    @ApiModelProperty(value = "投诉id")
+    @TableField("complaint_id")
+    private Integer complaintId;
+
+    @ApiModelProperty(value = "投诉类型  1-用户  2-商品")
+    @TableField("complaint_type")
+    private Integer complaintType;
+
+    @ApiModelProperty(value = "投诉原因")
+    @TableField("complaint_reason")
+    private String complaintReason;
+
+    @ApiModelProperty(value = "投诉状态  0-审核中  1-成功  2-失败")
+    @TableField("complaint_status")
+    private Integer complaintStatus;
+
+    @ApiModelProperty(value = "投诉结果")
+    @TableField("complaint_result")
+    private String complaintResult;
+
+    @ApiModelProperty(value = "删除标记 0:未删除 1:已删除")
+    @TableField("delete_flag")
+    @TableLogic
+    private Integer deleteFlag;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(value = "created_time", fill = FieldFill.INSERT)
+    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)
+    private Date updatedTime;
+
+    @ApiModelProperty(value = "修改人ID")
+    @TableField(value = "updated_user_id", fill = FieldFill.INSERT_UPDATE)
+    private Integer updatedUserId;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 20 - 0
alien-entity/src/main/java/shop/alien/entity/second/vo/SecondCommentVo.java

@@ -0,0 +1,20 @@
+package shop.alien.entity.second.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.StoreComment;
+
+@Data
+@JsonInclude
+@ApiModel(value = "二手商品", description = "用户信息")
+public class SecondCommentVo extends StoreComment {
+
+    @ApiModelProperty(value = "用户名")
+    private String userName;
+
+    @ApiModelProperty(value = "用户头像")
+    private String userImage;
+
+}

+ 73 - 2
alien-entity/src/main/java/shop/alien/entity/second/vo/SecondGoodsRecommendVo.java

@@ -1,13 +1,19 @@
 package shop.alien.entity.second.vo;
 
 import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import shop.alien.entity.second.SecondGoods;
 import shop.alien.entity.store.StoreComment;
+import shop.alien.entity.store.StoreImg;
 
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 @Data
 @JsonInclude
@@ -17,12 +23,18 @@ public class SecondGoodsRecommendVo extends SecondGoods {
     @ApiModelProperty(value = "用户名称")
     private String userName;
 
+    @ApiModelProperty(value = "用户PHONE")
+    private String userPhone;
+
     @ApiModelProperty(value = "用户头像")
     private String userImage;
 
     @ApiModelProperty(value = "距离")
     private String dist;
 
+    @ApiModelProperty(value = "是否关注")
+    private Integer fansStatus = 0;
+
     @ApiModelProperty(value = "是否点赞")
     private String likeStatus;
 
@@ -33,8 +45,67 @@ public class SecondGoodsRecommendVo extends SecondGoods {
     private String commentCount;
 
     @ApiModelProperty(value = "评论列表")
-    List<StoreComment> commentList;
+    private List<SecondCommentVo> commentList;
 
     @ApiModelProperty(value = "话题列表")
-    List<String> topicList;
+    @JsonProperty("topicList")
+    private List<String> topicList() {
+        return parseTopic(getTopic());
+    }
+
+    @ApiModelProperty(value = "图片列表")
+    private String[] imgList;
+
+    @ApiModelProperty(value = "发布时间")
+    @JsonProperty("timeAgo")
+    public String getFormattedTimeAgo() {
+        return getTimeAgo(getReleaseTime());
+    }
+
+
+    /**
+     * 解析话题列表
+     *
+     * @param topic 话题列表字符串
+     * @return 解析后的话题列表
+     */
+    public List<String> parseTopic(String topic) {
+        if (topic != null && !topic.isEmpty()) {
+            return Arrays.asList(topic.split(","));
+        } else {
+            return Collections.emptyList();
+        }
+    }
+
+    public String getTimeAgo(Date releaseTime) {
+        if (releaseTime == null) {
+            return "未知时间";
+        }
+
+        long now = System.currentTimeMillis();
+        long diff = now - releaseTime.getTime();
+
+        // 新增分钟级判断
+        long minutes = TimeUnit.MILLISECONDS.toMinutes(diff);
+        if (minutes < 1) {
+            return "刚刚";
+        } else if (minutes < 60) {
+            return minutes + "分钟前";
+        }
+
+        long hours = TimeUnit.MILLISECONDS.toHours(diff);
+        long days = TimeUnit.MILLISECONDS.toDays(diff);
+        long months = days / 31;
+        long years = days / 365;
+
+        if (hours < 24) {
+            return hours + "小时前";
+        } else if (days <= 31) {
+            return days + "天前";
+        } else if (years >= 1) {
+            return years + "年前";
+        } else {
+            return months + "个月前";
+        }
+    }
 }

+ 69 - 0
alien-entity/src/main/java/shop/alien/entity/store/LifeMessageNotDisturb.java

@@ -0,0 +1,69 @@
+package shop.alien.entity.store;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * <p>
+ * 消息免打扰
+ * </p>
+ *
+ * @author ssk
+ * @since 2025-07-11
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value="LifeMessageNotDisturb对象", description="消息免打扰")
+public class LifeMessageNotDisturb extends Model<LifeMessageNotDisturb> {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "主键id")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty(value = "用户id")
+    @TableField("phone_id")
+    private String phoneId;
+
+    @ApiModelProperty(value = "免打扰id")
+    @TableField("not_disturb_id")
+    private String notDisturbId;
+
+    @ApiModelProperty(value = "删除标记  0:未删除  1:已删除")
+    @TableField("delete_flag")
+    @TableLogic
+    private Integer deleteFlag;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(value = "created_time", fill = FieldFill.INSERT)
+    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)
+    private Date updatedTime;
+
+    @ApiModelProperty(value = "修改人ID")
+    @TableField(value = "updated_user_id", fill = FieldFill.INSERT_UPDATE)
+    private Integer updatedUserId;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

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

@@ -107,6 +107,18 @@ public class LifeUserViolation extends Model<LifeUserViolation> {
     @TableField(value = "report_result")
     private String reportResult;
 
+    @ApiModelProperty(value = "业务ID")
+    @TableField(value = "business_id")
+    private Integer businessId;
+
+    @ApiModelProperty(value = "举报类型")
+    @TableField(value = "dict_type")
+    private String dictType;
+
+    @ApiModelProperty(value = "举报类型ID")
+    @TableField(value = "dict_id")
+    private Integer dictId;
+
     @Override
     protected Serializable pkVal() {
         return this.id;

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

@@ -110,4 +110,16 @@ public class StoreUser extends Model<StoreUser> {
     @ApiModelProperty(value = "昵称")
     @TableField("nick_name")
     private String nickName;
+
+    @ApiModelProperty(value = "账号简介")
+    @TableField("account_blurb")
+    private String accountBlurb;
+
+    @ApiModelProperty(value = "注销code")
+    @TableField("logout_code")
+    private String logoutCode;
+
+    @ApiModelProperty(value = "头像")
+    @TableField("head_img")
+    private String headImg;
 }

+ 35 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/LifeCouponStatusVo.java

@@ -0,0 +1,35 @@
+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.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 优惠券状态信息DTO
+ * </p>
+ *
+ * @author zhangchen
+ * @since 2025-07-11
+ */
+@Data
+@JsonInclude
+@NoArgsConstructor
+@ApiModel(value="优惠券状态信息", description="优惠券状态信息")
+public class LifeCouponStatusVo {
+
+    @ApiModelProperty(value = "优惠券ID")
+    private String couponId;
+
+    @ApiModelProperty(value = "库存(优惠券数量)")
+    private Integer singleQty;
+
+    @ApiModelProperty(value = "限制购买数")
+    private Integer buyLimit;
+}

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

@@ -31,6 +31,9 @@ public class LifeMessageVo extends LifeMessage {
     @ApiModelProperty(value = "未读消息数量")
     private Long notReadCount;
 
+    @ApiModelProperty(value = "是否免打扰 0-未免打扰 1-免打扰")
+    private String isNotDisturb;
+
     @ApiModelProperty(value = "我是否关注对方 0-未关注 1-已关注")
     private String isFollowThis;
 

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

@@ -30,4 +30,10 @@ public class StoreUserVo extends StoreUser {
 
     @ApiModelProperty(value = "账号是否启用")
     private boolean switchStatus;
+
+    @ApiModelProperty(value = "验证码")
+    private String verificationCode;
+
+    @ApiModelProperty(value = "倒计时")
+    private long countdown;
 }

+ 9 - 0
alien-entity/src/main/java/shop/alien/mapper/LifeBlacklistMapper.java

@@ -2,7 +2,9 @@ package shop.alien.mapper;
 
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Select;
 import shop.alien.entity.store.LifeBlacklist;
+import shop.alien.entity.store.vo.LifeBlacklistVo;
 
 import java.util.List;
 
@@ -26,4 +28,11 @@ public interface LifeBlacklistMapper extends BaseMapper<LifeBlacklist> {
      * @return 拉黑用户id 集合
      */
     List<Integer> getBlackList(Integer userId);
+
+    @Select("select if (black.blocked_type = '2', concat('user_', user.user_phone), concat('store_', suser.phone)) phoneId " +
+            "from life_blacklist black " +
+            "left join life_user user on user.id = black.blocked_id and black.blocked_type = '2' and user.delete_flag = 0 " +
+            "left join store_user suser on suser.id = black.blocked_id and black.blocked_type = '1' and suser.delete_flag = 0 " +
+            "where black.blocker_type = #{userType} and black.blocker_id = #{userId} and black.delete_flag = 0 ")
+    List<LifeBlacklistVo> getPhoneIdByUserId(String userType, String userId);
 }

+ 16 - 0
alien-entity/src/main/java/shop/alien/mapper/LifeMessageNotDisturbMapper.java

@@ -0,0 +1,16 @@
+package shop.alien.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import shop.alien.entity.store.LifeMessageNotDisturb;
+
+/**
+ * <p>
+ * 消息免打扰 Mapper 接口
+ * </p>
+ *
+ * @author ssk
+ * @since 2025-07-11
+ */
+public interface LifeMessageNotDisturbMapper extends BaseMapper<LifeMessageNotDisturb> {
+
+}

+ 6 - 0
alien-entity/src/main/java/shop/alien/mapper/LifeNoticeMapper.java

@@ -2,9 +2,15 @@ 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.LifeNotice;
 
 @Mapper
 public interface LifeNoticeMapper extends BaseMapper<LifeNotice> {
 
+    @Select("select count(id) noReadNum from life_notice " +
+            "where delete_flag = 0 and is_read = 0 and receiver_id = #{receiverId} ")
+    int selectNoReadCount(@Param("receiverId") String receiverId);
+
 }

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

@@ -0,0 +1,17 @@
+package shop.alien.mapper.second;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import shop.alien.entity.second.SecondComplaint;
+
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author ssk
+ * @since 2025-07-09
+ */
+public interface SecondComplaintMapper extends BaseMapper<SecondComplaint> {
+
+}

+ 4 - 1
alien-entity/src/main/java/shop/alien/mapper/second/SecondRecommendMapper.java

@@ -3,6 +3,7 @@ package shop.alien.mapper.second;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.apache.ibatis.annotations.Param;
+import shop.alien.entity.second.vo.SecondCommentVo;
 import shop.alien.entity.second.vo.SecondGoodsRecommendVo;
 import shop.alien.entity.store.StoreComment;
 
@@ -22,5 +23,7 @@ public interface SecondRecommendMapper extends BaseMapper<SecondGoodsRecommendVo
 
     IPage<SecondGoodsRecommendVo> querySecondNewGoodsByPage(IPage<SecondGoodsRecommendVo> page,@Param("userId") String userId, @Param("phoneId") String phoneId, @Param("position") String position);
 
-    List<StoreComment> querySecondCommentInfo(@Param("ids") List<Integer> ids);
+    List<SecondCommentVo> querySecondCommentInfo(@Param("ids") List<Integer> ids);
+
+    SecondGoodsRecommendVo querySecondGoodsDetail(@Param("goodsId") Integer goodsId, @Param("phoneId") String phoneId, @Param("position") String position);
 }

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

@@ -0,0 +1,12 @@
+package shop.alien.mapper.second;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import shop.alien.entity.second.SecondShield;
+
+
+/**
+ * 二手商品映射器
+ */
+public interface SecondShieldMapper extends BaseMapper<SecondShield> {
+
+}

+ 44 - 11
alien-entity/src/main/resources/mapper/second/SecondGoodsInfoMapper.xml

@@ -27,14 +27,16 @@
         <result column="dist" property="dist" jdbcType="VARCHAR"/>
         <result column="isLike" property="isLike" jdbcType="VARCHAR"/>
         <result column="home_image" property="homeImage" jdbcType="VARCHAR"/>
+        <result column="user_phone" property="userPhone" jdbcType="VARCHAR"/>
     </resultMap>
 
     <!-- 分页查询推荐数据 -->
     <select id="getSecondRecommendByPage" resultType="shop.alien.entity.second.vo.SecondGoodsRecommendVo">
         with shieldUser as (
-            select g.id from second_shield s inner join second_goods g
-                on s.shield_id = g.user_id  and g.delete_flag = '0' and goods_status = '3' and s.delete_flag = '0'
-            where s.user_id = #{userId} and s.shield_type = 2
+            select g.id from life_blacklist lb inner join second_goods g
+                on lb.blocked_id = g.user_id  and g.delete_flag = '0' and g.goods_status = '3'
+            where lb.delete_flag = 0 and lb.blocker_type = 2 and lb.blocked_type = 2
+                and lb.blocker_id = #{userId}
         )
         SELECT
             g.id,
@@ -68,7 +70,7 @@
             <if test="typeId != null and typeId != '' ">
                 and (g.category_one_id = #{typeId} or g.category_two_id =#{typeId} )
             </if>
-            and not exists (select 1 from second_shield s where s.id = g.id)
+            and not exists (select 1 from shieldUser s where s.id = g.id)
             and not exists (select 1 from second_shield s where s.user_id = #{userId} and s.shield_type = 1 and s.shield_id = g.id and s.delete_flag = 0)
             and g.goods_status = 3
         order by dist, like_count desc, created_time desc
@@ -80,7 +82,7 @@
             g.id,
             g.user_id,
             g.title,
-            g.describe,
+            g.description,
             g.price,
             ROUND(ST_Distance_Sphere(ST_GeomFromText(CONCAT('POINT(', REPLACE(#{position}, ',', ' '), ')' )), ST_GeomFromText(CONCAT('POINT(', REPLACE(g.position, ',', ' '), ')' ))) / 1000, 2) AS dist,
             g.like_count,
@@ -107,12 +109,12 @@
                 and g.goods_status = 3
                 and g.delete_flag = 0
             left join life_like_record llr on llr.dianzan_id = #{phoneId} and llr.huifu_id = g.id and llr.type = 6 and llr.delete_flag = 0
-            left join life_collect lc on lc.goods_id = g.id and lc.user_id = #{phoneId} and lc.delete_flag = 0
+            left join life_collect lc on lc.business_id = g.id and lc.user_id = #{phoneId} and lc.delete_flag = 0 and lc.business_type = 1
         where
             f.fans_id = #{phoneId} and f.delete_flag = 0
     </select>
 
-    <select id="querySecondCommentInfo" resultType="shop.alien.entity.store.StoreComment">
+    <select id="querySecondCommentInfo" resultType="shop.alien.entity.second.vo.SecondCommentVo">
         select
             business_id,
             comment_content,
@@ -141,9 +143,10 @@
     <!-- 分页查询推荐数据 -->
     <select id="querySecondNewGoodsByPage" resultType="shop.alien.entity.second.vo.SecondGoodsRecommendVo">
         with shieldUser as (
-            select g.id from second_shield s inner join second_goods g
-            on s.shield_id = g.user_id  and g.delete_flag = '0' and goods_status = '3' and s.delete_flag = '0'
-            where s.user_id = #{userId} and s.shield_type = 2
+            select g.id from life_blacklist lb inner join second_goods g
+                on lb.blocked_id = g.user_id  and g.delete_flag = '0' and g.goods_status = '3'
+            where lb.delete_flag = 0 and lb.blocker_type = 2 and lb.blocked_type = 2
+                and lb.blocker_id = #{userId}
         )
         SELECT
             g.id,
@@ -175,11 +178,41 @@
         FROM
             second_goods g inner join life_user u on u.id =  g.user_id
             left join life_like_record llr on llr.dianzan_id = #{phoneId} and llr.huifu_id = g.id and llr.type = 6 and llr.delete_flag = 0
-            left join life_collect lc on lc.goods_id = g.id and lc.user_id = #{phoneId} and lc.delete_flag = 0
+            left join life_collect lc on lc.business_id = g.id and lc.user_id = #{phoneId} and lc.delete_flag = 0 and lc.business_type = 1
         where g.delete_flag = 0
             and not exists (select 1 from shieldUser s where s.id = g.id)
             and not exists (select 1 from second_shield s where s.user_id = #{userId} and s.shield_type = 1 and s.shield_id = g.id)
             and g.goods_status = 3
     </select>
 
+    <select id="querySecondGoodsDetail" resultType="shop.alien.entity.second.vo.SecondGoodsRecommendVo">
+        select
+            g.id,
+            g.user_id,
+            g.title,
+            g.description,
+            g.price,
+            g.position,
+            g.like_count,
+            g.collect_count,
+            g.category_one_id,
+            g.category_two_id,
+            g.label,
+            g.topic,
+            g.home_image,
+            g.release_time,
+            lu.user_name,
+            CONCAT('user_', lu.user_phone) as user_phone,
+            lu.user_image,
+            goods_status,
+            ROUND(ST_Distance_Sphere(ST_GeomFromText(CONCAT('POINT(', REPLACE(#{position}, ',', ' '), ')' )), ST_GeomFromText(CONCAT('POINT(', REPLACE(g.position, ',', ' '), ')' ))) / 1000, 2) AS dist,
+            (select count(1) from store_comment c where c.business_id = g.id and c.business_type = 6 and c.delete_flag = 0) as commentCount,
+            case when llr.id is null then '0' else '1' end likeStatus,
+            case when lc.id is null then '0' else '1' end collectStatus
+        from second_goods g inner join life_user lu on g.user_id = lu.id and lu.delete_flag = 0
+            left join life_like_record llr on llr.dianzan_id = #{phoneId} and llr.huifu_id = g.id and llr.type = 6 and llr.delete_flag = 0
+            left join life_collect lc on lc.business_id = g.id and lc.user_id = #{phoneId} and lc.delete_flag = 0 and lc.business_type = 1
+        where g.id = #{goodsId} and g.delete_flag = 0
+    </select>
+
 </mapper>

+ 1 - 1
alien-second/src/main/java/shop/alien/second/controller/SecondGoodsCategoryController.java

@@ -26,7 +26,7 @@ public class SecondGoodsCategoryController {
     @ApiOperation("搜索商品类型")
     @PostMapping("/querySecondGoodsByParentId")
     public R<List<SecondGoodsCategory>> querySecondGoodsByParentId(
-            @RequestParam(value = "parentId", required = false) Integer parentId) {
+            @RequestParam(value = "parentId", required = false) Integer parentId) throws Exception {
         return R.data(service.querySecondGoodsByParentId(parentId), "查询成功");
     }
 

+ 101 - 2
alien-second/src/main/java/shop/alien/second/controller/SecondGoodsController.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.google.common.collect.Lists;
 import io.swagger.annotations.*;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -13,7 +14,9 @@ import shop.alien.entity.second.SecondGoods;
 import shop.alien.entity.second.vo.SecondGoodsVo;
 import shop.alien.second.service.SecondGoodsService;
 import shop.alien.util.common.JwtUtil;
+import shop.alien.util.common.safe.*;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -30,6 +33,12 @@ public class SecondGoodsController {
 
     private final SecondGoodsService secondGoodsService;
 
+    // 注入文本审核工具
+    private final TextModerationUtil textModerationUtil;
+
+    // 注入图片审核工具
+    private final ImageModerationUtil imageModerationUtil;
+
     /**
      * 根据ID获取二手商品
      */
@@ -45,7 +54,7 @@ public class SecondGoodsController {
      */
     @PostMapping("/save")
     @ApiOperation("发布二手商品")
-    public R<Void> addSecondGoods(@ApiParam("二手商品信息") @RequestBody SecondGoodsVo secondGoods) {
+    public R<Void> addSecondGoods(@ApiParam("二手商品信息") @RequestBody SecondGoodsVo secondGoods) throws Exception {
         log.info("SecondGoodsController.addSecondGoods?secondGoods={}", secondGoods.toString());
         JSONObject data = JwtUtil.getCurrentUserInfo();
         if (null != data) {
@@ -71,7 +80,7 @@ public class SecondGoodsController {
      */
     @PostMapping("/edit")
     @ApiOperation("更新二手商品")
-    public R<Void> updateSecondGoods(@ApiParam("二手商品信息") @RequestBody SecondGoodsVo secondGoods) {
+    public R<Void> updateSecondGoods(@ApiParam("二手商品信息") @RequestBody SecondGoodsVo secondGoods) throws Exception {
         log.info("SecondGoodsController.updateSecondGoods?secondGoods={}", secondGoods.toString());
         // 添加商品 0 创建 1 更新
         if (!secondGoodsService.createBasicInfo(secondGoods,1)) {
@@ -119,4 +128,94 @@ public class SecondGoodsController {
         return R.data(secondGoodsService.getOne(queryWrapper).getGoodsStatus());
     }
 
+    /**
+     * 文本审核接口 - 商品发布场景
+     */
+    @GetMapping("/textModeration/productPublish")
+    @ApiOperation("文本审核 - 商品发布场景(大语言模型输入文字检测、广告法合规检测_专业版、URL风险链接检测)")
+    public R<TextModerationResultVO> productPublishTextModeration(@ApiParam("待审核文本") @RequestParam String text) {
+        log.info("SecondGoodsController.productPublishTextModeration?text={}", text);
+        try {
+            List<String> servicesList = Lists.newArrayList();
+            servicesList.add(TextReviewServiceEnum.AD_COMPLIANCE_DETECTION_PRO.getService());
+            servicesList.add(TextReviewServiceEnum.LLM_QUERY_MODERATION.getService());
+            TextModerationResultVO textModerationResultVO = textModerationUtil.invokeFunction(text,servicesList);
+            return R.data(textModerationResultVO);
+        } catch (Exception e) {
+            log.error("文本审核异常", e);
+            return R.fail("文本审核异常: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 文本审核接口 - 聊一聊场景
+     */
+    @GetMapping("/textModeration/chat")
+    @ApiOperation("文本审核 - 聊一聊场景(私聊互动内容检测_专业版、广告法合规检测_专业版、URL风险链接检测)")
+    public R<TextModerationResultVO> chatTextModeration(@ApiParam("待审核文本") @RequestParam String text) {
+        log.info("SecondGoodsController.chatTextModeration?text={}", text);
+        try {
+            List<String> servicesList = Lists.newArrayList();
+            servicesList.add(TextReviewServiceEnum.AD_COMPLIANCE_DETECTION_PRO.getService());
+            servicesList.add(TextReviewServiceEnum.URL_DETECTION.getService());
+            servicesList.add(TextReviewServiceEnum.CHAT_DETECTION_PRO.getService());
+            TextModerationResultVO textModerationResultVO = textModerationUtil.invokeFunction(text,servicesList);
+            return R.data(textModerationResultVO);
+        } catch (Exception e) {
+            log.error("文本审核异常", e);
+            return R.fail("文本审核异常: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 文本审核接口 - 评论场景
+     */
+    @GetMapping("/textModeration/comment")
+    @ApiOperation("文本审核 - 评论场景(公聊评论内容检测_专业版、广告法合规检测_专业版、URL风险链接检测)")
+    public R<TextModerationResultVO> commentTextModeration(@ApiParam("待审核文本") @RequestParam String text) {
+        log.info("SecondGoodsController.commentTextModeration?text={}", text);
+        try {
+            List<String> servicesList = Lists.newArrayList();
+            servicesList.add(TextReviewServiceEnum.AD_COMPLIANCE_DETECTION_PRO.getService());
+            servicesList.add(TextReviewServiceEnum.URL_DETECTION.getService());
+            servicesList.add(TextReviewServiceEnum.CHAT_DETECTION_PRO.getService());
+            TextModerationResultVO textModerationResultVO = textModerationUtil.invokeFunction(text,servicesList);
+            return R.data(textModerationResultVO);
+        } catch (Exception e) {
+            log.error("文本审核异常", e);
+            return R.fail("文本审核异常: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 图片审核接口 - 发布商品场景
+     */
+    @GetMapping("/imageModeration/productPublish")
+    @ApiOperation("图片审核 - 发布商品场景(内容治理检测、AIGC图片风险检测、图片万物识别)")
+    public R<ImageModerationResultVO> productPublishImageModeration(@ApiParam("图片地址") @RequestParam String imageUrl) {
+        log.info("SecondGoodsController.productPublishImageModeration?imageUrl={}", imageUrl);
+        try {
+            ImageModerationResultVO response = imageModerationUtil.productPublishCheck(imageUrl);
+            return R.data(response);
+        } catch (Exception e) {
+            log.error("图片审核异常", e);
+            return R.fail("图片审核异常: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 图片审核接口 - 聊一聊场景
+     */
+    @GetMapping("/imageModeration/chat")
+    @ApiOperation("图片审核 - 聊一聊场景(图片万物识别、内容治理检测)")
+    public R<ImageModerationResultVO> chatImageModeration(@ApiParam("图片地址") @RequestParam String imageUrl) {
+        log.info("SecondGoodsController.chatImageModeration?imageUrl={}", imageUrl);
+        try {
+            ImageModerationResultVO response = imageModerationUtil.chatCheck(imageUrl);
+            return R.data(response, "审核成功");
+        } catch (Exception e) {
+            log.error("图片审核异常", e);
+            return R.fail("图片审核异常: " + e.getMessage());
+        }
+    }
 }

+ 11 - 45
alien-second/src/main/java/shop/alien/second/controller/SecondRecommendController.java

@@ -30,7 +30,8 @@ public class SecondRecommendController {
             @RequestParam(value = "pageSize", required = false) Integer pageSize,
             @RequestParam(value = "typeId", required = false) Integer typeId,
             @RequestParam(value = "longitude", required = false) String longitude,
-            @RequestParam(value = "latitude", required = false) String latitude) {
+            @RequestParam(value = "latitude", required = false) String latitude) throws Exception {
+        log.info("LifeCollectController.cancelCollect?pageNum={},pageSize={},longitude={},latitude={},typeId={}", pageNum, pageSize, longitude, latitude, typeId);
         IPage<SecondGoodsRecommendVo> page = new Page<>(pageNum, pageSize);
         IPage<SecondGoodsRecommendVo> result = service.getSecondRecommendByPage(page, longitude, latitude, typeId);
         return R.data(result, "查询成功");
@@ -42,7 +43,8 @@ public class SecondRecommendController {
             @RequestParam(value = "pageNum", required = false) Integer pageNum,
             @RequestParam(value = "pageSize", required = false) Integer pageSize,
             @RequestParam(value = "longitude", required = false) String longitude,
-            @RequestParam(value = "latitude", required = false) String latitude) {
+            @RequestParam(value = "latitude", required = false) String latitude) throws Exception {
+        log.info("LifeCollectController.cancelCollect?pageNum={},pageSize={},longitude={},latitude={}", pageNum, pageSize, longitude, latitude);
         IPage<SecondGoodsRecommendVo> page = new Page<>(pageNum, pageSize);
         IPage<SecondGoodsRecommendVo> result = service.querySecondConcernByPage(page, longitude + "," + latitude);
         return R.data(result, "查询成功");
@@ -54,7 +56,8 @@ public class SecondRecommendController {
             @RequestParam(value = "pageNum", required = false) Integer pageNum,
             @RequestParam(value = "pageSize", required = false) Integer pageSize,
             @RequestParam(value = "longitude", required = false) String longitude,
-            @RequestParam(value = "latitude", required = false) String latitude) {
+            @RequestParam(value = "latitude", required = false) String latitude) throws Exception {
+        log.info("LifeCollectController.cancelCollect?pageNum={},pageSize={},longitude={},latitude={}", pageNum, pageSize, longitude, latitude);
         IPage<SecondGoodsRecommendVo> page = new Page<>(pageNum, pageSize);
         IPage<SecondGoodsRecommendVo> result = service.querySecondNewGoodsByPage(page, longitude + "," + latitude);
         return R.data(result, "查询成功");
@@ -63,48 +66,11 @@ public class SecondRecommendController {
     @ApiOperation("搜索商品详情")
     @PostMapping("/querySecondGoodsDetail")
     public R<SecondGoodsRecommendVo> querySecondGoodsDetail(
-            @RequestParam(value = "goodsId", required = false) Integer goodsId) {
-        //IPage<SecondGoodsRecommendVo> result = service.querySecondNewGoodsByPage(goodsId);
-        return R.data(null, "查询成功");
-    }
-
-
-
-    private static final double EARTH_RADIUS = 6371; // 地球半径 (千米)
-
-    /**
-     * 计算两个经纬度之间的距离
-     * @param lat1 第一个点的纬度
-     * @param lon1 第一个点的经度
-     * @param lat2 第二个点的纬度
-     * @param lon2 第二个点的经度
-     * @return 距离(千米)
-     */
-    public static double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
-        // 将经纬度从度数转换为弧度
-        double radLat1 = Math.toRadians(lat1);
-        double radLon1 = Math.toRadians(lon1);
-        double radLat2 = Math.toRadians(lat2);
-        double radLon2 = Math.toRadians(lon2);
-
-        // 计算经纬度差值
-        double deltaLat = radLat2 - radLat1;
-        double deltaLon = radLon2 - radLon1;
-
-        // Haversine 公式
-        double a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) +
-                Math.cos(radLat1) * Math.cos(radLat2) *
-                        Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2);
-        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
-
-        // 计算最终距离
-        return EARTH_RADIUS * c;
-    }
-
-    public static void main(String[] args) {
-        // 示例:计算北京 (39.9042° N, 116.4074° E) 到上海 (31.2304° N, 121.4737° E) 的距离
-        double distance = calculateDistance(39.01, 121.49, 41.48, 123.25);
-        System.out.printf("两地距离: %.2f 公里%n", distance);
+            @RequestParam(value = "goodsId", required = false) Integer goodsId,
+            @RequestParam(value = "longitude", required = false) String longitude,
+            @RequestParam(value = "latitude", required = false) String latitude) throws Exception {
+        log.info("LifeCollectController.cancelCollect?goodsId={},longitude={},latitude={}", goodsId, longitude, latitude);
+        return R.data(service.querySecondGoodsDetail(goodsId, longitude + "," + latitude), "查询成功");
     }
 
 }

+ 58 - 0
alien-second/src/main/java/shop/alien/second/controller/SecondShieldController.java

@@ -0,0 +1,58 @@
+package shop.alien.second.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiSort;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.poi.ss.formula.functions.T;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.entity.second.SecondShield;
+import shop.alien.mapper.second.SecondShieldMapper;
+import shop.alien.util.common.JwtUtil;
+
+import java.util.Date;
+
+@Slf4j
+@Api(tags = {"二手平台-拉黑"})
+@ApiSort(9)
+@CrossOrigin
+@RestController
+@RequestMapping("/second/shield")
+@RequiredArgsConstructor
+public class SecondShieldController {
+
+    private final SecondShieldMapper mapper;
+
+    @ApiOperation("商品拉黑")
+    @PostMapping("/saveGoodsShield")
+    public R<T> saveGoodsShield(
+            @RequestParam(value = "shieldId", required = false) Integer shieldId) {
+        JSONObject data = JwtUtil.getCurrentUserInfo();
+        Integer userId = null;
+        if (data != null) {
+            userId = data.getInteger("userId");
+        }
+        if (userId == null) {
+            return null;
+        }
+        SecondShield shield = new SecondShield();
+        shield.setUserId(userId);
+        shield.setShieldId(shieldId);
+        shield.setShieldType(1);
+        shield.setCreatedUserId(userId);
+        shield.setCreatedTime(new Date());
+        shield.setUpdatedUserId(userId);
+        shield.setUpdatedTime(new Date());
+        Integer num = mapper.insert(shield);
+
+        if(num == 1) {
+            return R.success("拉黑成功");
+        }
+        return R.fail("拉黑失败");
+
+    }
+
+}

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

@@ -15,6 +15,6 @@ public interface SecondGoodsCategoryService extends IService<SecondGoodsCategory
      * @param parentId 父ID
      * @return 分页后的屏蔽商品列
      */
-    List<SecondGoodsCategory> querySecondGoodsByParentId(Integer parentId);
+    List<SecondGoodsCategory> querySecondGoodsByParentId(Integer parentId) throws Exception;
 
 }

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

@@ -19,7 +19,7 @@ public interface SecondGoodsService extends IService<SecondGoods> {
      * @param editFlag 编辑标识 0:创建 1:编辑
      * @return 是否成功保存
      */
-    boolean createBasicInfo(SecondGoodsVo goods, Integer editFlag);
+    boolean createBasicInfo(SecondGoodsVo goods, Integer editFlag) throws Exception;
 
     /**
      * 保存为草稿

+ 27 - 4
alien-second/src/main/java/shop/alien/second/service/SecondRecommendService.java

@@ -13,13 +13,36 @@ public interface SecondRecommendService extends IService<SecondGoodsRecommendVo>
     /**
      * 查询推荐信息
      * @param page 分页信息
-     * @return 是否成功保存
+     * @param longitude 经度信息
+     * @param latitude 维度信息
+     * @param typeId 类型ID
+     * @return 推荐商品信息
      */
-    IPage<SecondGoodsRecommendVo> getSecondRecommendByPage(IPage<SecondGoodsRecommendVo> page, String longitude, String latitude, Integer typeId);
+    IPage<SecondGoodsRecommendVo> getSecondRecommendByPage(IPage<SecondGoodsRecommendVo> page, String longitude, String latitude, Integer typeId) throws Exception;
 
-    IPage<SecondGoodsRecommendVo> querySecondConcernByPage(IPage<SecondGoodsRecommendVo> page, String position);
+    /**
+     * 查询关注信息
+     * @param page 分页信息
+     * @param position 经纬度
+     * @return 关注商品信息
+     */
+    IPage<SecondGoodsRecommendVo> querySecondConcernByPage(IPage<SecondGoodsRecommendVo> page, String position) throws Exception;
 
-    IPage<SecondGoodsRecommendVo> querySecondNewGoodsByPage(IPage<SecondGoodsRecommendVo> page, String position);
+    /**
+     * 查询新品信息
+     * @param page 分页信息
+     * @param position 经纬度
+     * @return 新品商品信息
+     */
+    IPage<SecondGoodsRecommendVo> querySecondNewGoodsByPage(IPage<SecondGoodsRecommendVo> page, String position) throws Exception;
+
+    /**
+     * 查询商品详情信息
+     * @param goodsId 商品ID
+     * @param position 经纬度
+     * @return 商品详情信息
+     */
+    SecondGoodsRecommendVo querySecondGoodsDetail(Integer goodsId, String position) throws Exception;
 
 
 }

+ 9 - 2
alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsCategoryServiceImpl.java

@@ -2,6 +2,7 @@ package shop.alien.second.service.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import shop.alien.entity.second.SecondGoodsCategory;
@@ -13,6 +14,7 @@ import java.util.List;
 /**
  * 二手商品服务实现类
  */
+@Slf4j
 @Service
 @RequiredArgsConstructor
 public class SecondGoodsCategoryServiceImpl extends ServiceImpl<SecondGoodsCategoryMapper, SecondGoodsCategory> implements SecondGoodsCategoryService {
@@ -25,7 +27,12 @@ public class SecondGoodsCategoryServiceImpl extends ServiceImpl<SecondGoodsCateg
      * @return 是否成功保存
      */
     @Override
-    public List<SecondGoodsCategory> querySecondGoodsByParentId(Integer parentId) {
-        return mapper.querySecondGoodsByParentId(parentId);
+    public List<SecondGoodsCategory> querySecondGoodsByParentId(Integer parentId) throws Exception {
+        try {
+            return mapper.querySecondGoodsByParentId(parentId);
+        } catch (Exception e) {
+            log.error("SecondGoodsCategoryServiceImpl.querySecondGoodsByParentId Error Mgs={}", e.getMessage());
+            throw new Exception("查询二级商品分类失败", e);
+        }
     }
 }

+ 27 - 13
alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsServiceImpl.java

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.google.common.collect.Lists;
 import lombok.RequiredArgsConstructor;
 import org.apache.ibatis.annotations.Param;
 import org.springframework.beans.BeanUtils;
@@ -22,6 +23,7 @@ import shop.alien.second.service.SecondGoodsService;
 import shop.alien.util.common.VideoUtils;
 import shop.alien.util.common.netease.ImageCheckUtil;
 import shop.alien.util.common.netease.TextCheckUtil;
+import shop.alien.util.common.safe.*;
 
 import java.util.Collections;
 import java.util.Date;
@@ -39,6 +41,16 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
     private final VideoUtils videoUtils;
 
     /**
+     * 文本审核工具
+     */
+    private final TextModerationUtil textModerationUtil;
+
+    /**
+     * 图片审核工具
+     */
+    private final ImageModerationUtil imageModerationUtil;
+
+    /**
      * 二手商品Mapper
      */
     private final SecondGoodsMapper secondGoodsMapper;
@@ -98,7 +110,7 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
 
 
     @Override
-    public boolean createBasicInfo(SecondGoodsVo goodsDTO,Integer editFlag) {
+    public boolean createBasicInfo(SecondGoodsVo goodsDTO,Integer editFlag) throws Exception {
         // 实现基本信息保存逻辑
         SecondGoods goods = new SecondGoods();
         BeanUtils.copyProperties(goodsDTO, goods);
@@ -154,20 +166,23 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
     private boolean checkSafety(SecondGoods goods) {
         return true;
     }
-
     /**
      * 执行内容审核(图片和文本)
      * @param goods 商品信息
      * @param goodsDTO 商品DTO信息
      * @return 审核结果
      */
-    private boolean performContentReviews(SecondGoods goods, SecondGoodsVo goodsDTO) {
-        // 文本审核
-        Map<String, String> textCheckResult = TextCheckUtil.check(goodsDTO.getDescription());
-        if (!"200".equals(textCheckResult.get("code"))) {
-            // 文本审核不通过
+    private boolean performContentReviews(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());
+        // 使用商品发布场景的审核服务
+        TextModerationResultVO textCheckResult = textModerationUtil.invokeFunction(goodsDTO.getDescription(), servicesList);
+        
+        if ("high".equals(textCheckResult.getRiskLevel())) {
+            // 文本审核不通过或存在高风险
             goods.setGoodsStatus(2); // 审核失败
-            goods.setFailedReason("文本审核不通过:" + textCheckResult.get("msg"));
+            goods.setFailedReason("文本审核不通过:" + (textCheckResult.getRiskWords() != null ? textCheckResult.getRiskWords() : "存在高风险内容"));
             return false;
         }
 
@@ -176,12 +191,11 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
         if (imageUrls != null && !imageUrls.isEmpty()) {
             StringBuilder failReasonBuilder = new StringBuilder();
             for (String imageUrl : imageUrls) {
-                Map<String, String> imageCheckResult = ImageCheckUtil.check(imageUrl, 2);
-                if (!"200".equals(imageCheckResult.get("code"))) {
-                    // 任一图片审核不通过则整体不通过
+                ImageModerationResultVO response = imageModerationUtil.productPublishCheck(imageUrl);
+                if ("high".equals(response.getRiskLevel())) {
+                    // 文本审核不通过或存在高风险
                     goods.setGoodsStatus(2); // 审核失败
-                    failReasonBuilder.append("图片审核不通过:").append(imageUrl).append(" 原因:").append(imageCheckResult.get("msg")).append("; ");
-                    goods.setFailedReason(failReasonBuilder.toString());
+                    goods.setFailedReason("图片审核不通过:图片中包含" + (response.getDescriptions() != null ? response.getDescriptions() : "高风险内容"));
                     return false;
                 }
             }

+ 154 - 112
alien-second/src/main/java/shop/alien/second/service/impl/SecondRecommendServiceImpl.java

@@ -2,28 +2,43 @@ package shop.alien.second.service.impl;
 
 import cn.hutool.core.collection.CollectionUtil;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.poi.util.StringUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import shop.alien.entity.second.vo.SecondCommentVo;
 import shop.alien.entity.second.vo.SecondGoodsRecommendVo;
+import shop.alien.entity.store.LifeFans;
 import shop.alien.entity.store.StoreComment;
+import shop.alien.entity.store.StoreImg;
+import shop.alien.mapper.LifeFansMapper;
+import shop.alien.mapper.StoreImgMapper;
 import shop.alien.mapper.second.SecondRecommendMapper;
 import shop.alien.second.service.SecondRecommendService;
 import shop.alien.util.common.JwtUtil;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.stream.Collectors;
 
 /**
  * 二手商品服务实现类
  */
+@Slf4j
 @Service
 public class SecondRecommendServiceImpl extends ServiceImpl<SecondRecommendMapper, SecondGoodsRecommendVo> implements SecondRecommendService {
 
     @Autowired
     private SecondRecommendMapper mapper;
+
+    @Autowired
+    private StoreImgMapper storeImgMapper;
+
+    @Autowired
+    private LifeFansMapper lifeFansMapper;
     /**
      * 获取二手商品推荐列表
      * @param page 分页信息
@@ -31,26 +46,28 @@ public class SecondRecommendServiceImpl extends ServiceImpl<SecondRecommendMappe
      */
     @Override
     public IPage<SecondGoodsRecommendVo> getSecondRecommendByPage(
-            IPage<SecondGoodsRecommendVo> page, String longitude, String latitude, Integer typeId) {
-        JSONObject data = JwtUtil.getCurrentUserInfo();
-        Integer userId = null;
-        if (data != null) {
-            userId = data.getInteger("userId");
-        }
-        if (userId == null) {
-            return null;
-        }
-        IPage<SecondGoodsRecommendVo> result = mapper.getSecondRecommendByPage(page, userId, longitude + "," + latitude, typeId);
-        for (SecondGoodsRecommendVo row : result.getRecords()){
-            if (StringUtil.isNotBlank(row.getDist())) {
-                row.setPosition("距离" + row.getDist() + "km");
+            IPage<SecondGoodsRecommendVo> page, String longitude, String latitude, Integer typeId) throws Exception {
+        try{
+            JSONObject data = JwtUtil.getCurrentUserInfo();
+            Integer userId = null;
+            if (data != null) {
+                userId = data.getInteger("userId");
+                log.info("获取用户ID:userId={}", userId);
             }
-            if (StringUtil.isNotBlank(row.getTopic())) {
-                List<String> topicList = Arrays.asList(row.getTopic().split(","));
-                row.setTopicList(topicList);
+            if (userId == null) {
+                return null;
             }
+            IPage<SecondGoodsRecommendVo> result = mapper.getSecondRecommendByPage(page, userId, longitude + "," + latitude, typeId);
+            for (SecondGoodsRecommendVo row : result.getRecords()) {
+                if (StringUtil.isNotBlank(row.getDist())) {
+                    row.setPosition("距离" + row.getDist() + "km");
+                }
+            }
+            return result;
+        } catch (Exception e) {
+            log.error("SecondRecommendServiceImpl.getSecondRecommendByPage Error Mgs={}", e.getMessage());
+            throw new Exception(e);
         }
-        return result;
     }
 
     /**
@@ -59,45 +76,46 @@ public class SecondRecommendServiceImpl extends ServiceImpl<SecondRecommendMappe
      * @return 关注列表
      */
     public IPage<SecondGoodsRecommendVo> querySecondConcernByPage(
-            IPage<SecondGoodsRecommendVo> page, String position) {
-        JSONObject data = JwtUtil.getCurrentUserInfo();
-        String phoneId = null;
-        if (data != null) {
-            phoneId = data.getString("phone");
-        }
-        if (StringUtil.isBlank(phoneId)) {
-            return null;
-        }
-        IPage<SecondGoodsRecommendVo> list = mapper.querySecondConcernByPage(page, "user_" + phoneId, position);
-        List<Integer> idList = list.getRecords().stream() // 创建流
-                .map(obj -> obj.getId())   // 提取每个元素的 ID
-                .collect(Collectors.toList());
-        if (CollectionUtil.isEmpty(idList)) {
-            return list;
-        }
-        List<StoreComment> commentList =mapper.querySecondCommentInfo(idList);
-        list.getRecords().forEach(item -> {
-            // 距离拼接
-            if (StringUtil.isNotBlank(item.getDist())) {
-                item.setPosition("距离" + item.getDist() + "km");
+            IPage<SecondGoodsRecommendVo> page, String position) throws Exception {
+        try {
+            JSONObject data = JwtUtil.getCurrentUserInfo();
+            String phoneId = null;
+            if (data != null) {
+                phoneId = data.getString("phone");
             }
-            // 话题列表
-            if (StringUtil.isNotBlank(item.getTopic())) {
-                List<String> topicList = Arrays.asList(item.getTopic().split(","));
-                item.setTopicList(topicList);
+            if (StringUtil.isBlank(phoneId)) {
+                return null;
             }
-            // 评论列表
-            List<StoreComment> cList = new ArrayList<>();
-            commentList.forEach(comment -> {
-                if (item.getId() == comment.getBusinessId()) {
-                    cList.add(comment);
+            IPage<SecondGoodsRecommendVo> list = mapper.querySecondConcernByPage(page, "user_" + phoneId, position);
+            List<Integer> idList = list.getRecords().stream() // 创建流
+                    .map(obj -> obj.getId())   // 提取每个元素的 ID
+                    .collect(Collectors.toList());
+            if (CollectionUtil.isEmpty(idList)) {
+                return list;
+            }
+            List<SecondCommentVo> commentList =mapper.querySecondCommentInfo(idList);
+            list.getRecords().forEach(item -> {
+                // 距离拼接
+                if (StringUtil.isNotBlank(item.getDist())) {
+                    item.setPosition("距离" + item.getDist() + "km");
+                }
+
+                // 评论列表
+                List<SecondCommentVo> cList = new ArrayList<>();
+                commentList.forEach(comment -> {
+                    if (item.getId() == comment.getBusinessId()) {
+                        cList.add(comment);
+                    }
+                });
+                if (cList.size() > 0) {
+                    item.setCommentList(cList);
                 }
             });
-            if (cList.size() > 0) {
-                item.setCommentList(cList);
-            }
-        });
-        return list;
+            return list;
+        } catch (Exception e){
+            log.error("SecondRecommendServiceImpl.querySecondConcernByPage Error Mgs={}", e.getMessage());
+            throw new Exception(e);
+        }
     }
 
 
@@ -107,70 +125,94 @@ public class SecondRecommendServiceImpl extends ServiceImpl<SecondRecommendMappe
      * @return 关注列表
      */
     public IPage<SecondGoodsRecommendVo> querySecondNewGoodsByPage(
-            IPage<SecondGoodsRecommendVo> page, String position) {
-        JSONObject data = JwtUtil.getCurrentUserInfo();
-        String phoneId = null;
-        String userId = null;
-        if (data != null) {
-            phoneId = data.getString("phone");
-            userId = data.getString("userId");
-        }
-        if (StringUtil.isBlank(phoneId)) {
-            return null;
-        }
-        IPage<SecondGoodsRecommendVo> list = mapper.querySecondNewGoodsByPage(page, userId,"user_" + phoneId, position);
-        List<Integer> idList = list.getRecords().stream() // 创建流
-                .map(obj -> obj.getId())   // 提取每个元素的 ID
-                .collect(Collectors.toList());
-        if (CollectionUtil.isEmpty(idList)) {
-            return list;
-        }
-        List<StoreComment> commentList =mapper.querySecondCommentInfo(idList);
-        list.getRecords().forEach(item -> {
-            // 距离拼接
-            if (StringUtil.isNotBlank(item.getDist())) {
-                item.setPosition("距离" + item.getDist() + "km");
+            IPage<SecondGoodsRecommendVo> page, String position) throws Exception {
+        try {
+            JSONObject data = JwtUtil.getCurrentUserInfo();
+            String phoneId = null;
+            String userId = null;
+            if (data != null) {
+                phoneId = data.getString("phone");
+                userId = data.getString("userId");
+            }
+            if (StringUtil.isBlank(phoneId)) {
+                return null;
             }
-            // 话题列表
-            if (StringUtil.isNotBlank(item.getTopic())) {
-                List<String> topicList = Arrays.asList(item.getTopic().split(","));
-                item.setTopicList(topicList);
+            IPage<SecondGoodsRecommendVo> list = mapper.querySecondNewGoodsByPage(page, userId,"user_" + phoneId, position);
+            List<Integer> idList = list.getRecords().stream() // 创建流
+                    .map(obj -> obj.getId())   // 提取每个元素的 ID
+                    .collect(Collectors.toList());
+            if (CollectionUtil.isEmpty(idList)) {
+                return list;
             }
-            // 评论列表
-            List<StoreComment> cList = new ArrayList<>();
-            commentList.forEach(comment -> {
-                if (item.getId() == comment.getBusinessId()) {
-                    cList.add(comment);
+            List<SecondCommentVo> commentList = mapper.querySecondCommentInfo(idList);
+            list.getRecords().forEach(item -> {
+                // 距离拼接
+                if (StringUtil.isNotBlank(item.getDist())) {
+                    item.setPosition("距离" + item.getDist() + "km");
+                }
+
+                // 评论列表
+                List<SecondCommentVo> cList = new ArrayList<>();
+                commentList.forEach(comment -> {
+                    if (item.getId() == comment.getBusinessId()) {
+                        cList.add(comment);
+                    }
+                });
+                if (cList.size() > 0) {
+                    item.setCommentList(cList);
                 }
             });
-            if (cList.size() > 0) {
-                item.setCommentList(cList);
-            }
-        });
-        return list;
+            return list;
+        } catch (Exception e) {
+            log.error("SecondRecommendServiceImpl.querySecondNewGoodsByPage Error Mgs={}", e.getMessage());
+            throw new Exception(e);
+        }
     }
-    public static void main(String[] args) {
-        List<Map<String, Object>> list = new ArrayList<>();
-        Map<String, Object> map = new HashMap<>();
-        map.put("id", 1);
-        map.put("name", "张三");
-        list.add(map);
-        Map<String, Object> map1 = new HashMap<>();
-        map1.put("id", 2);
-        map1.put("name", "张三");
-        list.add(map1);
-        Map<String, Object> map2 = new HashMap<>();
-        map2.put("id", 3);
-        map2.put("name", "张三");
-        list.add(map2);
-        Map<String, Object> map3 = new HashMap<>();
-        map3.put("id", 4);
-        map3.put("name", "张三");
-        list.add(map3);
-        List<String> idList = list.stream() // 创建流
-                .map(obj -> obj.get("id").toString())   // 提取每个元素的 ID
-                .collect(Collectors.toList());
 
-        System.out.println(idList);
+    public SecondGoodsRecommendVo querySecondGoodsDetail(Integer goodsId, String position) throws Exception {
+        try {
+            JSONObject data = JwtUtil.getCurrentUserInfo();
+            String phoneId = null;
+            if (data != null) {
+                phoneId = data.getString("phone");
+            }
+            if (StringUtil.isBlank(phoneId)) {
+                return null;
+            }
+            SecondGoodsRecommendVo item = mapper.querySecondGoodsDetail(goodsId, "user_" + phoneId, position);
+
+            // 设置图片信息
+            QueryWrapper<StoreImg> query = new QueryWrapper<>();
+            query.lambda()
+                    .eq(StoreImg::getImgType, 18) // 商品 图片
+                    .eq(StoreImg::getDeleteFlag, 0)
+                    .eq(StoreImg::getStoreId, goodsId);
+            List<StoreImg> storeImgs = storeImgMapper.selectList(query);
+            // 设置图片信息
+            if (storeImgs.size() > 0) {
+                item.setImgList(storeImgs.stream().map(StoreImg::getImgUrl).toArray(String[]::new));
+            }
+
+            // 查看是否关注
+            QueryWrapper<LifeFans> query1 = new QueryWrapper<>();
+            query1.lambda()
+                    .eq(LifeFans::getFollowedId, item.getUserPhone()) // 商品 图片
+                    .eq(LifeFans::getDeleteFlag, 0)
+                    .eq(LifeFans::getFansId, "user_" + phoneId);
+            List<LifeFans> lifeFans = lifeFansMapper.selectList(query1);
+            // 关注状态添加
+            if (lifeFans.size() > 0) {
+                item.setFansStatus(1);
+            }
+
+            // 距离拼接
+            if (StringUtil.isNotBlank(item.getDist())) {
+                item.setPosition("距离" + item.getDist() + "km");
+            }
+            return item;
+        } catch (Exception e) {
+            log.error("SecondRecommendServiceImpl.querySecondGoodsDetail Error Mgs={}", e.getMessage());
+            throw new Exception(e);
+        }
     }
 }

+ 1 - 1
alien-store/src/main/java/shop/alien/store/config/WebSocketProcess.java

@@ -66,7 +66,7 @@ public class WebSocketProcess {
      * 接收到客户端消息时触发
      */
     @OnMessage
-    public R<String> onMessage(String message, @PathParam("sendId") String sendId) throws Exception {
+    public R<String> onMessage(String message) throws Exception {
         try {
             WebsocketVo websocketVo = JSONObject.parseObject(message, WebsocketVo.class);
             JSONObject jsonObject = new JSONObject();

+ 7 - 5
alien-store/src/main/java/shop/alien/store/controller/LifeCollectController.java

@@ -209,7 +209,7 @@ public class LifeCollectController {
         lifeCollect.setCreatedTime(new Date());
         int num = lifeCollectMapper.insert(lifeCollect);
         // 二手商品收藏数量+1
-        if (StringUtil.isBlank(lifeCollect.getBusinessType()) && lifeCollect.getBusinessType().equals(1)) {
+        if (StringUtil.isNotBlank(lifeCollect.getBusinessType()) && lifeCollect.getBusinessType().equals("1")) {
             LambdaUpdateWrapper<SecondGoods> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
             lambdaUpdateWrapper.eq(SecondGoods::getId, lifeCollect.getBusinessId());
             lambdaUpdateWrapper.setSql("collect_count = collect_count + 1");
@@ -224,7 +224,9 @@ public class LifeCollectController {
     @ApiOperation("取消收藏")
     @ApiOperationSupport(order = 3)
     @ApiImplicitParams({@ApiImplicitParam(name = "userId", value = "用户id", dataType = "String", paramType = "query"),
-            @ApiImplicitParam(name = "storeId", value = "storeId", dataType = "String", paramType = "query")})
+            @ApiImplicitParam(name = "storeId", value = "店铺id", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "businessId", value = "业务id", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "businessType", value = "业务类型", dataType = "String", paramType = "query")})
     @PostMapping("cancelCollect")
     public R<Boolean> cancelCollect(
             @RequestParam(value = "userId", required = false) String userId,
@@ -232,7 +234,7 @@ public class LifeCollectController {
             @RequestParam(value = "businessId", required = false) String businessId,
             @RequestParam(value = "businessType", required = false) String businessType,
             @RequestParam(value = "couponId", required = false) String couponId) {
-        log.info("LifeCollectController.cancelCollect?userId={},storeId={}", userId, storeId);
+        log.info("LifeCollectController.cancelCollect?userId={},storeId={},businessId={},businessType={}", userId, storeId, businessId, businessType);
         LambdaUpdateWrapper<LifeCollect> wrapper = new LambdaUpdateWrapper<>();
         wrapper.eq(LifeCollect::getUserId, userId);
         if(!StringUtils.isEmpty(storeId)) {
@@ -240,7 +242,7 @@ public class LifeCollectController {
         } else if (!StringUtils.isEmpty(couponId)){
             wrapper.eq(LifeCollect::getCouponId, couponId);
         }
-        if (StringUtil.isBlank(businessType) && businessType.equals(1)) {
+        if (StringUtil.isNotBlank(businessType) && businessType.equals("1")) {
             wrapper.eq(LifeCollect::getBusinessId, businessId);
             wrapper.eq(LifeCollect::getBusinessType, businessType);
         } else {
@@ -249,7 +251,7 @@ public class LifeCollectController {
         wrapper.set(LifeCollect::getDeleteFlag, 1);
         int num = lifeCollectMapper.update(null, wrapper);
         // 二手交易收藏数量-1
-        if (StringUtil.isBlank(businessType) && businessType.equals(1)) {
+        if (StringUtil.isNotBlank(businessType) && businessType.equals("1")) {
             // 创建LambdaUpdateWrapper实例用于构建更新条件
             LambdaUpdateWrapper<SecondGoods> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
             // 设置更新条件:根据商品ID匹配且收藏数大于0

+ 19 - 4
alien-store/src/main/java/shop/alien/store/controller/LifeCouponController.java

@@ -1,15 +1,13 @@
 package shop.alien.store.controller;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiImplicitParam;
-import io.swagger.annotations.ApiImplicitParams;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.*;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.*;
 import shop.alien.entity.result.R;
 import shop.alien.entity.store.LifeCoupon;
+import shop.alien.entity.store.vo.LifeCouponStatusVo;
 import shop.alien.store.service.LifeCouponService;
 
 import java.util.Map;
@@ -80,4 +78,21 @@ public class LifeCouponController {
         return R.data(lifeCouponService.couponVerify(storeId, quanCode));
     }
 
+    @ApiOperation("获取优惠券状态")
+    @ApiOperationSupport(order = 1)
+    @GetMapping("/getCouponStatus")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "couponId", value = "优惠券id", dataType = "String", paramType = "query", required = true),
+    })
+    public R<LifeCouponStatusVo> getCouponStatus(@RequestParam(value = "couponId") String couponId) {
+        log.info("LifeDiscountCouponController.getCouponStatus?couponId={}", couponId);
+        try {
+            LifeCouponStatusVo lifeCouponStatusVo = lifeCouponService.getCouponStatus(couponId);
+            return R.data(lifeCouponStatusVo);
+        } catch (Exception e) {
+            log.error("LifeDiscountCouponController.getCouponStatus ERROR Msg={}", e.getMessage());
+            return R.fail("查询失败");
+        }
+    }
+
 }

+ 18 - 0
alien-store/src/main/java/shop/alien/store/controller/LifeDiscountCouponController.java

@@ -9,6 +9,7 @@ import shop.alien.entity.result.R;
 import shop.alien.entity.store.UserLoginInfo;
 import shop.alien.entity.store.dto.LifeDiscountCouponDto;
 import shop.alien.entity.store.dto.LifeDiscountCouponUserDto;
+import shop.alien.entity.store.vo.LifeCouponStatusVo;
 import shop.alien.entity.store.vo.LifeDiscountCouponVo;
 import shop.alien.store.service.LifeDiscountCouponService;
 import shop.alien.store.service.LifeDiscountCouponUserService;
@@ -262,4 +263,21 @@ public class LifeDiscountCouponController {
         }
     }
 
+    @ApiOperation("获取优惠券状态")
+    @ApiOperationSupport(order = 1)
+    @GetMapping("/getCouponStatus")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "couponId", value = "优惠券id", dataType = "String", paramType = "query", required = true),
+    })
+    public R<LifeCouponStatusVo> getCouponStatus(@RequestParam(value = "couponId") String couponId) {
+        log.info("LifeDiscountCouponController.getCouponStatus?couponId={}", couponId);
+        try {
+            LifeCouponStatusVo lifeCouponStatusVo = lifeDiscountCouponService.getCouponStatus(couponId);
+            return R.data(lifeCouponStatusVo);
+        } catch (Exception e) {
+            log.error("LifeDiscountCouponController.getCouponStatus ERROR Msg={}", e.getMessage());
+            return R.fail("查询失败");
+        }
+    }
+
 }

+ 47 - 39
alien-store/src/main/java/shop/alien/store/controller/LifeMessageController.java

@@ -3,6 +3,7 @@ package shop.alien.store.controller;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import io.swagger.annotations.*;
+import io.swagger.models.auth.In;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.messaging.handler.annotation.MessageMapping;
@@ -19,7 +20,7 @@ import java.util.List;
 /**
  * 消息
  */
-@Api(tags = {"期-消息"})
+@Api(tags = {"期-消息"})
 @Slf4j
 @RestController
 @CrossOrigin
@@ -27,8 +28,6 @@ import java.util.List;
 @RequiredArgsConstructor
 public class LifeMessageController {
 
-    private final LifeMessageMapper messageMapper;
-
     private final LifeMessageService lifeMessageService;
 
     @ApiOperation("消息列表")
@@ -40,34 +39,34 @@ public class LifeMessageController {
     @GetMapping("/getMessageList")
     public R<List<LifeMessageVo>> getMessageList(@RequestParam String receiverId,
                                                   @RequestParam int friendType,
-                                                  @RequestParam String search) {
+                                                  @RequestParam String search) throws Exception {
         log.info("LifeMessageController.getMessageList?receiverId={}, friendType={}, search={}", receiverId, friendType, search);
         return R.data(lifeMessageService.getMessageList(receiverId, friendType, search));
     }
 
-    @ApiOperation("未聊过的消息数据")
+    @ApiOperation("未读消息与通知数量")
     @ApiOperationSupport(order = 2)
     @ApiImplicitParams({@ApiImplicitParam(name = "receiverId", value = "当前登录人", dataType = "String", paramType = "query")})
-    @GetMapping("/getStrangerMessageNum")
-    public R<LifeMessageVo> getStrangerMessageNum(@RequestParam String receiverId) {
-        log.info("LifeMessageController.getStrangerMessageNum?receiverId={}", receiverId);
-        return R.data(lifeMessageService.getStrangerMessageNum(receiverId));
+    @GetMapping("/getAllNoReadCount")
+    public R<Integer> getAllNoReadCount(@RequestParam String receiverId) throws Exception {
+        log.info("LifeMessageController.getAllNoReadCount?receiverId={}", receiverId);
+        return R.data(lifeMessageService.getAllNoReadCount(receiverId));
     }
 
-    @ApiOperation("未关注人的消息数据")
+    @ApiOperation("未聊过的消息数据")
     @ApiOperationSupport(order = 3)
     @ApiImplicitParams({@ApiImplicitParam(name = "receiverId", value = "当前登录人", dataType = "String", paramType = "query")})
-    @GetMapping("/getNoFriendMessage")
-    public R<LifeMessageVo> getNoFriendMessage(@RequestParam String receiverId) {
-        log.info("LifeMessageController.getNoFriendMessageNum?receiverId={}", receiverId);
-        return R.data(lifeMessageService.getNoFriendMessageNum(receiverId));
+    @GetMapping("/getStrangerMessageNum")
+    public R<LifeMessageVo> getStrangerMessageNum(@RequestParam String receiverId) throws Exception {
+        log.info("LifeMessageController.getStrangerMessageNum?receiverId={}", receiverId);
+        return R.data(lifeMessageService.getStrangerMessageNum(receiverId));
     }
 
     @ApiOperation("消息详情")
     @ApiOperationSupport(order = 4)
     @ApiImplicitParams({@ApiImplicitParam(name = "当前登录人", value = "receiverId", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "senderId", value = "聊天对方", dataType = "String", paramType = "query")})
     @GetMapping("/getMessageListByReceiverId")
-    public R<List<LifeMessageVo>> getMessageListByReceiverId(@RequestParam String receiverId, @RequestParam String senderId) {
+    public R<List<LifeMessageVo>> getMessageListByReceiverId(@RequestParam String receiverId, @RequestParam String senderId) throws Exception {
         log.info("LifeMessageController.getMessageListByReceiverId?receiverId={}, senderId={}", receiverId, senderId);
         return R.data(lifeMessageService.getMessageListByReceiverId(receiverId, senderId));
     }
@@ -76,43 +75,52 @@ public class LifeMessageController {
     @ApiOperationSupport(order = 5)
     @ApiImplicitParams({@ApiImplicitParam(name = "receiverId", value = "当前登录人", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "senderId", value = "聊天对方", dataType = "String", paramType = "query")})
     @GetMapping("/read")
-    public R<Boolean> read(@RequestParam String receiverId, @RequestParam String senderId) {
+    public R<Boolean> read(@RequestParam String receiverId, @RequestParam String senderId) throws Exception {
         log.info("LifeMessageController.read?receiverId={}, senderId={}", receiverId, senderId);
         lifeMessageService.read(receiverId, senderId);
         return R.success("操作成功");
     }
 
-    @ApiOperation("未读消息数量")
-    @ApiOperationSupport(order = 6)
-    @ApiImplicitParams({@ApiImplicitParam(name = "receiverId", value = "当前登录人", dataType = "String", paramType = "query")})
-    @GetMapping("/noReadCount")
-    public R<Integer> noReadCount(@RequestParam String receiverId) {
-        log.info("LifeMessageController.noReadCount?receiverId={}", receiverId);
-        return R.data(lifeMessageService.noReadCount(receiverId));
-    }
-
     @ApiOperation("删除消息")
-    @ApiOperationSupport(order = 7)
+    @ApiOperationSupport(order = 6)
     @ApiImplicitParams({@ApiImplicitParam(name = "senderId", value = "聊天对方", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "receiverId", value = "当前登录人", dataType = "String", paramType = "query")})
     @GetMapping("/deleteMessageByPhoneId")
-    public R<Integer> deleteMessageByPhoneId(@RequestParam String senderId, @RequestParam String receiverId) {
+    public R<Integer> deleteMessageByPhoneId(@RequestParam String senderId, @RequestParam String receiverId) throws Exception {
         log.info("LifeMessageController.deleteMessageByPhoneId?senderId={},receiverId={}", senderId, receiverId);
         return R.data(lifeMessageService.deleteMessageByPhoneId(senderId, receiverId));
     }
 
-    @MessageMapping("/send")
-    @SendTo("/topic/messages")
-    public LifeMessage sendMessage(LifeMessage message) {
-        log.info("LifeMessageController.sendMessage?message={}", message.toString());
-        messageMapper.insert(message);
-        return message;
+    @ApiOperation("未关注人的消息数据")
+    @ApiOperationSupport(order = 7)
+    @ApiImplicitParams({@ApiImplicitParam(name = "receiverId", value = "当前登录人", dataType = "String", paramType = "query")})
+    @GetMapping("/getNoFriendMessage")
+    public R<LifeMessageVo> getNoFriendMessage(@RequestParam String receiverId) throws Exception {
+        log.info("LifeMessageController.getNoFriendMessageNum?receiverId={}", receiverId);
+        return R.data(lifeMessageService.getNoFriendMessageNum(receiverId));
     }
 
-    @GetMapping("/messages")
-    public List<LifeMessage> getMessages(@RequestParam String receiverId) {
-        log.info("LifeMessageController.getMessages?receiverId={}", receiverId);
-        LambdaUpdateWrapper<LifeMessage> wrapper = new LambdaUpdateWrapper<>();
-        wrapper.eq(LifeMessage::getReceiverId, receiverId);
-        return messageMapper.selectList(wrapper);
+    @ApiOperation("未读消息数量")
+    @ApiOperationSupport(order = 8)
+    @ApiImplicitParams({@ApiImplicitParam(name = "receiverId", value = "当前登录人", dataType = "String", paramType = "query")})
+    @GetMapping("/noReadCount")
+    public R<Integer> noReadCount(@RequestParam String receiverId) throws Exception {
+        log.info("LifeMessageController.noReadCount?receiverId={}", receiverId);
+        return R.data(lifeMessageService.noReadCount(receiverId));
     }
+
+//    @MessageMapping("/send")
+//    @SendTo("/topic/messages")
+//    public LifeMessage sendMessage(LifeMessage message) {
+//        log.info("LifeMessageController.sendMessage?message={}", message.toString());
+//        messageMapper.insert(message);
+//        return message;
+//    }
+//
+//    @GetMapping("/messages")
+//    public List<LifeMessage> getMessages(@RequestParam String receiverId) {
+//        log.info("LifeMessageController.getMessages?receiverId={}", receiverId);
+//        LambdaUpdateWrapper<LifeMessage> wrapper = new LambdaUpdateWrapper<>();
+//        wrapper.eq(LifeMessage::getReceiverId, receiverId);
+//        return messageMapper.selectList(wrapper);
+//    }
 }

+ 43 - 0
alien-store/src/main/java/shop/alien/store/controller/LifeMessageNotDisturbController.java

@@ -0,0 +1,43 @@
+package shop.alien.store.controller;
+
+import io.swagger.annotations.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.store.service.LifeMessageNotDisturbService;
+
+/**
+ * <p>
+ * 消息免打扰 前端控制器
+ * </p>
+ *
+ * @author ssk
+ * @since 2025-07-11
+ */
+@Api(tags = {"三期-消息免打扰"})
+@Slf4j
+@CrossOrigin
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/lifeMessageNotDisturb")
+public class LifeMessageNotDisturbController {
+
+    private final LifeMessageNotDisturbService lifeMessageNotDisturbService;
+
+    @ApiOperation("免打扰")
+    @ApiOperationSupport(order = 1)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "receiverId", value = "当前登录人phoneId", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "disturbId", value = "秒打扰人phoneId", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "type", value = "1-免打扰  2-取消免打扰", dataType = "Integer", paramType = "query")})
+    @GetMapping("/notDisturb")
+    public R<Boolean> notDisturb(@RequestParam String receiverId,
+                                 @RequestParam String disturbId,
+                                 @RequestParam int type) {
+        log.info("LifeMessageNotDisturbController.notDisturb?receiverId={}, disturbId={}, type={}", receiverId, disturbId, type);
+        if (lifeMessageNotDisturbService.notDisturb(receiverId, disturbId, type)) return R.success("操作成功");
+        return R.fail("操作失败");
+    }
+
+}

+ 1 - 1
alien-store/src/main/java/shop/alien/store/controller/StoreCommentController.java

@@ -104,7 +104,7 @@ public class StoreCommentController {
             @ApiImplicitParam(name = "id", value = "主键", dataType = "Integer", paramType = "query"),
             @ApiImplicitParam(name = "businessId", value = "业务id", dataType = "Integer", paramType = "query"),
             @ApiImplicitParam(name = "businessType", value = "业务类型(1:订单评论, 2:动态社区评论, 3:活动评论, 4:店铺打卡评论, 5:订单评价)", dataType = "Integer", paramType = "query"),
-            @ApiImplicitParam(name = "storeId", value = "门店id", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "storeId", value = "门店id", dataType = "Integer", paramType = "query"),
             @ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer", paramType = "query", required = true),
             @ApiImplicitParam(name = "replyId", value = "回复id", dataType = "Integer", paramType = "query"),
             @ApiImplicitParam(name = "commentContent", value = "评论内容", dataType = "String", paramType = "query"),

+ 7 - 2
alien-store/src/main/java/shop/alien/store/controller/StoreInfoController.java

@@ -117,12 +117,17 @@ public class StoreInfoController {
     @PostMapping("/deleteStoreInfo")
     public R deleteStoreInfo(@RequestBody StoreInfoDto storeInfoDto) {
         log.info("StoreInfoController.deleteStoreInfo?storeInfoDto={}", storeInfoDto);
+        String s;
         try {
-            storeInfoService.deleteStoreInfo(storeInfoDto);
+            s = storeInfoService.deleteStoreInfo(storeInfoDto);
         } catch (Exception e) {
             return R.fail("失败");
         }
-        return R.success("成功");
+        if ("成功".equals(s)) {
+            return R.success(s);
+        }else {
+            return R.fail(s);
+        }
     }
 
     @ApiOperation("web端重置商户及管理账户密码")

+ 40 - 26
alien-store/src/main/java/shop/alien/store/controller/StoreUserController.java

@@ -17,6 +17,7 @@ import shop.alien.store.service.StoreInfoService;
 import shop.alien.store.service.StoreUserService;
 
 import java.io.IOException;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 
@@ -90,40 +91,33 @@ public class StoreUserController {
                 : R.fail("密码错误");
     }
 
-    @ApiOperation("修改密码")
+    @ApiOperation("修改密码/忘记密码/更换绑定手机号")
     @ApiOperationSupport(order = 2)
     @ApiImplicitParams({@ApiImplicitParam(name = "phone", value = "手机号", dataType = "String", paramType = "query", required = true),
+            @ApiImplicitParam(name = "newPhone", value = "新手机号", dataType = "String", paramType = "query"),
             @ApiImplicitParam(name = "oldPassword", value = "旧密码", dataType = "String", paramType = "query"),
             @ApiImplicitParam(name = "newPassword", value = "新密码", dataType = "String", paramType = "query", required = true),
-            @ApiImplicitParam(name = "type", value = "类型:0:忘记密码,其他:修改密码", dataType = "Integer", paramType = "query", required = true)})
+            @ApiImplicitParam(name = "confirmNewPassword", value = "新密码确认", dataType = "String", paramType = "query", required = true),
+            @ApiImplicitParam(name = "verificationCode", value = "验证码", dataType = "String", paramType = "query", required = true),
+            @ApiImplicitParam(name = "type", value = "类型:0:忘记密码,1:修改密码,2:更换绑定手机号", dataType = "Integer", paramType = "query", required = true)})
     @GetMapping("/updatePassword")
-    public R<Boolean> updatePassword(String phone, String oldPassword, String newPassword, Integer type) {
-        log.info("StoreUserController.updatePassword?phone={}&oldPassword={}&newPassword={}&type={}", phone, oldPassword, newPassword, type);
-        StoreUser storeUser = storeUserService.getUserByPhone(phone);
-        if (null != storeUser) {
-            if (0 == type || oldPassword.equals(storeUser.getPassword())) {
-                if (newPassword.equals(storeUser.getPassword())) {
-                    return R.fail("新密码与原密码相同");
-                }
-                if (storeUserService.updatePassword(storeUser.getId(), newPassword)) {
-                    return R.success("修改成功");
-                }
-                return R.fail("修改失败");
-            }
-            return R.fail("旧密码错误");
+    public R<Boolean> updatePassword(String phone,String newPhone, String oldPassword, String newPassword,String confirmNewPassword,String verificationCode,Integer type) {
+        log.info("StoreUserController.updatePassword?phone={}&newPhone&oldPassword={}&newPassword={}&confirmNewPassword={}&verificationCode={}&type={}", phone, newPhone, oldPassword, newPassword, confirmNewPassword, verificationCode, type);
+        boolean flag = false;
+        flag = storeUserService.forgetOrModifyPassword(phone, newPhone, oldPassword, newPassword, confirmNewPassword, verificationCode, type);
+        if(flag){
+            return R.success("密码修改成功");
+        }else {
+            return R.success("密码修改失败");
         }
-        return R.fail("手机号不存在");
     }
 
     @ApiOperation("修改用户信息")
     @ApiOperationSupport(order = 3)
-    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "主键", dataType = "String", paramType = "query", required = true),
-            @ApiImplicitParam(name = "name", value = "姓名", dataType = "String", paramType = "query", required = true),
-            @ApiImplicitParam(name = "idCard", value = "身份证", dataType = "String", paramType = "query", required = true)})
-    @GetMapping("/setUserInfo")
-    public R<Boolean> setUserInfo(Integer id, String name, String idCard) {
-        log.info("StoreUserController.setUserInfo?id={}&name={}&idCard={}", id, name, idCard);
-        if (storeUserService.setUserInfo(id, name, idCard)) {
+    @PostMapping("/setUserInfo")
+    public R<Boolean> setUserInfo(@RequestBody StoreUser storeUserVo) {
+        log.info("StoreUserController.setUserInfo?storeUserVo={}", storeUserVo);
+        if (storeUserService.setUserInfo(storeUserVo)) {
             return R.success("修改成功");
         }
         return R.fail("修改失败");
@@ -281,8 +275,7 @@ public class StoreUserController {
     @DeleteMapping("/deleteStoreUser")
     public R<StoreUserVo> deleteStoreUser(@RequestParam(value = "id") String id) {
         log.info("StoreUserController.deleteStoreUser?id={}", id);
-        storeUserService.deleteStoreUser(id);
-        return R.success("删除成功");
+        return storeUserService.deleteStoreUser(id);
     }
 
     /**
@@ -366,6 +359,16 @@ public class StoreUserController {
     }
 
     /**
+     * 商家端注销用户效验
+     */
+    @ApiOperation("商家端注销用户效验")
+    @PostMapping("/storeCancelAccountVerification")
+    public R<Map<String, String>> storeCancelAccountVerification(@RequestBody StoreUserVo storeUserVo) {
+        log.info("StoreUserController.storeCancelAccountVerification?storeUserVo={}", storeUserVo);
+             return R.data(storeUserService.storeCancelAccountVerification(storeUserVo));
+    }
+
+    /**
      * 商家端注销用户
      */
     @ApiOperation("商家端注销用户")
@@ -390,4 +393,15 @@ public class StoreUserController {
         storeUserService.storeCancelAccountUn(storeUserVo);
         return R.success("撤回注销成功");
     }
+
+    /**
+     * 商家端撤销注销用户
+     */
+    @ApiOperation("手动删除商家账号及店铺")
+    @DeleteMapping("/deleteStoreAccountInfo")
+    public R<StoreUserVo> deleteStoreAccountInfo(@RequestBody StoreUserVo storeUserVo) {
+        log.info("StoreUserController.deleteStoreAccountInfo?storeUserVo={}", storeUserVo);
+        storeUserService.deleteStoreAccountInfo(storeUserVo);
+        return R.success("删除成功");
+    }
 }

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

@@ -3,6 +3,7 @@ package shop.alien.store.service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
 import shop.alien.entity.store.LifeCoupon;
+import shop.alien.entity.store.vo.LifeCouponStatusVo;
 
 import java.util.Map;
 
@@ -19,4 +20,8 @@ public interface LifeCouponService extends IService<LifeCoupon> {
 
     Map<String,String> couponVerify(String storeId, String quanCode);
 
+    /**
+     * 获取代金券状态
+     */
+    public LifeCouponStatusVo getCouponStatus(String couponId);
 }

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

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import shop.alien.entity.store.LifeDiscountCoupon;
 import shop.alien.entity.store.UserLoginInfo;
 import shop.alien.entity.store.dto.LifeDiscountCouponDto;
+import shop.alien.entity.store.vo.LifeCouponStatusVo;
 import shop.alien.entity.store.vo.LifeDiscountCouponVo;
 
 import java.math.BigDecimal;
@@ -76,4 +77,8 @@ public interface LifeDiscountCouponService extends IService<LifeDiscountCoupon>
      */
     public String getCouponRule(String couponId, UserLoginInfo userLoginInfo);
 
+    /**
+     * 获取优惠券状态
+     */
+    public LifeCouponStatusVo getCouponStatus(String couponId);
 }

+ 18 - 0
alien-store/src/main/java/shop/alien/store/service/LifeMessageNotDisturbService.java

@@ -0,0 +1,18 @@
+package shop.alien.store.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import shop.alien.entity.store.LifeMessageNotDisturb;
+
+/**
+ * <p>
+ * 消息免打扰 服务类
+ * </p>
+ *
+ * @author ssk
+ * @since 2025-07-11
+ */
+public interface LifeMessageNotDisturbService extends IService<LifeMessageNotDisturb> {
+
+    boolean notDisturb(String receiverId, String disturbId, int type);
+
+}

+ 9 - 8
alien-store/src/main/java/shop/alien/store/service/LifeMessageService.java

@@ -9,19 +9,20 @@ import java.util.List;
 
 public interface LifeMessageService extends IService<LifeMessage> {
 
-    List<LifeMessageVo> getMessageList(String receiverId, int friendType, String search);
+    List<LifeMessageVo> getMessageList(String receiverId, int friendType, String search) throws Exception;
 
-    LifeMessageVo getStrangerMessageNum(String receiverId);
+    LifeMessageVo getStrangerMessageNum(String receiverId) throws Exception ;
 
-    LifeMessageVo getNoFriendMessageNum(String receiverId);
+    LifeMessageVo getNoFriendMessageNum(String receiverId) throws Exception ;
 
-    List<LifeMessageVo> getMessageListByReceiverId(String senderId, String receiverId);
+    List<LifeMessageVo> getMessageListByReceiverId(String senderId, String receiverId) throws Exception;
 
-    int read(String receiverId, String senderId);
+    int read(String receiverId, String senderId) throws Exception;
 
-    int noReadCount(String receiverId);
+    int noReadCount(String receiverId)throws Exception;
 
-    int deleteMessageByPhoneId(String senderId, String receiverId);
+    int deleteMessageByPhoneId(String senderId, String receiverId) throws Exception;
+
+    int getAllNoReadCount(String receiverId) throws Exception;
 
-    boolean notDisturb(String receiverId, int disturbId, int type);
 }

+ 6 - 0
alien-store/src/main/java/shop/alien/store/service/LifeStoreService.java

@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
@@ -16,6 +17,7 @@ import shop.alien.entity.store.vo.LifeStoreVo;
 import shop.alien.entity.store.vo.LifeUserVo;
 import shop.alien.entity.store.vo.StoreInfoVo;
 import shop.alien.mapper.*;
+import shop.alien.store.config.BaseRedisService;
 import shop.alien.util.common.ListToPage;
 
 import java.time.LocalDateTime;
@@ -25,9 +27,11 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
+
 /**
  * 门店
  */
+@Slf4j
 @Service
 @RequiredArgsConstructor
 public class LifeStoreService {
@@ -52,6 +56,8 @@ public class LifeStoreService {
 
     private final LifeBlacklistMapper lifeBlacklistMapper;
 
+    private final BaseRedisService baseRedisService;
+
     public LifeUser loginByPhone(String phone) {
         LambdaUpdateWrapper<LifeUser> wrapperFans = new LambdaUpdateWrapper<>();
         wrapperFans.eq(LifeUser::getUserPhone, phone);

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

@@ -126,7 +126,7 @@ public interface StoreInfoService extends IService<StoreInfo> {
      *
      * @return ResponseEntity
      */
-    void deleteStoreInfo(StoreInfoDto storeInfoDto);
+    String deleteStoreInfo(StoreInfoDto storeInfoDto);
 
     /**
      * web端删除门店及门店用户

+ 26 - 7
alien-store/src/main/java/shop/alien/store/service/StoreUserService.java

@@ -8,6 +8,7 @@ import shop.alien.entity.store.vo.StoreUserVo;
 
 import java.io.IOException;
 import java.util.List;
+import java.util.Map;
 
 /**
  * 二期-门店用户 服务类
@@ -23,7 +24,7 @@ public interface StoreUserService extends IService<StoreUser> {
      * @param phone 手机号
      * @return StoreUser
      */
-    StoreUser getUserByPhone(String phone);
+    StoreUserVo getUserByPhone(String phone);
 
 
     /**
@@ -52,14 +53,22 @@ public interface StoreUserService extends IService<StoreUser> {
     boolean updatePassword(Integer id, String password);
 
     /**
-     * 设置用户信息
+     * 修改密码或忘记密码
      *
-     * @param id     主键
-     * @param name   姓名
-     * @param idCard 身份证号
+     * @param phone   手机号
+     * @param oldPassword 原密码
+     * @param newPassword       新密码
+     * @param confirmNewPassword 确认密码
+     * @param type 类型
      * @return boolean
      */
-    boolean setUserInfo(Integer id, String name, String idCard);
+    boolean forgetOrModifyPassword(String phone, String newPhone, String oldPassword, String newPassword,String confirmNewPassword,String verificationCode, Integer type);
+
+    /**
+     * 设置用户信息
+     * @return boolean
+     */
+    boolean setUserInfo(StoreUser storeUserVo);
 
     /**
      * 修改支付密码
@@ -103,7 +112,7 @@ public interface StoreUserService extends IService<StoreUser> {
      *
      * @return boolean
      */
-    void deleteStoreUser(String id);
+    R<StoreUserVo> deleteStoreUser(String id);
 
     /**
      * web端切换商家端用户状态
@@ -144,6 +153,11 @@ public interface StoreUserService extends IService<StoreUser> {
     R<Boolean> register(String phone, String password);
 
     /**
+     *
+     */
+    Map<String,String> storeCancelAccountVerification(StoreUserVo storeUserVo);
+
+    /**
      * 商家端注销用户
      */
     void storeCancelAccount(StoreUserVo storeUserVo);
@@ -154,6 +168,11 @@ public interface StoreUserService extends IService<StoreUser> {
     void storeCancelAccountUn(StoreUserVo storeUserVo);
 
     /**
+     * 手动删除商家账号及店铺
+     */
+    void deleteStoreAccountInfo(StoreUserVo storeUserVo);
+
+    /**
      * 获取主键集合
      *
      * @param name

+ 34 - 4
alien-store/src/main/java/shop/alien/store/service/impl/LifeCouponServiceImpl.java

@@ -9,11 +9,9 @@ import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
-import shop.alien.entity.store.LifeCoupon;
-import shop.alien.entity.store.LifeUserOrder;
-import shop.alien.entity.store.StoreDictionary;
-import shop.alien.entity.store.StoreIncomeDetailsRecord;
+import shop.alien.entity.store.*;
 import shop.alien.entity.store.dto.LifeDiscountCouponStoreFriendDto;
+import shop.alien.entity.store.vo.LifeCouponStatusVo;
 import shop.alien.mapper.LifeCouponMapper;
 import shop.alien.mapper.LifeUserOrderMapper;
 import shop.alien.mapper.StoreDictionaryMapper;
@@ -192,4 +190,36 @@ public class LifeCouponServiceImpl extends ServiceImpl<LifeCouponMapper, LifeCou
         return resultMap;
     }
 
+    /**
+     * <p>
+     * 获取代金券状态
+     * </p>
+     *
+     * @author zhangchen
+     * @since 2025-07-14
+     */
+    @Override
+    public LifeCouponStatusVo getCouponStatus(String couponId) {
+        if (couponId == null || couponId.isEmpty()) {
+            log.error("获取代金券状态失败:couponId为空");
+            throw new IllegalArgumentException("couponId不能为空");
+        }
+        try {
+            LifeCoupon coupon = lifeCouponMapper.selectById(couponId);
+            LifeCouponStatusVo lifeCouponStatusVo = new LifeCouponStatusVo();
+            if (coupon != null) {
+                lifeCouponStatusVo.setCouponId(couponId);
+                lifeCouponStatusVo.setSingleQty(coupon.getSingleQty());
+                lifeCouponStatusVo.setBuyLimit(coupon.getBuyLimit());
+            } else {
+                // 可选:设置默认值或标记状态为无效
+                lifeCouponStatusVo.setSingleQty(0); // 或其他默认逻辑
+            }
+            return lifeCouponStatusVo;
+        } catch (Exception e) {
+            log.error("获取代金券状态失败: {}", e);
+            throw new RuntimeException("获取代金券状态失败", e); // 或者根据项目规范处理
+        }
+    }
+
 }

+ 32 - 0
alien-store/src/main/java/shop/alien/store/service/impl/LifeDiscountCouponServiceImpl.java

@@ -12,6 +12,7 @@ import org.springframework.beans.BeansException;
 import org.springframework.stereotype.Service;
 import shop.alien.entity.store.*;
 import shop.alien.entity.store.dto.LifeDiscountCouponDto;
+import shop.alien.entity.store.vo.LifeCouponStatusVo;
 import shop.alien.entity.store.vo.LifeDiscountCouponStoreFriendVo;
 import shop.alien.entity.store.vo.LifeDiscountCouponVo;
 import shop.alien.mapper.*;
@@ -856,6 +857,37 @@ public class LifeDiscountCouponServiceImpl extends ServiceImpl<LifeDiscountCoupo
         return forbiddenRule;
     }
 
+    /**
+     * <p>
+     * 获取优惠券状态
+     * </p>
+     *
+     * @author zhangchen
+     * @since 2025-07-14
+     */
+    @Override
+    public LifeCouponStatusVo getCouponStatus(String couponId) {
+        if (couponId == null || couponId.isEmpty()) {
+            log.error("获取优惠券状态失败:couponId为空");
+            throw new IllegalArgumentException("couponId不能为空");
+        }
+        try {
+            LifeDiscountCoupon lifeDiscountCoupon = lifeDiscountCouponMapper.selectById(couponId);
+            LifeCouponStatusVo lifeCouponStatusVo = new LifeCouponStatusVo();
+            if (lifeDiscountCoupon != null) {
+                lifeCouponStatusVo.setCouponId(couponId);
+                lifeCouponStatusVo.setSingleQty(lifeDiscountCoupon.getSingleQty());
+            } else {
+                    // 可选:设置默认值或标记状态为无效
+                lifeCouponStatusVo.setSingleQty(0); // 或其他默认逻辑
+            }
+            return lifeCouponStatusVo;
+        } catch (Exception e) {
+            log.error("获取优惠券状态失败: {}", e);
+            throw new RuntimeException("获取优惠券状态失败", e); // 或者根据项目规范处理
+        }
+    }
+
 //    private static final String API_URL = "https://date.nager.at/api/v3/PublicHolidays/{year}/{countryCode}";
 //    private static final String COUNTRY_CODE = "CN";
 //    public static void get() throws Exception {

+ 42 - 0
alien-store/src/main/java/shop/alien/store/service/impl/LifeMessageNotDisturbServiceImpl.java

@@ -0,0 +1,42 @@
+package shop.alien.store.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import shop.alien.entity.store.LifeMessageNotDisturb;
+import shop.alien.mapper.LifeMessageNotDisturbMapper;
+import shop.alien.store.service.LifeMessageNotDisturbService;
+
+/**
+ * <p>
+ * 消息免打扰 服务实现类
+ * </p>
+ *
+ * @author ssk
+ * @since 2025-07-11
+ */
+@Service
+@RequiredArgsConstructor
+public class LifeMessageNotDisturbServiceImpl extends ServiceImpl<LifeMessageNotDisturbMapper, LifeMessageNotDisturb> implements LifeMessageNotDisturbService {
+
+    private final LifeMessageNotDisturbMapper lifeMessageNotDisturbMapper;
+
+    @Override
+    public boolean notDisturb(String receiverId, String disturbId, int type) {
+        if (1 == type) {
+            LifeMessageNotDisturb disturb = new LifeMessageNotDisturb();
+            disturb.setPhoneId(receiverId);
+            disturb.setNotDisturbId(disturbId);
+            lifeMessageNotDisturbMapper.insert(disturb);
+            return true;
+        } else if (2 == type) {
+            UpdateWrapper<LifeMessageNotDisturb> wrapper = new UpdateWrapper<>();
+            wrapper.eq("phone_id", receiverId);
+            wrapper.eq("not_disturb_id", disturbId);
+            lifeMessageNotDisturbMapper.delete(wrapper);
+            return true;
+        }
+        return false;
+    }
+}

+ 319 - 236
alien-store/src/main/java/shop/alien/store/service/impl/LifeMessageServiceImpl.java

@@ -3,46 +3,48 @@ package shop.alien.store.service.impl;
 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;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.github.pagehelper.util.StringUtil;
 import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
-import org.springframework.util.StringUtils;
 import shop.alien.entity.store.*;
+import shop.alien.entity.store.vo.LifeBlacklistVo;
 import shop.alien.entity.store.vo.LifeFansVo;
 import shop.alien.entity.store.vo.LifeMessageVo;
-import shop.alien.mapper.LifeFansMapper;
-import shop.alien.mapper.LifeMessageMapper;
-import shop.alien.mapper.LifeUserMapper;
+import shop.alien.mapper.*;
 import shop.alien.store.service.LifeMessageService;
 import shop.alien.store.service.LifeUserService;
 import shop.alien.util.common.JwtUtil;
 
+import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.List;
 import java.util.Objects;
 import java.util.stream.Collectors;
 
+@Slf4j
 @Service
 @RequiredArgsConstructor
 public class LifeMessageServiceImpl extends ServiceImpl<LifeMessageMapper, LifeMessage> implements LifeMessageService {
 
-    private final LifeMessageMapper messageMapper;
-
+    private final LifeMessageMapper lifeMessageMapper;
     private final LifeFansMapper fansMapper;
     private final LifeFansMapper lifeFansMapper;
     private final LifeUserMapper lifeUserMapper;
     private final StoreUserServiceImpl storeUserService;
     private final StoreImgServiceImpl storeImgService;
     private final LifeUserService lifeUserService;
-
+    private final LifeMessageNotDisturbMapper lifeMessageNotDisturbMapper;
+    private final LifeBlacklistMapper lifeBlacklistMapper;
+    private final LifeNoticeMapper lifeNoticeMapper;
 
     @Override
-    public List<LifeMessageVo> getMessageList(String receiverId, int friendType, String search) {
-        // 查询所有好友
+    public List<LifeMessageVo> getMessageList(String receiverId, int friendType, String search) throws Exception {
+        try {
+            // 查询所有好友
 //        QueryWrapper<LifeFansVo> wrapper = new QueryWrapper<>();
 //        wrapper.groupBy("foll.phoneId");
 
@@ -72,283 +74,364 @@ public class LifeMessageServiceImpl extends ServiceImpl<LifeMessageMapper, LifeM
 //            wrapper.apply("(sender_id not in (" + friendsIdsStr + ") and receiver_id not in (" + friendsIdsStr + "))");
 //        }
 
-        String blockerType = "user".equals(Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getString("userType")) ? "2" : "1";
-        String blockerId = JwtUtil.getCurrentUserInfo().getString("userId");
-        QueryWrapper<LifeFansVo> wrapper = new QueryWrapper<>();
-        wrapper.eq("message.num", 1);
-        // 过滤拉黑
-        wrapper.apply("(user.id not in ( " +
-                            "     select blocked_id from life_blacklist " +
-                            "     where blocker_type = '" + blockerType + "' and blocker_id = '" + blockerId + "' and blocked_type = '2' and delete_flag = 0 " +
-                            ") or user.id is null)");
-        wrapper.apply("(suser.id not in ( " +
-                            "     select blocked_id from life_blacklist " +
-                            "     where blocker_type = '" + blockerType + "' and blocker_id = '" + blockerId + "' and blocked_type = '1' and delete_flag = 0 " +
-                            ") or suser.id is null)");
-
-        // 通过搜索查询的情况下  不区分是否聊过  搜索所有消息
-        if (0 == friendType && StringUtil.isNotEmpty(search)) {
-            wrapper.apply("(user.user_name like '%" + search + "%' or suser.name like '%" + search + "%')");
-        // 聊过
-        } else if (1 == friendType) {
-            wrapper.apply("message.phoneId in ( " +
-                    "    select receiver_id " +
-                    "    from life_message " +
-                    "    where sender_id = '" + receiverId + "'" +
-                    "    group by receiver_id " +
-                    ")");
-        // 没聊过
-        } else if (2 == friendType) {
-            wrapper.apply("message.phoneId not in ( " +
-                    "    select receiver_id " +
-                    "    from life_message " +
-                    "    where sender_id = '" + receiverId + "'" +
-                    "    group by receiver_id " +
-                    ")");
-        }
-        wrapper.orderByDesc("message.created_time");
+            String blockerType = "user".equals(Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getString("userType")) ? "2" : "1";
+            String blockerId = JwtUtil.getCurrentUserInfo().getString("userId");
+            QueryWrapper<LifeFansVo> wrapper = new QueryWrapper<>();
+            wrapper.eq("message.num", 1);
+            // 过滤拉黑
+            wrapper.apply("(user.id not in ( " +
+                    "     select blocked_id from life_blacklist " +
+                    "     where blocker_type = '" + blockerType + "' and blocker_id = '" + blockerId + "' and blocked_type = '2' and delete_flag = 0 " +
+                    ") or user.id is null)");
+            wrapper.apply("(suser.id not in ( " +
+                    "     select blocked_id from life_blacklist " +
+                    "     where blocker_type = '" + blockerType + "' and blocker_id = '" + blockerId + "' and blocked_type = '1' and delete_flag = 0 " +
+                    ") or suser.id is null)");
+
+            // 通过搜索查询的情况下  不区分是否聊过  搜索所有消息
+            if (0 == friendType && StringUtil.isNotEmpty(search)) {
+                wrapper.apply("(user.user_name like '%" + search + "%' or suser.name like '%" + search + "%')");
+                // 聊过
+            } else if (1 == friendType) {
+                wrapper.apply("message.phoneId in ( " +
+                        "    select receiver_id " +
+                        "    from life_message " +
+                        "    where sender_id = '" + receiverId + "'" +
+                        "    group by receiver_id " +
+                        ")");
+                // 没聊过
+            } else if (2 == friendType) {
+                wrapper.apply("message.phoneId not in ( " +
+                        "    select receiver_id " +
+                        "    from life_message " +
+                        "    where sender_id = '" + receiverId + "'" +
+                        "    group by receiver_id " +
+                        ")");
+            }
+            wrapper.orderByDesc("message.created_time");
 //        IPage<LifeMessageVo> ipage = new Page<>(page, size);
-        List<LifeMessageVo> lifeMessagePageList = messageMapper.getLifeMessagePageByPhoneId(receiverId, wrapper);
-        if (!CollectionUtils.isEmpty(lifeMessagePageList)) {
-            // 取出所有发送消息的用户
+            List<LifeMessageVo> lifeMessagePageList = lifeMessageMapper.getLifeMessagePageByPhoneId(receiverId, wrapper);
+            if (!CollectionUtils.isEmpty(lifeMessagePageList)) {
+                // 取出所有发送消息的用户
 //            List<String> phoneIdList = lifeMessagePageList.stream().map(LifeMessageVo::getPhoneId).filter(item -> item.contains("_")).collect(Collectors.toList());
 
-            // 当前用户的所有关注
-            LambdaQueryWrapper<LifeFans> followWrapper = new LambdaQueryWrapper<>();
-            followWrapper.eq(LifeFans::getFansId, receiverId);
-            followWrapper.eq(LifeFans::getDeleteFlag, 0);
-            List<LifeFans> followList = fansMapper.selectList(followWrapper);
-            List<String> followIds = followList.stream().map(LifeFans::getFollowedId).collect(Collectors.toList());
-
-            // 当前用户的所有粉丝
-            LambdaQueryWrapper<LifeFans> fansWrapper = new LambdaQueryWrapper<>();
-            fansWrapper.eq(LifeFans::getFollowedId, receiverId);
-            followWrapper.eq(LifeFans::getDeleteFlag, 0);
-            List<LifeFans> fansList = fansMapper.selectList(fansWrapper);
-            List<String> fansIds = fansList.stream().map(LifeFans::getFansId).collect(Collectors.toList());
-
-            // 查询所有未读消息
-            LambdaQueryWrapper<LifeMessage> messageWrapper = new LambdaQueryWrapper<>();
-            messageWrapper.eq(LifeMessage::getReceiverId, receiverId);
-            messageWrapper.eq(LifeMessage::getIsRead, 0);
-            messageWrapper.eq(LifeMessage::getType, "1");
-            messageWrapper.eq(LifeMessage::getDeleteFlag, 0);
-            List<LifeMessage> noReadList = messageMapper.selectList(messageWrapper);
+                // 当前用户的所有关注
+                LambdaQueryWrapper<LifeFans> followWrapper = new LambdaQueryWrapper<>();
+                followWrapper.eq(LifeFans::getFansId, receiverId);
+                followWrapper.eq(LifeFans::getDeleteFlag, 0);
+                List<LifeFans> followList = fansMapper.selectList(followWrapper);
+                List<String> followIds = followList.stream().map(LifeFans::getFollowedId).collect(Collectors.toList());
+
+                // 当前用户的所有粉丝
+                LambdaQueryWrapper<LifeFans> fansWrapper = new LambdaQueryWrapper<>();
+                fansWrapper.eq(LifeFans::getFollowedId, receiverId);
+                followWrapper.eq(LifeFans::getDeleteFlag, 0);
+                List<LifeFans> fansList = fansMapper.selectList(fansWrapper);
+                List<String> fansIds = fansList.stream().map(LifeFans::getFansId).collect(Collectors.toList());
+
+                // 查询所有未读消息
+                LambdaQueryWrapper<LifeMessage> messageWrapper = new LambdaQueryWrapper<>();
+                messageWrapper.eq(LifeMessage::getReceiverId, receiverId);
+                messageWrapper.eq(LifeMessage::getIsRead, 0);
+                messageWrapper.eq(LifeMessage::getDeleteFlag, 0);
+                List<LifeMessage> noReadList = lifeMessageMapper.selectList(messageWrapper);
+
+                // 查询免打扰用户
+                QueryWrapper<LifeMessageNotDisturb> notDisturbWrapper = new QueryWrapper<>();
+                notDisturbWrapper.eq("phone_id", receiverId);
+                List<String> notDisturbList = lifeMessageNotDisturbMapper.selectList(notDisturbWrapper).stream().map(LifeMessageNotDisturb::getNotDisturbId).collect(Collectors.toList());
 
 //            // 根据手机号查询发送人信息
 //            List<String> storePhoneList = phoneIdList.stream().filter(item -> "store".equals(item.split("_")[0])).map(item -> item.split("_")[1]).collect(Collectors.toList());
 //            List<String> userPhoneList = phoneIdList.stream().filter(item -> "user".equals(item.split("_")[0])).map(item -> item.split("_")[1]).collect(Collectors.toList());
 //            String storePhones = "'" + String.join("','", storePhoneList) + "'";
 //            String userPhones = "'" + String.join("','", userPhoneList) + "'";
-//            List<LifeMessageVo> userList = messageMapper.getLifeUserAndStoreUserByPhone(storePhones, userPhones);
+//            List<LifeMessageVo> userList = lifeMessageMapper.getLifeUserAndStoreUserByPhone(storePhones, userPhones);
 
-            for (LifeMessageVo messageVo : lifeMessagePageList) {
+                for (LifeMessageVo messageVo : lifeMessagePageList) {
 //                // 发送人信息
 //                LifeMessageVo user = userList.stream().filter(item -> item.getPhoneId().equals(messageVo.getPhoneId())).findFirst().orElse(null);
 //                messageVo.setUserName(null == user ? "" : user.getUserName());
 //                messageVo.setUserImage(null == user ? "" : user.getUserImage());
 
-                // 未读消息数量
-                messageVo.setNotReadCount(noReadList.stream().filter(item -> item.getSenderId().equals(messageVo.getPhoneId())).count());
-
-                // 我是否关注对方
-                if (followIds.contains(messageVo.getPhoneId())) {
-                    messageVo.setIsFollowThis("1");
-                } else {
-                    messageVo.setIsFollowThis("0");
-                }
-
-                // 对方是否关注我
-                if (fansIds.contains(messageVo.getPhoneId())) {
-                    messageVo.setIsFollowMe("1");
-                } else {
-                    messageVo.setIsFollowMe("0");
-                }
-
-                // 判断当前登录人是否是商户
-                boolean store = messageVo.getPhoneId().contains("store_");
-                if (store) {
-                    messageVo.setIsMerchant("1");
-                } else {
-                    messageVo.setIsMerchant("0");
+                    // 免打扰
+                    if (notDisturbList.contains(messageVo.getPhoneId())) {
+                        messageVo.setIsNotDisturb("1");
+                        // 未读消息数量
+                        messageVo.setNotReadCount(0L);
+                    } else {
+                        messageVo.setIsNotDisturb("0");
+                        messageVo.setNotReadCount(noReadList.stream().filter(item -> item.getSenderId().equals(messageVo.getPhoneId())).count());
+                        // 未读消息数量
+                    }
+
+                    // 我是否关注对方
+                    if (followIds.contains(messageVo.getPhoneId())) {
+                        messageVo.setIsFollowThis("1");
+                    } else {
+                        messageVo.setIsFollowThis("0");
+                    }
+
+                    // 对方是否关注我
+                    if (fansIds.contains(messageVo.getPhoneId())) {
+                        messageVo.setIsFollowMe("1");
+                    } else {
+                        messageVo.setIsFollowMe("0");
+                    }
+
+                    // 判断当前登录人是否是商户
+                    boolean store = messageVo.getPhoneId().contains("store_");
+                    if (store) {
+                        messageVo.setIsMerchant("1");
+                    } else {
+                        messageVo.setIsMerchant("0");
+                    }
                 }
             }
-        }
 
-        return lifeMessagePageList;
+            return lifeMessagePageList;
+        } catch (Exception e) {
+            log.error("LifeMessageServiceImpl.getMessageList Error Mgs={}", e.getMessage());
+            throw new Exception(e);
+        }
     }
 
     @Override
-    public LifeMessageVo getStrangerMessageNum(String receiverId) {
-        String blockerType = "user".equals(Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getString("userType")) ? "2" : "1";
-        String blockerId = JwtUtil.getCurrentUserInfo().getString("userId");
-        QueryWrapper<LifeFansVo> wrapper = new QueryWrapper<>();
-        // 过滤拉黑
-        wrapper.apply("(user.id not in ( " +
-                "     select blocked_id from life_blacklist " +
-                "     where blocker_type = '" + blockerType + "' and blocker_id = '" + blockerId + "' and blocked_type = '2' and delete_flag = 0 " +
-                ") or user.id is null)");
-        wrapper.apply("(suser.id not in ( " +
-                "     select blocked_id from life_blacklist " +
-                "     where blocker_type = '" + blockerType + "' and blocker_id = '" + blockerId + "' and blocked_type = '1' and delete_flag = 0 " +
-                ") or suser.id is null)");
-        // 没聊过
-        wrapper.apply("message.phoneId not in ( " +
-                "    select receiver_id " +
-                "    from life_message " +
-                "    where sender_id = '" + receiverId + "'" +
-                "    group by receiver_id " +
-                ")");
-        wrapper.orderByDesc("message.created_time");
-//        IPage<LifeMessageVo> ipage = new Page<>(1, Integer.MAX_VALUE);
-        List<LifeMessageVo> lifeMessagePageList = messageMapper.getLifeMessagePageByPhoneId(receiverId, wrapper);
-        LifeMessageVo vo = new LifeMessageVo();
-        if (!CollectionUtils.isEmpty(lifeMessagePageList)) {
-            vo.setUserName(lifeMessagePageList.get(0).getUserName());
-            vo.setNotReadCount(lifeMessagePageList.stream().filter(item -> 0 == item.getIsRead()).count());
-        }
+    public LifeMessageVo getStrangerMessageNum(String receiverId) throws Exception {
+        try {
+            // 查询免打扰用户
+            QueryWrapper<LifeMessageNotDisturb> notDisturbWrapper = new QueryWrapper<>();
+            notDisturbWrapper.eq("phone_id", receiverId);
+            List<String> notDisturbList = lifeMessageNotDisturbMapper.selectList(notDisturbWrapper).stream().map(LifeMessageNotDisturb::getNotDisturbId).collect(Collectors.toList());
+
+            String blockerType = "user".equals(Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getString("userType")) ? "2" : "1";
+            String blockerId = JwtUtil.getCurrentUserInfo().getString("userId");
+            QueryWrapper<LifeFansVo> wrapper = new QueryWrapper<>();
+            // 过滤拉黑
+            wrapper.apply("(user.id not in ( " +
+                    "     select blocked_id from life_blacklist " +
+                    "     where blocker_type = '" + blockerType + "' and blocker_id = '" + blockerId + "' and blocked_type = '2' and delete_flag = 0 " +
+                    ") or user.id is null)");
+            wrapper.apply("(suser.id not in ( " +
+                    "     select blocked_id from life_blacklist " +
+                    "     where blocker_type = '" + blockerType + "' and blocker_id = '" + blockerId + "' and blocked_type = '1' and delete_flag = 0 " +
+                    ") or suser.id is null)");
+            // 没聊过
+            wrapper.apply("message.phoneId not in ( " +
+                    "    select receiver_id " +
+                    "    from life_message " +
+                    "    where sender_id = '" + receiverId + "'" +
+                    "    group by receiver_id " +
+                    ")");
+            wrapper.orderByDesc("message.created_time");
+
+            List<LifeMessageVo> lifeMessagePageList = lifeMessageMapper.getLifeMessagePageByPhoneId(receiverId, wrapper);
+            LifeMessageVo vo = new LifeMessageVo();
+            if (!CollectionUtils.isEmpty(lifeMessagePageList)) {
+                vo.setUserName(lifeMessagePageList.get(0).getUserName());
+                lifeMessagePageList = lifeMessagePageList.stream().filter(item -> !notDisturbList.contains(item.getPhoneId())).collect(Collectors.toList());
+                vo.setNotReadCount(lifeMessagePageList.stream().filter(item -> 0 == item.getIsRead()).count());
+            }
 
-        return vo;
+            return vo;
+        } catch (Exception e) {
+            log.error("LifeMessageServiceImpl.getStrangerMessageNum Error Mgs={}", e.getMessage());
+            throw new Exception(e);
+        }
     }
 
     @Override
-    public LifeMessageVo getNoFriendMessageNum(String receiverId) {
-        // 查询所有好友
-        QueryWrapper<LifeFansVo> wrapper = new QueryWrapper<>();
-        wrapper.groupBy("foll.phoneId");
-        String blockerType = "";
-        String blockerId = "";
-        if ("user".equals(receiverId.split("_")[0])) {
-            String myselfUserPhone = receiverId.split("_")[1];
-            blockerType = "2";
-            LifeUser myLifeUser = lifeUserService.getUserByPhone(myselfUserPhone);
-            blockerId = String.valueOf(myLifeUser.getId());
-        } else {
-            String myselfStorePhone = receiverId.split("_")[1];
-            blockerType = "1";
-            StoreUser myStoreUser = storeUserService.getUserByPhone(myselfStorePhone);
-            blockerId = String.valueOf(myStoreUser.getId());
-        }
-
-        List<LifeFansVo> lifeFansList = lifeFansMapper.getMutualAttention(new Page<>(1, Integer.MAX_VALUE), receiverId, blockerType, blockerId, wrapper).getRecords();
-        List<String> friendsIds = lifeFansList.stream().map(LifeFansVo::getPhoneId).filter(item -> !item.equals(receiverId)).collect(Collectors.toList());
-        String friendsIdsStr = "'" + String.join("','", friendsIds) + "'";
-
-        // 当前用户的所有未关注人消息
-        wrapper = new QueryWrapper<>();
-        wrapper.eq("num", 1);
-        wrapper.apply("(sender_id not in (" + friendsIdsStr + ") and receiver_id not in (" + friendsIdsStr + "))");
-        wrapper.orderByDesc("created_time");
-//        IPage<LifeMessageVo> ipage = new Page<>(1, Integer.MAX_VALUE);
-        List<LifeMessageVo> lifeMessageVoList = messageMapper.getLifeMessagePageByPhoneId(receiverId, wrapper);
-
-        LifeMessageVo messageVo = lifeMessageVoList.stream().max(Comparator.comparing(LifeMessageVo::getCreatedTime)).orElse(null);
-        if (messageVo != null) {
-            messageVo.setNotReadCount(lifeMessageVoList.stream().filter(item -> 0 == item.getIsRead()).count());
-            // 根据手机号查询发送人信息
-            String storePhones = "''";
-            String userPhones = "''";
-            if (messageVo.getPhoneId().split("_")[0].equals("store")) {
-                storePhones = "'" + messageVo.getPhoneId().split("_")[1] + "'";
+    public LifeMessageVo getNoFriendMessageNum(String receiverId) throws Exception {
+        try {
+            // 查询所有好友
+            QueryWrapper<LifeFansVo> wrapper = new QueryWrapper<>();
+            wrapper.groupBy("foll.phoneId");
+            String blockerType = "";
+            String blockerId = "";
+            if ("user".equals(receiverId.split("_")[0])) {
+                String myselfUserPhone = receiverId.split("_")[1];
+                blockerType = "2";
+                LifeUser myLifeUser = lifeUserService.getUserByPhone(myselfUserPhone);
+                blockerId = String.valueOf(myLifeUser.getId());
             } else {
-                userPhones = "'" + messageVo.getPhoneId().split("_")[1] + "'";
+                String myselfStorePhone = receiverId.split("_")[1];
+                blockerType = "1";
+                StoreUser myStoreUser = storeUserService.getUserByPhone(myselfStorePhone);
+                blockerId = String.valueOf(myStoreUser.getId());
             }
-            List<LifeMessageVo> userList = messageMapper.getLifeUserAndStoreUserByPhone(storePhones, userPhones);
-            if (!CollectionUtils.isEmpty(userList)) {
-                messageVo.setUserName(userList.get(0).getUserName());
-                messageVo.setUserImage(userList.get(0).getUserImage());
-            }
-        }
 
-        return messageVo;
-    }
+            List<LifeFansVo> lifeFansList = lifeFansMapper.getMutualAttention(new Page<>(1, Integer.MAX_VALUE), receiverId, blockerType, blockerId, wrapper).getRecords();
+            List<String> friendsIds = lifeFansList.stream().map(LifeFansVo::getPhoneId).filter(item -> !item.equals(receiverId)).collect(Collectors.toList());
+            String friendsIdsStr = "'" + String.join("','", friendsIds) + "'";
 
-    @Override
-    public List<LifeMessageVo> getMessageListByReceiverId(String receiverId, String senderId) {
-
-
-        // 获取发送方与接收方头像
-        LifeUser lifeUser1 = null;
-        StoreImg storeImg = null;
-        if (receiverId.startsWith("user_")) {
-            lifeUser1 = lifeUserMapper.selectOne(new QueryWrapper<LifeUser>().eq("user_phone", receiverId.substring(5)));
-        } else {
-            StoreUser storeUser1 = storeUserService.getOne(new QueryWrapper<StoreUser>().eq("phone", receiverId.substring(6)));
-            List<StoreImg> storeImgList = storeImgService.getStoreImg(storeUser1.getStoreId(), 10);
-            if (!storeImgList.isEmpty()) {
-                storeImg = storeImgList.get(0);
+            // 当前用户的所有未关注人消息
+            wrapper = new QueryWrapper<>();
+            wrapper.eq("num", 1);
+            wrapper.apply("(sender_id not in (" + friendsIdsStr + ") and receiver_id not in (" + friendsIdsStr + "))");
+            wrapper.orderByDesc("created_time");
+//        IPage<LifeMessageVo> ipage = new Page<>(1, Integer.MAX_VALUE);
+            List<LifeMessageVo> lifeMessageVoList = lifeMessageMapper.getLifeMessagePageByPhoneId(receiverId, wrapper);
+
+            LifeMessageVo messageVo = lifeMessageVoList.stream().max(Comparator.comparing(LifeMessageVo::getCreatedTime)).orElse(null);
+            if (messageVo != null) {
+                messageVo.setNotReadCount(lifeMessageVoList.stream().filter(item -> 0 == item.getIsRead()).count());
+                // 根据手机号查询发送人信息
+                String storePhones = "''";
+                String userPhones = "''";
+                if (messageVo.getPhoneId().split("_")[0].equals("store")) {
+                    storePhones = "'" + messageVo.getPhoneId().split("_")[1] + "'";
+                } else {
+                    userPhones = "'" + messageVo.getPhoneId().split("_")[1] + "'";
+                }
+                List<LifeMessageVo> userList = lifeMessageMapper.getLifeUserAndStoreUserByPhone(storePhones, userPhones);
+                if (!CollectionUtils.isEmpty(userList)) {
+                    messageVo.setUserName(userList.get(0).getUserName());
+                    messageVo.setUserImage(userList.get(0).getUserImage());
+                }
             }
-        }
 
-        LifeUser lifeUser2 = null;
-        StoreImg storeImg1 = null;
-        if (senderId.startsWith("user_")) {
-            lifeUser2 = lifeUserMapper.selectOne(new QueryWrapper<LifeUser>().eq("user_phone", senderId.substring(5)));
-        } else {
-            StoreUser storeUser2 = storeUserService.getOne(new QueryWrapper<StoreUser>().eq("phone", senderId.substring(6)));
-            List<StoreImg> storeImgList = storeImgService.getStoreImg(storeUser2.getStoreId(), 10);
-            if (!storeImgList.isEmpty()) {
-                storeImg1 = storeImgList.get(0);
-            }
+            return messageVo;
+        } catch (Exception e) {
+            log.error("LifeMessageServiceImpl.getNoFriendMessageNum Error Mgs={}", e.getMessage());
+            throw new Exception(e);
         }
+    }
 
-
-        List<LifeMessageVo> lifeMessageVos = messageMapper.selectUserImageLists(receiverId, senderId);
-        for (LifeMessageVo lifeMessageVo : lifeMessageVos) {
-            if (lifeMessageVo.getReceiverId().equals(receiverId)) {
-                if (null != lifeUser1) {
-                    lifeMessageVo.setReceiverImg(lifeUser1.getUserImage());
-                } else if (null != storeImg) {
-                    lifeMessageVo.setReceiverImg(storeImg.getImgUrl());
+    @Override
+    public List<LifeMessageVo> getMessageListByReceiverId(String receiverId, String senderId) throws Exception {
+        try {
+            // 获取发送方与接收方头像
+            LifeUser lifeUser1 = null;
+            StoreImg storeImg = null;
+            if (receiverId.startsWith("user_")) {
+                lifeUser1 = lifeUserMapper.selectOne(new QueryWrapper<LifeUser>().eq("user_phone", receiverId.substring(5)));
+            } else {
+                StoreUser storeUser1 = storeUserService.getOne(new QueryWrapper<StoreUser>().eq("phone", receiverId.substring(6)));
+                List<StoreImg> storeImgList = storeImgService.getStoreImg(storeUser1.getStoreId(), 10);
+                if (!storeImgList.isEmpty()) {
+                    storeImg = storeImgList.get(0);
                 }
+            }
 
-                if (null != lifeUser2) {
-                    lifeMessageVo.setSenderImg(lifeUser2.getUserImage());
-                } else if (null != storeImg1) {
-                    lifeMessageVo.setSenderImg(storeImg1.getImgUrl());
-                }
+            LifeUser lifeUser2 = null;
+            StoreImg storeImg1 = null;
+            if (senderId.startsWith("user_")) {
+                lifeUser2 = lifeUserMapper.selectOne(new QueryWrapper<LifeUser>().eq("user_phone", senderId.substring(5)));
             } else {
-                if (null != lifeUser1) {
-                    lifeMessageVo.setSenderImg(lifeUser1.getUserImage());
-                } else if (null != storeImg) {
-                    lifeMessageVo.setSenderImg(storeImg.getImgUrl());
+                StoreUser storeUser2 = storeUserService.getOne(new QueryWrapper<StoreUser>().eq("phone", senderId.substring(6)));
+                List<StoreImg> storeImgList = storeImgService.getStoreImg(storeUser2.getStoreId(), 10);
+                if (!storeImgList.isEmpty()) {
+                    storeImg1 = storeImgList.get(0);
                 }
-                if (null != lifeUser2) {
-                    lifeMessageVo.setReceiverImg(lifeUser2.getUserImage());
-                } else if (null != storeImg1) {
-                    lifeMessageVo.setReceiverImg(storeImg1.getImgUrl());
+            }
+
+            List<LifeMessageVo> lifeMessageVos = lifeMessageMapper.selectUserImageLists(receiverId, senderId);
+            for (LifeMessageVo lifeMessageVo : lifeMessageVos) {
+                if (lifeMessageVo.getReceiverId().equals(receiverId)) {
+                    if (null != lifeUser1) {
+                        lifeMessageVo.setReceiverImg(lifeUser1.getUserImage());
+                    } else if (null != storeImg) {
+                        lifeMessageVo.setReceiverImg(storeImg.getImgUrl());
+                    }
+
+                    if (null != lifeUser2) {
+                        lifeMessageVo.setSenderImg(lifeUser2.getUserImage());
+                    } else if (null != storeImg1) {
+                        lifeMessageVo.setSenderImg(storeImg1.getImgUrl());
+                    }
+                } else {
+                    if (null != lifeUser1) {
+                        lifeMessageVo.setSenderImg(lifeUser1.getUserImage());
+                    } else if (null != storeImg) {
+                        lifeMessageVo.setSenderImg(storeImg.getImgUrl());
+                    }
+                    if (null != lifeUser2) {
+                        lifeMessageVo.setReceiverImg(lifeUser2.getUserImage());
+                    } else if (null != storeImg1) {
+                        lifeMessageVo.setReceiverImg(storeImg1.getImgUrl());
+                    }
                 }
             }
+            return lifeMessageVos;
+        } catch (Exception e) {
+            log.error("LifeMessageServiceImpl.getMessageListByReceiverId Error Mgs={}", e.getMessage());
+            throw new Exception(e);
         }
-        return lifeMessageVos;
     }
 
     @Override
-    public int read(String receiverId, String senderId) {
-        LambdaUpdateWrapper<LifeMessage> wrapper = new LambdaUpdateWrapper<>();
-        wrapper.eq(LifeMessage::getReceiverId, receiverId);
-        wrapper.eq(LifeMessage::getSenderId, senderId);
-        wrapper.eq(LifeMessage::getDeleteFlag, 0);
-        wrapper.set(LifeMessage::getIsRead, 1);
-        return messageMapper.update(null, wrapper);
+    public int read(String receiverId, String senderId) throws Exception {
+        try {
+            LambdaUpdateWrapper<LifeMessage> wrapper = new LambdaUpdateWrapper<>();
+            wrapper.eq(LifeMessage::getReceiverId, receiverId);
+            wrapper.eq(LifeMessage::getSenderId, senderId);
+            wrapper.eq(LifeMessage::getDeleteFlag, 0);
+            wrapper.set(LifeMessage::getIsRead, 1);
+            return lifeMessageMapper.update(null, wrapper);
+        } catch (Exception e) {
+            log.error("LifeMessageServiceImpl.read Error Mgs={}", e.getMessage());
+            throw new Exception(e);
+        }
     }
 
     @Override
-    public int noReadCount(String receiverId) {
-        LambdaUpdateWrapper<LifeMessage> wrapper = new LambdaUpdateWrapper<>();
-        wrapper.eq(LifeMessage::getReceiverId, receiverId);
-        wrapper.eq(LifeMessage::getIsRead, 0);
-        wrapper.eq(LifeMessage::getDeleteFlag, 0);
-        return messageMapper.selectCount(wrapper);
+    public int noReadCount(String receiverId) throws Exception {
+        try {
+            LambdaUpdateWrapper<LifeMessage> wrapper = new LambdaUpdateWrapper<>();
+            wrapper.eq(LifeMessage::getReceiverId, receiverId);
+            wrapper.eq(LifeMessage::getIsRead, 0);
+            wrapper.eq(LifeMessage::getDeleteFlag, 0);
+            return lifeMessageMapper.selectCount(wrapper);
+        } catch (Exception e) {
+            log.error("LifeMessageServiceImpl.noReadCount Error Mgs={}", e.getMessage());
+            throw new Exception(e);
+        }
     }
 
     @Override
-    public int deleteMessageByPhoneId(String senderId, String receiverId) {
-        return messageMapper.deleteMessageByPhoneId(senderId, receiverId);
+    public int deleteMessageByPhoneId(String senderId, String receiverId) throws Exception {
+        try {
+            return lifeMessageMapper.deleteMessageByPhoneId(senderId, receiverId);
+        } catch (Exception e) {
+            log.error("LifeMessageServiceImpl.deleteMessageByPhoneId Error Mgs={}", e.getMessage());
+            throw new Exception(e);
+        }
     }
 
     @Override
-    public boolean notDisturb(String receiverId, int disturbId, int type) {
-        return false;
+    public int getAllNoReadCount(String receiverId) throws Exception {
+        try {
+            String blockerType = "user".equals(Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getString("userType")) ? "2" : "1";
+            String blockerId = JwtUtil.getCurrentUserInfo().getString("userId");
+
+            // 查询拉黑
+            List<String> lifeBlacklistVoList = lifeBlacklistMapper.getPhoneIdByUserId(blockerType, blockerId).stream().map(LifeBlacklistVo::getPhoneId).collect(Collectors.toList());
+
+            // 查询免打扰用户
+            QueryWrapper<LifeMessageNotDisturb> notDisturbWrapper = new QueryWrapper<>();
+            notDisturbWrapper.eq("phone_id", receiverId);
+            List<String> notDisturbList = lifeMessageNotDisturbMapper.selectList(notDisturbWrapper).stream().map(LifeMessageNotDisturb::getNotDisturbId).collect(Collectors.toList());
+            notDisturbList.addAll(lifeBlacklistVoList);
+            String notDisturbIdsStr = "'" + String.join("','", notDisturbList) + "'";
+
+            // 查询未读消息数量
+            LambdaQueryWrapper<LifeMessage> messageWrapper = new LambdaQueryWrapper<>();
+            messageWrapper.eq(LifeMessage::getReceiverId, receiverId);
+            messageWrapper.eq(LifeMessage::getIsRead, 0);
+            messageWrapper.notIn(LifeMessage::getSenderId, notDisturbIdsStr);
+            int noReadMessageCount = lifeMessageMapper.selectCount(messageWrapper);
+
+            // 查询未读通知数量
+            LambdaQueryWrapper<LifeNotice> noticeWrapper = new LambdaQueryWrapper<>();
+            noticeWrapper.eq(LifeNotice::getReceiverId, receiverId);
+            noticeWrapper.eq(LifeNotice::getIsRead, 0);
+            int noReadNoticeCount = lifeNoticeMapper.selectCount(noticeWrapper);
+
+            return noReadMessageCount + noReadNoticeCount;
+        } catch (Exception e) {
+            log.error("LifeMessageServiceImpl.getAllNoReadCount Error Mgs={}", e.getMessage());
+            throw new Exception(e);
+        }
     }
+
 }

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

@@ -417,7 +417,7 @@ public class StoreCommentServiceImpl extends ServiceImpl<StoreCommentMapper, Sto
             storeComment.setEvaluationTags(evaluationTags);
             storeComment.setPhoneId(phoneId);
             List<String> fileNameSet = new ArrayList<>(multipartRequest.getMultiFileMap().keySet());
-            if (!fileNameSet.isEmpty()) {
+            if (!fileNameSet.isEmpty() && storeId != null) {
                 StringBuilder imgId = new StringBuilder();
                 for (int i = 0; i < fileNameSet.size(); i++) {
                     MultipartFile multipartFile = multipartRequest.getFileMap().get(fileNameSet.get(i));

+ 19 - 12
alien-store/src/main/java/shop/alien/store/service/impl/StoreInfoServiceImpl.java

@@ -5,6 +5,7 @@ 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;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -691,19 +692,25 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
     }
 
     @Override
-    public void deleteStoreInfo(StoreInfoDto storeInfoDto) {
-        //判断是否修改变更过的用户账户
-        StoreUser storeUser = storeUserMapper
-                .selectOne(new LambdaQueryWrapper<StoreUser>().eq(StoreUser::getStoreId, storeInfoDto.getId()));
-        if (storeUser != null) {
-            LambdaUpdateWrapper<StoreUser> storeUserLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
-            storeUserLambdaUpdateWrapper.set(StoreUser::getStoreId, null)
-                    .eq(StoreUser::getId, storeUser.getId());
-            storeUserMapper.update(null, storeUserLambdaUpdateWrapper);
+    public String deleteStoreInfo(StoreInfoDto storeInfoDto) {
+        //判断是否有未完成的订单
+        List<LifeUserOrder> lifeUserOrders = lifeUserOrderMapper.selectList(new LambdaQueryWrapper<LifeUserOrder>().in(LifeUserOrder::getStatus, 0, 3));
+        if (ObjectUtils.isNotEmpty(lifeUserOrders)) {
+            return "您有暂未完成的订单无法删除店铺,请在完成后删除";
+        }else {
+            //判断是否修改变更过的用户账户
+            StoreUser storeUser = storeUserMapper
+                    .selectOne(new LambdaQueryWrapper<StoreUser>().eq(StoreUser::getStoreId, storeInfoDto.getId()));
+            if (storeUser != null) {
+                LambdaUpdateWrapper<StoreUser> storeUserLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
+                storeUserLambdaUpdateWrapper.set(StoreUser::getStoreId, null)
+                        .eq(StoreUser::getId, storeUser.getId());
+                storeUserMapper.update(null, storeUserLambdaUpdateWrapper);
+            }
+            //删除商铺信息
+            storeInfoMapper.deleteById(storeInfoDto.getId());
+            return "成功";
         }
-        //删除商铺信息
-        storeInfoMapper.deleteById(storeInfoDto.getId());
-
     }
 
     @Override

+ 244 - 27
alien-store/src/main/java/shop/alien/store/service/impl/StoreUserServiceImpl.java

@@ -2,12 +2,15 @@ package shop.alien.store.service.impl;
 
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.tuple.Triple;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Value;
@@ -27,8 +30,9 @@ import shop.alien.util.common.DateUtils;
 import shop.alien.util.common.JwtUtil;
 
 import java.io.IOException;
-import java.time.Instant;
-import java.time.ZoneId;
+import java.text.SimpleDateFormat;
+import java.time.*;
+
 import java.time.format.DateTimeFormatter;
 import java.util.*;
 
@@ -38,6 +42,7 @@ import java.util.*;
  * @author ssk
  * @since 2024-12-11
  */
+@Slf4j
 @Transactional
 @Service
 @RequiredArgsConstructor
@@ -81,18 +86,30 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
      * @return StoreUser
      */
     @Override
-    public StoreUser getUserByPhone(String phone) {
+    public StoreUserVo getUserByPhone(String phone) {
         LambdaQueryWrapper<StoreUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
         lambdaQueryWrapper.eq(StoreUser::getPhone, phone);
         StoreUser user = this.getOne(lambdaQueryWrapper);
-        if (null == user) return new StoreUser();
+        StoreUserVo storeUserVo = new StoreUserVo();
+        if(user.getStatus() == -1){
+            LocalDateTime localDateTime = user.getLogoutTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
+            LocalDateTime future = localDateTime.plusDays(7);
+            LocalDateTime now = LocalDateTime.now();
+            Duration duration = Duration.between(now, future);
+            long correct = duration.toMillis();
+            storeUserVo.setCountdown(correct);
+        }
+
+        if (null == user) return new StoreUserVo();
         LambdaQueryWrapper<StoreInfo> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(StoreInfo::getId, user.getStoreId());
         StoreInfo info = storeInfoMapper.selectOne(wrapper);
         if (null != info) user.setName(info.getStoreName());
-        return user;
+        BeanUtils.copyProperties(user, storeUserVo);
+        return storeUserVo;
     }
 
+
     /**
      * token
      *
@@ -176,20 +193,139 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
         return this.updateById(storeUser);
     }
 
+    @Override
+    public boolean forgetOrModifyPassword(String phone, String newPhone, String oldPassword, String newPassword, String confirmNewPassword, String verificationCode, Integer type) {
+        boolean flag = false;
+        //类型为0 忘记密码
+        if (type == 0) {
+            forgetPassword(phone, newPassword, verificationCode);
+        }
+        //修改密码
+        else if (type == 1) {
+            //效验新密码规则
+            passwordVerification(phone, oldPassword, newPassword, confirmNewPassword);
+            LambdaUpdateWrapper<StoreUser> updateWrapper = new LambdaUpdateWrapper<>();
+            updateWrapper.eq(StoreUser::getPhone, phone);
+            updateWrapper.set(StoreUser::getPassword, newPassword);
+            flag = this.update(updateWrapper);
+
+            //修改成功后同步删除redis缓存token
+            if (flag) {
+                String token = "store_" + phone;
+                baseRedisService.delete(token);
+            } else {
+                log.error("密码修改失败");
+                throw new RuntimeException("密码修改失败");
+            }
+            return flag;
+        }
+        //更换绑定手机号
+        else if (type == 2) {
+            ChangeBoundPhone(phone, newPhone, verificationCode);
+        }
+        return flag;
+    }
+
+    private void passwordVerification(String phone, String password, String newPassword, String confirmNewPassword) {
+        LambdaUpdateWrapper<StoreUser> wrapperFans = new LambdaUpdateWrapper<>();
+        wrapperFans.eq(StoreUser::getPhone, phone);
+        StoreUser storeUser = this.getOne(wrapperFans);
+        if (storeUser == null || storeUser.equals("")) {
+            log.info("该手机号没有注册过账户");
+            throw new RuntimeException("该手机号没有注册过账户");
+        } else {
+            wrapperFans.eq(StoreUser::getPassword, password);
+            StoreUser storeUserPw = this.getOne(wrapperFans);
+            if (storeUserPw == null || storeUserPw.getPassword().equals("")) {
+                log.info("密码输入错误 请重新输入");
+                throw new RuntimeException("密码输入错误 请重新输入");
+            }
+        }
+        if (!newPassword.equals(confirmNewPassword)) {
+            log.info("两次新密码输入不一致 请重新输入");
+            throw new RuntimeException("两次新密码输入不一致 请重新输入");
+        }
+    }
+
+    private boolean forgetPassword(String phone, String newPassword, String verificationCode) {
+        boolean flag = false;
+        String key = "verification_" + phone;
+        String redisVerificationCode = baseRedisService.getString(key);
+        if (!StringUtils.isEmpty(redisVerificationCode) && redisVerificationCode.equals(verificationCode)) {
+            LambdaUpdateWrapper<StoreUser> updateWrapper = new LambdaUpdateWrapper<>();
+            updateWrapper.eq(StoreUser::getPhone, phone);
+            updateWrapper.set(StoreUser::getPassword, newPassword);
+            flag = this.update(updateWrapper);
+            if (flag) {
+                log.info("密码修改成功");
+                String token = "store_" + phone;
+                baseRedisService.delete(token);
+            }
+            if (!flag) {
+                log.error("密码修改失败");
+                throw new RuntimeException("密码修改失败");
+            }
+            return flag;
+        } else {
+            throw new RuntimeException("验证码错误");
+        }
+    }
+
+    private boolean ChangeBoundPhone(String phone, String newPhone, String verificationCode) {
+        boolean flag = false;
+        String key = "verification_" + phone;
+        String redisVerificationCode = baseRedisService.getString(key);
+        if (!StringUtils.isEmpty(redisVerificationCode) && redisVerificationCode.equals(verificationCode)) {
+            LambdaUpdateWrapper<StoreUser> storeUserWrapper = new LambdaUpdateWrapper<>();
+            storeUserWrapper.eq(StoreUser::getPhone, phone);
+            StoreUser storeUser = this.getOne(storeUserWrapper);
+            if (storeUser != null) {
+                storeUser.setPhone(newPhone);
+                flag = this.updateById(storeUser);
+            }
+            if (flag) {
+                log.info("新手机号绑定成功");
+                String token = "store_" + phone;
+                baseRedisService.delete(token);
+            }
+            if (!flag) {
+                log.error("手机号更换绑定失败");
+                throw new RuntimeException("手机号更换绑定失败");
+            }
+            return flag;
+        } else {
+            throw new RuntimeException("验证码错误");
+        }
+    }
+
     /**
      * 设置用户信息
-     *
-     * @param id     主键
-     * @param name   姓名
-     * @param idCard 身份证号
      * @return boolean
      */
     @Override
-    public boolean setUserInfo(Integer id, String name, String idCard) {
+    public boolean setUserInfo(StoreUser storeUserParam) {
         StoreUser storeUser = new StoreUser();
-        storeUser.setId(id);
-        storeUser.setName(name);
-        storeUser.setIdCard(idCard);
+        storeUser.setId(storeUserParam.getId());
+        //昵称
+        if (StringUtils.isNotEmpty(storeUserParam.getNickName())) {
+            storeUser.setNickName(storeUserParam.getNickName());
+        }
+        //身份证号
+        if (StringUtils.isNotEmpty(storeUserParam.getIdCard())) {
+            storeUser.setIdCard(storeUserParam.getIdCard());
+        }
+        //姓名
+        if (StringUtils.isNotEmpty(storeUserParam.getName())) {
+            storeUser.setName(storeUserParam.getName());
+        }
+        //账号简介
+        if (StringUtils.isNotEmpty(storeUserParam.getAccountBlurb())) {
+            storeUser.setAccountBlurb(storeUserParam.getAccountBlurb());
+        }
+        //头像
+        if (StringUtils.isNotEmpty(storeUserParam.getHeadImg())) {
+            storeUser.setHeadImg(storeUserParam.getHeadImg());
+        }
         return this.updateById(storeUser);
     }
 
@@ -262,10 +398,19 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
     }
 
     @Override
-    public void deleteStoreUser(String id) {
+    public R<StoreUserVo> deleteStoreUser(String id) {
         StoreUser storeUser = storeUserMapper.selectById(id);
         String phone = storeUser.getPhone();
         Integer storeId = storeUser.getStoreId();
+
+        // 判断该账号是否关联店铺
+        if (ObjectUtils.isNotEmpty(storeId)) {
+            List<StoreInfo> storeInfos = storeInfoMapper.selectList(new LambdaQueryWrapper<StoreInfo>().eq(StoreInfo::getId, storeId).eq(StoreInfo::getDeleteFlag, 0).eq(StoreInfo::getLogoutFlag, 0));
+            if (ObjectUtils.isNotEmpty(storeInfos)) {
+                return R.fail("请删除店铺后再删除账号");
+            }
+        }
+
         storeUserMapper.deleteById(id);
         //删除用户redis中的token
         baseRedisService.delete("store_" + storeUser.getPhone());
@@ -283,6 +428,8 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
         lifeMessageMapper.delete(new LambdaQueryWrapper<LifeMessage>().eq(LifeMessage::getSenderId, "store_" + phone));
         //删除该账号的接受消息信息
         lifeMessageMapper.delete(new LambdaQueryWrapper<LifeMessage>().eq(LifeMessage::getReceiverId, "store_" + phone));
+
+        return R.success("删除成功");
     }
 
     @Override
@@ -379,6 +526,34 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
 
     }
 
+    @Override
+    public Map<String, String> storeCancelAccountVerification(StoreUserVo storeUserVo) {
+        // 通过id获取当前商家账号信息
+        LambdaQueryWrapper<StoreUser> storeUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
+        storeUserLambdaQueryWrapper.eq(StoreUser::getId, storeUserVo.getId());
+        StoreUser storeUser = storeUserMapper.selectOne(storeUserLambdaQueryWrapper);
+        Map<String, String> storeMap = new HashMap<>();
+        if (storeUser != null) {
+            if (null != storeUser.getStoreId()) {
+                StoreInfo storeInfo = storeInfoMapper.selectById(storeUser.getStoreId());
+                if (1 != storeInfo.getLogoutFlag()) {
+                    //vaule为0代表有商铺未注销
+                    storeMap.put("accountStore", "0");
+                } else {
+                    //vaule为1代表可注销
+                    storeMap.put("accountStore", "1");
+                }
+            } else if (storeUser.getMoney() != null && storeUser.getMoney() > 0) {
+                //vaule为0代表有未体现的现金
+                storeMap.put("accountMoney", "0");
+            } else {
+                //vaule为1代表没有未体现的现金
+                storeMap.put("accountMoney", "1");
+            }
+        }
+        return storeMap;
+    }
+
 
     /**
      * @param phone
@@ -431,19 +606,28 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
         storeUserLambdaQueryWrapper.eq(StoreUser::getId, storeUserVo.getId());
         StoreUser storeUser = storeUserMapper.selectOne(storeUserLambdaQueryWrapper);
         if (storeUser != null) {
-            if (null != storeUser.getStoreId()) {
-                StoreInfo storeInfo = storeInfoMapper.selectById(storeUser.getStoreId());
-                if (1 != storeInfo.getLogoutFlag()) {
-                    throw new RuntimeException("请先注销店铺再进行注销用户操作!");
-                }
+                // 添加注销原因
+                storeUser.setLogoutReason(storeUserVo.getLogoutReason());
+                // 添加注销code
+                storeUser.setLogoutCode(storeUserVo.getLogoutCode());
+                // 注销中状态
+                storeUser.setStatus(-1);
+                // 添加注销申请时间
+                storeUser.setLogoutTime(new Date());
+                int num = storeUserMapper.updateById(storeUser);
+                if (num > 0) {
+                    // 发送通知
+                    LifeNotice lifeMessage = new LifeNotice();
+                    lifeMessage.setReceiverId("user_" + storeUser.getPhone());
+                    String text = "您提交的账号注销申请已成功提交, 系统将按流程进行处理. 注销申请提交后, 将进入7天的冷静期. 期间您可以随时在" +
+                            "[账号信息]撤回申请. 冷静期结束后, 系统将正式开始注销操作. 账号内所有数据(包括但不限于个人信息、 资产等) 将被永久清除, 且无法恢复." +
+                            "如有疑问, 可联系【客服】咨询. 感谢您使用我们的服务.";
+                    lifeMessage.setContext(text);
+                    lifeMessage.setSenderId("system");
+                    lifeMessage.setIsRead(0);
+                    lifeMessage.setNoticeType(1);
+                    lifeNoticeMapper.insert(lifeMessage);
             }
-            // 修改注销标记为1
-            storeUser.setLogoutFlag(1);
-            // 添加注销原因
-            storeUser.setLogoutReason(storeUserVo.getLogoutReason());
-            // 添加注销申请时间
-            storeUser.setLogoutTime(new Date());
-            storeUserMapper.updateById(storeUser);
         }
     }
 
@@ -455,11 +639,44 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
         StoreUser storeUser = storeUserMapper.selectOne(storeUserLambdaQueryWrapper);
         // 修改注销标记为0
         storeUser.setLogoutFlag(0);
+        // 注销状态变为可用
+        storeUser.setStatus(0);
         // 清空注销原因
         storeUser.setLogoutReason(null);
         // 清空注销申请时间
         storeUser.setLogoutTime(null);
-        storeUserMapper.updateById(storeUser);
+        int num = storeUserMapper.updateById(storeUser);
+            if (num > 0) {
+                // 发送通知
+                LifeNotice lifeMessage = new LifeNotice();
+                lifeMessage.setReceiverId("user_" + storeUser.getPhone());
+                String text = "处理结果:已撤回注销申请" +
+                        "处理时间:"+ storeUser.getCreatedTime() +
+                        "当前账号状态以为恢复正常. 您可以继续使用该账号登录并享受各项服务, 所有个人数据及账户信息" +
+                        "均已妥善保留. 若您后续仍有注销需求, 可随时通过账号信息页面重新提交申请. 感谢您的理解与支持!";
+                lifeMessage.setContext(text);
+                lifeMessage.setSenderId("system");
+                lifeMessage.setIsRead(0);
+                lifeMessage.setNoticeType(1);
+                lifeNoticeMapper.insert(lifeMessage);
+            }
+    }
+
+    @Override
+    public void deleteStoreAccountInfo(StoreUserVo storeUserVo) {
+        LambdaQueryWrapper<StoreUser> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(StoreUser::getId, storeUserVo.getId());
+        StoreUser storeUser = storeUserMapper.selectOne(queryWrapper);
+        // 删除已过注销时间的商家
+        storeUserMapper.deleteById(storeUserVo.getId());
+        //删除用户redis中的token
+        baseRedisService.delete("store_" + storeUserVo.getPhone());
+        LambdaQueryWrapper<LifeFans> lifeFansLambdaQueryWrapper = new LambdaQueryWrapper<LifeFans>().eq(LifeFans::getFollowedId, "store_" + storeUser.getPhone())
+                .or().eq(LifeFans::getFansId, "store_" + storeUser.getPhone());
+        lifeFansMapper.delete(lifeFansLambdaQueryWrapper);
+        if(storeUser.getStoreId()!=null){
+            storeInfoMapper.deleteById(storeUser.getStoreId());
+        }
     }
 
     @Override

+ 4 - 0
alien-store/src/main/java/shop/alien/store/util/ali/AliSms.java

@@ -9,6 +9,7 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
+import shop.alien.store.config.BaseRedisService;
 import shop.alien.util.common.RandomCreateUtil;
 
 import java.util.Arrays;
@@ -25,6 +26,7 @@ import java.util.List;
 @Component
 @RequiredArgsConstructor
 public class AliSms {
+    private final BaseRedisService baseRedisService;
 
     @Value("${ali.sms.accessKeyId}")
     private String accessKeyId;
@@ -82,6 +84,8 @@ public class AliSms {
             if (!"OK".equals(sendSmsResponse.getBody().getCode())) {
                 return null;
             }
+            // 验证码发送成功,将验证码保存到redis中 设置60秒过期
+            baseRedisService.setString("verification_"+phone,code.toString(),Long.valueOf(60));
             return code;
         } catch (Exception e) {
             log.error("AliSmsConfig.sendSms ERROR Msg={}", e.getMessage());

+ 44 - 0
alien-util/src/main/java/shop/alien/util/common/safe/DeepseekClient.java

@@ -0,0 +1,44 @@
+package shop.alien.util.common.safe;
+
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import okhttp3.*;
+
+import java.io.IOException;
+
+public class DeepseekClient {
+    private final String apiKey;
+    private final OkHttpClient client;
+
+    public DeepseekClient(String apiKey) {
+        this.apiKey = apiKey;
+        this.client = new OkHttpClient();
+    }
+
+    public String generateText(String prompt) throws IOException {
+        // 创建请求体
+        JSONObject messages = new JSONObject();
+        messages.put("role", "user");
+        messages.put("content", prompt);
+
+        JSONObject requestBody = new JSONObject();
+        requestBody.put("model", "deepseek-chat");
+        requestBody.put("messages", JSON.parseArray(messages.toJSONString(), Object.class));
+        requestBody.put("stream", false);
+
+        Request request = new Request.Builder()
+                .url("https://api.deepseek.com/chat/completions")
+                .post(RequestBody.create(MediaType.get("application/json"), requestBody.toJSONString()))
+                .addHeader("Content-Type", "application/json")
+                .addHeader("Authorization", "Bearer " + apiKey)
+                .build();
+
+        try (Response response = client.newCall(request).execute()) {
+            if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
+
+            JSONObject responseBody = JSON.parseObject(response.body().string());
+            return responseBody.getJSONArray("choices").getJSONObject(0).getJSONObject("message").getString("content");
+        }
+    }
+}

+ 18 - 0
alien-util/src/main/java/shop/alien/util/common/safe/ImageModerationResultVO.java

@@ -0,0 +1,18 @@
+package shop.alien.util.common.safe;
+
+import lombok.Data;
+
+/**
+ * 图片审核结果返回值对象
+ */
+@Data
+public class ImageModerationResultVO {
+    // 风险等级
+    private String riskLevel;
+    // 细分标签
+    private String labels;
+    // 细分标签描述
+    private String descriptions;
+    // 生成的商品文案
+    private String generatedText;
+}

+ 112 - 29
alien-util/src/main/java/shop/alien/util/common/safe/ImageModerationUtil.java

@@ -1,5 +1,6 @@
 package shop.alien.util.common.safe;
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
 import com.aliyun.green20220302.Client;
 import com.aliyun.green20220302.models.ImageBatchModerationResponse;
 import com.aliyun.green20220302.models.ImageModerationRequest;
@@ -10,18 +11,22 @@ import com.aliyun.green20220302.models.ImageBatchModerationResponseBody;
 import com.aliyun.green20220302.models.ImageModerationResponseBody;
 import com.aliyun.green20220302.models.ImageModerationResponseBody.ImageModerationResponseBodyData;
 import com.aliyun.green20220302.models.ImageModerationResponseBody.ImageModerationResponseBodyDataResult;
+
 import com.aliyun.teaopenapi.models.Config;
 import com.aliyun.teautil.models.RuntimeOptions;
+import com.google.common.collect.Lists;
 import jdk.nashorn.internal.runtime.logging.Logger;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
 
+import java.io.IOException;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
 @Logger
+@Component
 public class ImageModerationUtil {
 
     @Value("${ali.yundun.accessKeyID}")
@@ -40,6 +45,8 @@ public class ImageModerationUtil {
      */
     public Client createClient() throws Exception {
         Config config = new Config();
+//        config.setAccessKeyId("LTAI5tReZWshffH78oQJPzZG");
+//        config.setAccessKeySecret("Gi30OLYAWunaDbwsv5qqdZ3PzbDyGP");
         config.setAccessKeyId(accessKeyId);
         config.setAccessKeySecret(accessKeySecret);
         // 设置http代理。
@@ -48,6 +55,7 @@ public class ImageModerationUtil {
         //config.setHttpsProxy("https://10.10.xx.xx:xxxx");
         // 接入区域和地址请根据实际情况修改
         // 接入地址列表:https://help.aliyun.com/document_detail/467828.html?#section-uib-qkw-0c8
+//        config.setEndpoint("green-cip.cn-shanghai.aliyuncs.com");
         config.setEndpoint(ImgEndpoint);
         return new Client(config);
     }
@@ -119,38 +127,83 @@ public class ImageModerationUtil {
      * 顺序调用内容治理检测、AIGC图片风险检测、图片万物识别
      *
      * @param imageUrl 图片地址
-     * @return 检测结果
+     * @return 检测结果VO
      * @throws Exception 检测异常
      */
-    public ImageBatchModerationResponse productPublishCheck(String imageUrl) throws Exception {
-
+    public ImageModerationResultVO productPublishCheck(String imageUrl) throws Exception {
+        ImageModerationResultVO resultVO = new ImageModerationResultVO();
         // 批量服务key
-        String serviceEnum = ImageReviewServiceEnum.TONALITY_IMPROVE.getService() + "," + ImageReviewServiceEnum.AIGC_CHECK.getService() + "," + ImageReviewServiceEnum.GENERAL_RECOGNITION.getService();
+        StringBuilder serviceBatchEnum = new StringBuilder();
+        StringBuilder serviceEnum = new StringBuilder();
+        List<String> servicesList = Lists.newArrayList();
+        // TODO 后续配置到数据库 中
+        servicesList.add(ImageReviewServiceEnum.TONALITY_IMPROVE.getService());
+        servicesList.add(ImageReviewServiceEnum.AIGC_CHECK.getService());
+        for (String service : servicesList){
+            if (isSpecialService(service)){
+                serviceBatchEnum.append(service).append(",");
+            }else {
+                serviceEnum.append(service).append(",");
+            }
+        }
+        // 若存在特殊服务,则拼接字符串  并调取多service阿里图片审核服务
+        if (serviceBatchEnum.length() > 0) {
+            serviceBatchEnum.setLength(serviceBatchEnum.length() - 1);
+            // 多service图片审核
+            resultVO = getImageModerationResultVO(imageUrl, serviceBatchEnum);
+        }
+        // TODO 现阶段使用的服务都支持多service 图片审核,后续如果有不支持的服务则 融合 使用单service图片审核
 
-        // 批量图片检测
-        ImageBatchModerationResponse response = invokeBeachFunction(imageUrl,serviceEnum);
-        if (response != null) {
-            if (response.getStatusCode() == 200) {
-                ImageBatchModerationResponseBody body = response.getBody();
-                System.out.println("requestId=" + body.getRequestId());
-                System.out.println("code=" + body.getCode());
-                System.out.println("msg=" + body.getMsg());
-                if (body.getCode() == 200) {
-                    ImageBatchModerationResponseBody.ImageBatchModerationResponseBodyData data = body.getData();
-                    System.out.println("dataId=" + data.getDataId());
+
+        return resultVO;
+    }
+
+    private ImageModerationResultVO getImageModerationResultVO(String imageUrl, StringBuilder serviceEnum) throws Exception {
+        // 多service图片审核
+        ImageBatchModerationResponse response = invokeBeachFunction(imageUrl, serviceEnum.toString());
+        ImageModerationResultVO resultVO = new ImageModerationResultVO();
+
+        if (response != null && response.getStatusCode() == 200) {
+            ImageBatchModerationResponseBody body = response.getBody();
+            if (body != null && body.getCode() == 200) {
+                ImageBatchModerationResponseBody.ImageBatchModerationResponseBodyData data = body.getData();
+                if (data != null) {
+                    String riskLevel = data.getRiskLevel();
                     List<ImageBatchModerationResponseBody.ImageBatchModerationResponseBodyDataResult> results = data.getResult();
-                    for (ImageBatchModerationResponseBody.ImageBatchModerationResponseBodyDataResult result : results) {
-                        System.out.println("label=" + result.getLabel());
-                        System.out.println("confidence=" + result.getConfidence());
+                    StringBuilder labelsBuilder = new StringBuilder();
+                    StringBuilder descriptionsBuilder = new StringBuilder();
+                    // 处理结果 多个服务总敏感程度
+                    if ("high".equals(riskLevel)) {
+                        for (ImageBatchModerationResponseBody.ImageBatchModerationResponseBodyDataResult result : results) {
+                            // 触发多个,如果置信分高于80 则拼接描述
+                            if (result.getConfidence() > 80 ) {
+                                String label = result.getLabel();
+                                String description = result.getDescription();
+                                // 拼接标签
+                                if (label != null && !label.isEmpty()) {
+                                    labelsBuilder.append(label).append(",");
+                                }
+                                // 拼接描述
+                                if (description != null && !description.isEmpty()) {
+                                    descriptionsBuilder.append(description).append(",");
+                                }
+                            }
+                        }
+                    }
+                    // 移除最后一个逗号
+                    if (labelsBuilder.length() > 0) {
+                        labelsBuilder.setLength(labelsBuilder.length() - 1);
                     }
-                } else {
-                    System.out.println("image moderation not success. code:" + body.getCode());
+                    if (descriptionsBuilder.length() > 0) {
+                        descriptionsBuilder.setLength(descriptionsBuilder.length() - 1);
+                    }
+                    resultVO.setRiskLevel(riskLevel);
+                    resultVO.setLabels(labelsBuilder.toString());
+                    resultVO.setDescriptions(descriptionsBuilder.toString());
                 }
-            } else {
-                System.out.println("response not success. status:" + response.getStatusCode());
             }
         }
-        return response;
+        return resultVO;
     }
 
     /**
@@ -161,13 +214,43 @@ public class ImageModerationUtil {
      * @return 检测结果
      * @throws Exception 检测异常
      */
-    public ImageBatchModerationResponse chatCheck(String imageUrl) throws Exception {
-        // 批量服务key
-        String serviceEnum = ImageReviewServiceEnum.GENERAL_RECOGNITION.getService() + "," + ImageReviewServiceEnum.TONALITY_IMPROVE.getService();
-
+    public ImageModerationResultVO chatCheck(String imageUrl) throws Exception {
         // 批量图片检测
-        ImageBatchModerationResponse response = invokeBeachFunction(imageUrl,serviceEnum);
+        ImageModerationResponse response = invokeFunction(imageUrl, "generalRecognition");
+        ImageModerationResultVO resultVO = new ImageModerationResultVO();
+        ImageModerationResponseBody body = response.body;
+        ImageModerationResponseBody.ImageModerationResponseBodyDataExt dataExt = body.data.ext;
+        // 调用DeepSeek接口生成商品文案
+        String prompt = "根据以下标签生成一个吸引人的商品售卖文案(200字以内): " + dataExt;
+        String generatedText = callDeepSeekAPI(prompt);
+        resultVO.setGeneratedText(generatedText);
+        return resultVO;
+    }
 
-        return response;
+    /**
+     * 调用DeepSeek接口生成商品文案
+     * @param prompt 提示信息
+     * @return 生成的文案
+     * @throws IOException 调用异常
+     */
+    private String callDeepSeekAPI(String prompt) throws IOException {
+        DeepseekClient client = new DeepseekClient("sk-dd8a6e10972145c9847883791ac9fb41");
+        return client.generateText(prompt);
+    }
+
+    /**
+     * 判断服务是否为特殊服务,若是可以调取阿里多service审核服务,返回多个场景的总审核结果
+     * @param service 服务名称
+     * @return 是否为特殊服务
+     */
+    public static boolean isSpecialService(String service) {
+        return ImageReviewServiceEnum.BASELINE_CHECK.getService().equals(service)
+                || ImageReviewServiceEnum.BASELINE_CHECK_PRO.getService().equals(service)
+                || ImageReviewServiceEnum.TONALITY_IMPROVE.getService().equals(service)
+                || ImageReviewServiceEnum.AIGC_CHECK.getService().equals(service)
+                || ImageReviewServiceEnum.PROFILE_PHOTO_CHECK.getService().equals(service)
+                || ImageReviewServiceEnum.POST_IMAGE_CHECK.getService().equals(service)
+                || ImageReviewServiceEnum.ADVERTISING_CHECK.getService().equals(service)
+                || ImageReviewServiceEnum.LIVE_STREAM_CHECK.getService().equals(service);
     }
 }

+ 1 - 0
alien-util/src/main/java/shop/alien/util/common/safe/ImageReviewServiceEnum.java

@@ -38,6 +38,7 @@ public enum ImageReviewServiceEnum {
         this.serviceScene = serviceScene;
     }
 
+
     public String getService() {
         return service;
     }

+ 120 - 0
alien-util/src/main/java/shop/alien/util/common/safe/ImageUrlDemo.java

@@ -0,0 +1,120 @@
+package shop.alien.util.common.safe;
+import com.alibaba.fastjson.JSON;
+import com.aliyun.green20220302.Client;
+import com.aliyun.green20220302.models.ImageModerationRequest;
+import com.aliyun.green20220302.models.ImageModerationResponse;
+import com.aliyun.green20220302.models.ImageModerationResponseBody;
+import com.aliyun.green20220302.models.ImageModerationResponseBody.ImageModerationResponseBodyData;
+import com.aliyun.green20220302.models.ImageModerationResponseBody.ImageModerationResponseBodyDataResult;
+import com.aliyun.teaopenapi.models.Config;
+import com.aliyun.teautil.models.RuntimeOptions;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+public class ImageUrlDemo {
+    /**
+     * 创建请求客户端
+     *
+     * @param accessKeyId
+     * @param accessKeySecret
+     * @param endpoint
+     * @return
+     * @throws Exception
+     */
+    public static Client createClient(String accessKeyId, String accessKeySecret, String endpoint) throws Exception {
+        Config config = new Config();
+        config.setAccessKeyId(accessKeyId);
+        config.setAccessKeySecret(accessKeySecret);
+        // 设置http代理。
+        //config.setHttpProxy("http://10.10.xx.xx:xxxx");
+        // 设置https代理。
+        //config.setHttpsProxy("https://10.10.xx.xx:xxxx");
+        // 接入区域和地址请根据实际情况修改
+        // 接入地址列表:https://help.aliyun.com/document_detail/467828.html?#section-uib-qkw-0c8
+        config.setEndpoint(endpoint);
+        return new Client(config);
+    }
+
+    public static ImageModerationResponse invokeFunction(String accessKeyId, String accessKeySecret, String endpoint) throws Exception {
+        //注意,此处实例化的client请尽可能重复使用,避免重复建立连接,提升检测性能。
+        Client client = createClient(accessKeyId, accessKeySecret, endpoint);
+
+        // 创建RuntimeObject实例并设置运行参数
+        RuntimeOptions runtime = new RuntimeOptions();
+
+        // 检测参数构造。
+        Map<String, String> serviceParameters = new HashMap<>();
+        //公网可访问的URL。
+        serviceParameters.put("imageUrl", "http://devfile.ailien.shop/image/暴恐违禁2367012.jpg");
+        //待检测数据唯一标识
+        serviceParameters.put("dataId", UUID.randomUUID().toString());
+
+        ImageModerationRequest request = new ImageModerationRequest();
+        // 图片检测service:内容安全控制台图片增强版规则配置的serviceCode,示例:baselineCheck
+        // 支持service请参考:https://help.aliyun.com/document_detail/467826.html?0#p-23b-o19-gff
+        request.setService("generalRecognition");
+        request.setServiceParameters(JSON.toJSONString(serviceParameters));
+
+        ImageModerationResponse response = null;
+        try {
+            response = client.imageModerationWithOptions(request, runtime);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return response;
+    }
+
+    public static void main(String[] args) throws Exception {
+        /**
+         * 阿里云账号AccessKey拥有所有API的访问权限,建议您使用RAM用户进行API访问或日常运维。
+         * 常见获取环境变量方式:
+         * 方式一:
+         *     获取RAM用户AccessKey ID:System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
+         *     获取RAM用户AccessKey Secret:System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
+         * 方式二:
+         *     获取RAM用户AccessKey ID:System.getProperty("ALIBABA_CLOUD_ACCESS_KEY_ID");
+         *     获取RAM用户AccessKey Secret:System.getProperty("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
+         */
+        String accessKeyId = "LTAI5tReZWshffH78oQJPzZG";
+        String accessKeySecret = "Gi30OLYAWunaDbwsv5qqdZ3PzbDyGP";
+        // 接入区域和地址请根据实际情况修改。
+        ImageModerationResponse response = invokeFunction(accessKeyId, accessKeySecret, "green-cip.cn-shanghai.aliyuncs.com");
+        try {
+            // 自动路由。
+            if (response != null) {
+                //区域切换到cn-beijing。
+                if (500 == response.getStatusCode() || (response.getBody() != null && 500 == (response.getBody().getCode()))) {
+                    // 接入区域和地址请根据实际情况修改。
+                    response = invokeFunction(accessKeyId, accessKeySecret, "green-cip.cn-beijing.aliyuncs.com");
+                }
+            }
+            // 打印检测结果。
+            if (response != null) {
+                if (response.getStatusCode() == 200) {
+                    ImageModerationResponseBody body = response.getBody();
+                    System.out.println("requestId=" + body.getRequestId());
+                    System.out.println("code=" + body.getCode());
+                    System.out.println("msg=" + body.getMsg());
+                    if (body.getCode() == 200) {
+                        ImageModerationResponseBodyData data = body.getData();
+                        System.out.println("dataId=" + data.getDataId());
+                        List<ImageModerationResponseBodyDataResult> results = data.getResult();
+                        for (ImageModerationResponseBodyDataResult result : results) {
+                            System.out.println("label=" + result.getLabel());
+                            System.out.println("confidence=" + result.getConfidence());
+                        }
+                    } else {
+                        System.out.println("image moderation not success. code:" + body.getCode());
+                    }
+                } else {
+                    System.out.println("response not success. status:" + response.getStatusCode());
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 0 - 10
alien-util/src/main/java/shop/alien/util/common/safe/TextModerationResultVO.java

@@ -7,17 +7,7 @@ import lombok.Data;
  */
 @Data
 public class TextModerationResultVO {
-    private Integer code;
-    private String message;
-    
-    // 以下字段对应原始data对象中的属性
-    private String labels; // 标签
-    private String reason; // 原因(JSON字符串)
-
     // 扁平化的风险信息字段
     private String riskLevel; // 风险等级
-    private String riskTips; // 细分标签
     private String riskWords; // 命中风险内容
-    private String customizedWords; // 命中用户词
-    private String customizedLibs; // 命中用户词库名
 }

+ 189 - 87
alien-util/src/main/java/shop/alien/util/common/safe/TextModerationUtil.java

@@ -1,14 +1,21 @@
 package shop.alien.util.common.safe;
+import cn.hutool.core.collection.CollectionUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.aliyun.green20220302.Client;
-import com.aliyun.green20220302.models.ImageModerationResponse;
-import com.aliyun.green20220302.models.TextModerationPlusRequest;
-import com.aliyun.green20220302.models.TextModerationPlusResponse;
-import com.aliyun.green20220302.models.TextModerationPlusResponseBody;
+import com.aliyun.green20220302.models.*;
 import com.aliyun.teaopenapi.models.Config;
+import com.aliyun.teautil.models.RuntimeOptions;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.google.common.collect.Lists;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
 
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+@Component
 public class TextModerationUtil {
 
 
@@ -50,12 +57,12 @@ public class TextModerationUtil {
     /**
      * 根据业务类型执行文本审核
      * @param text 待审核文本
-     * @param services 文本审核服务枚举
+     * @param servicesList 文本审核服务枚举
      * @return 审核结果VO
      * @throws Exception 调用服务异常
      */
-    public TextModerationResultVO invokeFunction(String text, ImageReviewServiceEnum... services) throws Exception {
-        if (services == null || services.length == 0) {
+    public TextModerationResultVO invokeFunction(String text, List<String> servicesList) throws Exception {
+        if (CollectionUtil.isEmpty(servicesList)) {
             throw new IllegalArgumentException("至少需要一个审核服务");
         }
 
@@ -64,102 +71,185 @@ public class TextModerationUtil {
         TextModerationResultVO resultVO = new TextModerationResultVO();
         
         // 存储风险等级和原因的字符串
-        StringBuilder riskTipsBuilder = new StringBuilder();
         StringBuilder riskWordsBuilder = new StringBuilder();
-        StringBuilder customizedWordsBuilder = new StringBuilder();
-        StringBuilder customizedLibsBuilder = new StringBuilder();
-        String highestRiskLevel = "low"; // 默认最低风险等级
+        String highestRiskLevel = "none"; // 默认未检测到风险
         
         try {
-            for (ImageReviewServiceEnum service : services) {
-                TextModerationPlusRequest textModerationPlusRequest = new TextModerationPlusRequest();
-                textModerationPlusRequest.setService(service.getService());
-                
-                // 构建服务参数
-                textModerationPlusRequest.setServiceParameters(buildServiceParameters(text));
-                
-                TextModerationPlusResponse response = client.textModerationPlus(textModerationPlusRequest);
-                if (response.getStatusCode() == 200) {
-                    TextModerationPlusResponseBody result = response.getBody();
-                    
-                    if (200 == result.getCode()) {
-                        // 解析审核结果
-                        TextModerationPlusResponseBody.TextModerationPlusResponseBodyData data = result.getData();
-
-                        // 解析审核结果
-                        JSONObject dataJson = JSON.parseObject(JSON.toJSONString(result.getData()));
-                        String labels = dataJson.getString("labels");
-                        String reason = dataJson.getString("reason");
-
-                        // 解析风险等级和详细信息
-                        JSONObject reasonJson = JSON.parseObject(reason);
-                        String riskLevel = reasonJson.getString("riskLevel");
-                        String riskTip = reasonJson.getString("riskTips");
-                        String riskWord = reasonJson.getString("riskWords");
-                        String customizedWord = reasonJson.getString("customizedWords");
-                        String customizedLib = reasonJson.getString("customizedLibs");
-                        
-                        // 如果存在风险信息,则添加到构建器中
-                        if (riskTip != null && !riskTip.isEmpty()) {
-                            if (riskTipsBuilder.length() > 0) {
-                                riskTipsBuilder.append(", ");
-                            }
-                            riskTipsBuilder.append(riskTip);
-                        }
-                        
-                        if (riskWord != null && !riskWord.isEmpty()) {
-                            if (riskWordsBuilder.length() > 0) {
-                                riskWordsBuilder.append(", ");
-                            }
-                            riskWordsBuilder.append(riskWord);
-                        }
-                        
-                        if (customizedWord != null && !customizedWord.isEmpty()) {
-                            if (customizedWordsBuilder.length() > 0) {
-                                customizedWordsBuilder.append(", ");
-                            }
-                            customizedWordsBuilder.append(customizedWord);
-                        }
-                        
-                        if (customizedLib != null && !customizedLib.isEmpty()) {
-                            if (customizedLibsBuilder.length() > 0) {
-                                customizedLibsBuilder.append(", ");
+            for (String service : servicesList) {
+                // 判断传入参service参数是否包含 chat_detection_pro、ad_compliance_detection_pro、llm_query_moderation、comment_detection_pro、
+                if (isSpecialService(service)) {
+                    // 处理特殊服务
+                    highestRiskLevel = handleSpecialService(text, service, client, riskWordsBuilder, highestRiskLevel);
+                } else {
+                    // 判断service中包含 url_detection ,将文本中的url进行检测 提取url 传入进行检测
+                    if ("url_detection".equals( service )) {
+                        // 写一个文本提取url 的方法
+                        List<String> urls = extractUrls(text);
+                        if (CollectionUtil.isNotEmpty(urls)){
+                            for (String url : urls) {
+                                // 链接调取
+                                highestRiskLevel = processTextModeration(client, url, service, riskWordsBuilder,highestRiskLevel);
                             }
-                            customizedLibsBuilder.append(customizedLib);
                         }
-                        
-                        // 判断风险等级优先级
-                        if (riskLevel != null) {
-                            if (riskLevel.equals("high") && !highestRiskLevel.equals("high")) {
-                                highestRiskLevel = "high";
-                            } else if (riskLevel.equals("medium") && highestRiskLevel.equals("low")) {
-                                highestRiskLevel = "medium";
-                            }
-                        }
-                        
-                        // 设置基础信息
-                        resultVO.setLabels(labels);
+                    }else {
+                        // 文本调取
+                        highestRiskLevel = processTextModeration(client, text, service, riskWordsBuilder,highestRiskLevel);
                     }
                 }
             }
-            
             // 设置结果VO
-            resultVO.setCode(200);
-            resultVO.setMessage("OK");
             resultVO.setRiskLevel(highestRiskLevel);
-            resultVO.setRiskTips(riskTipsBuilder.toString());
             resultVO.setRiskWords(riskWordsBuilder.toString());
-            resultVO.setCustomizedWords(customizedWordsBuilder.toString());
-            resultVO.setCustomizedLibs(customizedLibsBuilder.toString());
-            
         } catch (Exception e) {
-            resultVO.setCode(500);
-            resultVO.setMessage("调用服务失败: " + e.getMessage());
+            throw new RuntimeException("解析失败" + e);
         }
-        
         return resultVO;
     }
 
+    /**
+     * 通用服务调取
+     * @param text 文本
+     * @param service  服务
+     * @param client  客户端
+     * @param riskWordsBuilder 危险词
+     * @param highestRiskLevel 最高危险等级
+     * @throws Exception 错误
+     */
+    private String processTextModeration(Client client, String text, String service, StringBuilder riskWordsBuilder,String highestRiskLevel) throws Exception {
+        // 调用文本检测服务
+        TextModerationResponse response = callTextModeration(client, text, service);
+        if (response != null) {
+            if (response.getStatusCode() == 200) {
+                TextModerationResponseBody result = response.getBody();
+                Integer code = result.getCode();
+                if (code != null && code == 200) {
+                    TextModerationResponseBody.TextModerationResponseBodyData data = result.getData();
+                    String reason = data.getReason();
+                    if (reason != null) {
+                        try {
+                            JSONObject reasonObj = JSON.parseObject(reason);
+                            String riskLevel = reasonObj.getString("riskLevel");
+                            if ("high".equals(riskLevel)) {
+                                highestRiskLevel = riskLevel;
+                                String riskWords = reasonObj.getString("riskWords");
+                                if (riskWords != null && !riskWords.isEmpty()) {
+                                    riskWordsBuilder.append(riskWords).append(",");
+                                }
+                            }
+                        } catch (Exception e) {
+                            // 解析失败,忽略该条原因
+                        }
+                    }
+                }
+            }
+        }
+        return highestRiskLevel;
+    }
+
+    /**
+     * 处理TextModerationPlus服务
+     * @param text 文本
+     * @param service  服务
+     * @param client  客户端
+     * @param riskWordsBuilder 危险词
+     * @param highestRiskLevel 最高危险等级
+     * @throws Exception 错误
+     */
+    private String handleSpecialService(String text, String service, Client client, StringBuilder riskWordsBuilder, String highestRiskLevel) throws Exception {
+        // 调用plus服务并获取响应
+        TextModerationPlusResponse response = callTextModerationPlusService(client, text, service);
+        // 根据response 返回参数处理结果 返回vo所需的参数
+        TextModerationPlusResponseBody body = response.body;
+        TextModerationPlusResponseBody.TextModerationPlusResponseBodyData data = body.getData();
+        if (data != null) {
+            // 分级:riskLevel
+            String riskLevel = data.getRiskLevel();
+            // high:高风险 medium:中风险 low:低风险 none:未检测到风险
+            if ("high".equals(riskLevel)) {
+                highestRiskLevel = riskLevel;
+                List<TextModerationPlusResponseBody.TextModerationPlusResponseBodyDataResult> resultList = data.getResult();
+                for (TextModerationPlusResponseBody.TextModerationPlusResponseBodyDataResult result : resultList) {
+                    // 文字内容检测运算后返回的标签,可能会检出多个标签和分值。
+                    String label = result.getLabel();
+                    // 检测到的敏感词,多个词用逗号分隔,部分标签不会返回敏感词。
+                    String riskWords = result.getRiskWords();
+                    String description = result.getDescription();
+                    if (StringUtils.isNotEmpty(riskWords)){
+                        riskWordsBuilder.append(riskWords).append(",");
+                    }
+                    // 获取 集合 getCustomizedHit 中 所有KeyWords 拼接为字符串并追加到 riskWordsBuilder
+                    if (CollectionUtil.isNotEmpty(result.getCustomizedHit())){
+                        result.getCustomizedHit().forEach(hit -> riskWordsBuilder.append(hit.getKeyWords()).append(","));
+                    }
+                    //置信分值,0到100分,保留到小数点后2位。部分标签无置信分。
+                    Float confidence = result.getConfidence();
+
+                }
+            }
+        }
+        return highestRiskLevel;
+    }
+
+    /**
+     * 调用TextModerationPlus服务
+     * @param text 文本
+     * @param service  服务
+     * @param client  客户端
+     * @return 检测结果
+     * @throws Exception 检测异常
+     */
+    private TextModerationPlusResponse callTextModerationPlusService(Client client, String text, String service) throws Exception {
+        // 包含调取plus服务
+        TextModerationPlusRequest textModerationPlusRequest = new TextModerationPlusRequest();
+        textModerationPlusRequest.setService(service);
+        // 构建服务参数
+        textModerationPlusRequest.setServiceParameters(buildServiceParameters(text));
+        return client.textModerationPlus(textModerationPlusRequest);
+    }
+
+    /**
+     * 调取普通服务
+     * @param text 文本
+     * @param service  服务
+     * @param client  客户端
+     * @return 检测结果
+     * @throws Exception 检测异常
+     */
+    private TextModerationResponse callTextModeration(Client client, String text, String service) throws Exception {
+        // 创建RuntimeObject实例并设置运行参数。
+        RuntimeOptions runtime = new RuntimeOptions();
+        runtime.readTimeout = 10000;
+        runtime.connectTimeout = 10000;
+        //检测参数构造
+        JSONObject serviceParameters = new JSONObject();
+        serviceParameters.put("content", text);
+        // 调取普通服务
+        TextModerationRequest textModerationRequest = new TextModerationRequest();
+        textModerationRequest.setService(service);
+        textModerationRequest.setServiceParameters(serviceParameters.toJSONString());
+        return client.textModerationWithOptions(textModerationRequest, runtime);
+    }
+
+    /**
+     * 提取URL
+     * @param text 文本
+     * @return URL列表
+     */
+    private List<String> extractUrls(String text) {
+        List<String> urls = Lists.newArrayList();
+
+        // 使用改进后的正则表达式匹配URL
+        Pattern urlPattern = Pattern.compile("(https?://\\S+)(:\\d+)?(/\\S*)?");
+
+        Matcher matcher = urlPattern.matcher(text);
+
+        while (matcher.find()) {
+            urls.add(matcher.group());
+        }
+
+        return urls;
+    }
+
 
     private String buildServiceParameters(String text) {
         // 创建服务参数JSON
@@ -167,4 +257,16 @@ public class TextModerationUtil {
         serviceParameters.put("content", text);
         return serviceParameters.toJSONString();
     }
+    /**
+     * 判断服务是否为特殊服务
+     * @param service 服务名称
+     * @return 是否为特殊服务
+     */
+    public static boolean isSpecialService(String service) {
+        return TextReviewServiceEnum.CHAT_DETECTION_PRO.getService().equals(service)
+                || TextReviewServiceEnum.AD_COMPLIANCE_DETECTION_PRO.getService().equals(service)
+                || TextReviewServiceEnum.LLM_QUERY_MODERATION.getService().equals(service)
+                || TextReviewServiceEnum.COMMENT_DETECTION_PRO.getService().equals(service);
+    }
+
 }

+ 45 - 15
alien-util/src/main/java/shop/alien/util/common/safe/TextReviewServiceEnum.java

@@ -1,26 +1,56 @@
 package shop.alien.util.common.safe;
 
-import jdk.nashorn.internal.runtime.logging.Logger;
-import lombok.Getter;
-
 /**
- * @author Alien
- * @date 2021/09/05
+ * @author: alien
+ * @date: 2023/10/31
  */
-@Getter
-@Logger
 public enum TextReviewServiceEnum {
-    SPAM("spam"),
-    AD("ad"),
-    POLITICS("politics"),
-    ABUSE("abuse"),
-    VIOLENCE("violence"),
-    PORNOGRAPHY("pornography");
+    UGC_MODERATION_BY_LLM("ugc_moderation_byllm", "UGC场景文本审核大模型服务", "针对UGC场景,基于大模型能力的文本审核服务,能够高效精准地识别违规内容。", "通用场景"),
+    AIGC_MODERATION_BY_LLM("aigc_moderation_byllm", "AIGC场景文本审核大模型服务", "针对AIGC场景,基于大模型能力的文本审核服务,能够高效精准地识别违规内容。", "AIGC场景"),
+    LLM_QUERY_MODERATION("llm_query_moderation", "大语言模型输入文字检测", "检测大语言模型输入文字中是否存在色情、涉政、暴恐、违禁等红线类的违规内容。", "AIGC场景"),
+    LLM_RESPONSE_MODERATION("llm_response_moderation", "大语言模型生成文字检测", "检测大语言模型生成文字中是否存在色情、涉政、暴恐、违禁等红线类的违规内容。", "AIGC场景"),
+    COMMENT_DETECTION_PRO("comment_detection_pro", "公聊评论内容检测_专业版", "检测公聊评论中是否存在违规、不宜传播或者影响平台秩序的内容。建议对公聊评论场景的文本均进行该项检测。支持更细粒度的标签返回。", "业务场景"),
+    NICKNAME_DETECTION_PRO("nickname_detection_pro", "用户昵称检测_专业版", "检测用户昵称中是否存在违规、不宜传播或者影响平台秩序的内容。建议对用户昵称场景的文本均进行该项检测。支持更细粒度的标签返回。", "业务场景"),
+    CHAT_DETECTION_PRO("chat_detection_pro", "私聊互动内容检测_专业版", "检测私聊互动中是否存在违规、不宜传播或者影响平台秩序的内容。建议对私聊互动场景的文本均进行该项检测。支持更细粒度的标签返回。", "业务场景"),
+    AD_COMPLIANCE_DETECTION_PRO("ad_compliance_detection_pro", "广告法合规检测_专业版", "针对有推广含义的文本(包括商品标题、详情介绍页、投放营销的素材等)进行专门优化,检测是否有违反广告法以及其他违规或不宜传播的内容。支持更细粒度的标签返回。", "特殊场景"),
+    AI_ART_DETECTION("ai_art_detection", "AIGC类文字检测", "检测AIGC文生图中的文字是否存在色情、涉政、暴恐、违禁等红线类的违规内容。", "AIGC场景"),
+    COMMENT_DETECTION("comment_detection", "公聊评论内容检测", "检测公聊评论中是否存在违规、不宜传播或者影响平台秩序的内容。建议对公聊评论场景的文本均进行该项检测。", "业务场景"),
+    NICKNAME_DETECTION("nickname_detection", "用户昵称检测", "检测用户昵称中是否存在违规、不宜传播或者影响平台秩序的内容。建议对用户昵称场景的文本均进行该项检测。", "业务场景"),
+    CHAT_DETECTION("chat_detection", "私聊互动内容检测", "检测私聊互动中是否存在违规、不宜传播或者影响平台秩序的内容。建议对私聊互动场景的文本均进行该项检测。", "业务场景"),
+    AD_COMPLIANCE_DETECTION("ad_compliance_detection", "广告法合规检测", "针对有推广含义的文本(包括商品标题、详情介绍页、投放营销的素材等)进行专门优化,检测是否有违反广告法以及其他违规或不宜传播的内容。", "特殊场景"),
+    COMMENT_MULTILINGUAL_PRO("comment_multilingual_pro", "国际业务多语言检测", "针对多国语言进行检测,识别出文本中包含的违规、不宜传播或者影响平台秩序的内容。", "特殊场景"),
+    PGC_DETECTION("pgc_detection", "PGC通用物料检测", "针对新闻报道、专业视频、教育物料等具有较高制作标准的文本内容,检测判断是否存在违规、不宜传播或者影响平台秩序的内容。", "特殊场景"),
+    BAILIAN_QUERY_CHECK("bailian_query_check", "百炼文字输入检测", "支持对底线类违规(涉黄、涉政、涉暴等)、不良诱导信息的检测,支持对部分诱导性敏感话题进行检测。", "百炼场景"),
+    BAILIAN_RESPONSE_CHECK("bailian_response_check", "百炼文字输出检测", "支持对底线类违规(涉黄、涉政、涉暴等)、不良诱导信息的检测,支持对AI可能产生的辱骂、偏见、不良价值观信息进行检测。", "百炼场景"),
+    BAILIAN_QUERY_CHECK_PRO("bailian_query_check_pro", "百炼文字输入检测_pro", "支持对底线类违规(涉黄、涉政、涉暴等)、不良诱导信息的检测,支持对部分诱导性敏感话题进行检测。在部分场景中,该服务引入了审核大模型用于提升识别效果。", "百炼场景"),
+    BAILIAN_RESPONSE_CHECK_PRO("bailian_response_check_pro", "百炼文字输出检测_pro", "支持对底线类违规(涉黄、涉政、涉暴等)、不良诱导信息的检测,支持对AI可能产生的辱骂、偏见、不良价值观信息进行检测。在部分场景中,该服务引入了审核大模型用于提升识别效果。", "百炼场景"),
+    URL_DETECTION("url_detection", "URL风险链接检测", "支持检测网站是否涉及色情、赌博、钓鱼、欺诈等风险。", "--");
 
     private final String service;
+    private final String serviceName;
+    private final String serviceDescription;
+    private final String serviceScene;
 
-    TextReviewServiceEnum(String service) {
+    TextReviewServiceEnum(String service, String serviceName, String serviceDescription, String serviceScene) {
         this.service = service;
+        this.serviceName = serviceName;
+        this.serviceDescription = serviceDescription;
+        this.serviceScene = serviceScene;
+    }
+
+    public String getService() {
+        return service;
+    }
+
+    public String getServiceName() {
+        return serviceName;
+    }
+
+    public String getServiceDescription() {
+        return serviceDescription;
     }
 
-}
+    public String getServiceScene() {
+        return serviceScene;
+    }
+}