Browse Source

Merge remote-tracking branch 'origin/master'

zjy 2 weeks ago
parent
commit
a4c91c0a46
47 changed files with 1176 additions and 301 deletions
  1. 67 0
      alien-entity/src/main/java/shop/alien/entity/second/SecondGoodsAudit.java
  2. 17 5
      alien-entity/src/main/java/shop/alien/entity/second/SecondTradeRecord.java
  3. 1 1
      alien-entity/src/main/java/shop/alien/entity/store/LifeMessage.java
  4. 5 0
      alien-entity/src/main/java/shop/alien/entity/store/LifeUserDynamics.java
  5. 8 0
      alien-entity/src/main/java/shop/alien/entity/store/StoreInfo.java
  6. 4 0
      alien-entity/src/main/java/shop/alien/entity/store/dto/StoreInfoDto.java
  7. 3 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/LifeMessageVo.java
  8. 2 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/LifeUserDynamicsVo.java
  9. 9 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreSalesDetailsVo.java
  10. 7 1
      alien-entity/src/main/java/shop/alien/entity/store/vo/WebsocketVo.java
  11. 2 1
      alien-entity/src/main/java/shop/alien/mapper/LifeBlacklistMapper.java
  12. 2 1
      alien-entity/src/main/java/shop/alien/mapper/LifeMessageMapper.java
  13. 1 1
      alien-entity/src/main/java/shop/alien/mapper/LifeUserDynamicsMapper.java
  14. 2 1
      alien-entity/src/main/java/shop/alien/mapper/StoreSalesDetailsMapper.java
  15. 25 0
      alien-entity/src/main/java/shop/alien/mapper/second/SecondGoodsAuditMapper.java
  16. 2 1
      alien-gateway/src/main/resources/bootstrap.yml
  17. 12 0
      alien-second/src/main/java/shop/alien/second/controller/SearchGoodsController.java
  18. 50 12
      alien-second/src/main/java/shop/alien/second/controller/SecondTradeRecordController.java
  19. 5 0
      alien-second/src/main/java/shop/alien/second/service/SecondGoodsService.java
  20. 9 4
      alien-second/src/main/java/shop/alien/second/service/SecondTradeRecordService.java
  21. 121 49
      alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsServiceImpl.java
  22. 69 14
      alien-second/src/main/java/shop/alien/second/service/impl/SecondTradeRecordServiceImpl.java
  23. 16 0
      alien-store/src/main/java/shop/alien/store/config/BaseRedisService.java
  24. 21 0
      alien-store/src/main/java/shop/alien/store/config/SpringContext.java
  25. 31 29
      alien-store/src/main/java/shop/alien/store/config/WebSocketProcess.java
  26. 19 8
      alien-store/src/main/java/shop/alien/store/controller/AliController.java
  27. 3 3
      alien-store/src/main/java/shop/alien/store/controller/LifeGroupPackageController.java
  28. 15 5
      alien-store/src/main/java/shop/alien/store/controller/LifeMessageController.java
  29. 6 6
      alien-store/src/main/java/shop/alien/store/controller/StoreFileUploadController.java
  30. 16 4
      alien-store/src/main/java/shop/alien/store/controller/StoreInfoController.java
  31. 18 6
      alien-store/src/main/java/shop/alien/store/controller/StoreUserController.java
  32. 4 4
      alien-store/src/main/java/shop/alien/store/job/StoreMembershipCardJob.java
  33. 0 10
      alien-store/src/main/java/shop/alien/store/service/LifeUserDynamicsService.java
  34. 9 1
      alien-store/src/main/java/shop/alien/store/service/StoreInfoService.java
  35. 11 2
      alien-store/src/main/java/shop/alien/store/service/StoreUserService.java
  36. 2 1
      alien-store/src/main/java/shop/alien/store/service/impl/LifeMessageServiceImpl.java
  37. 38 3
      alien-store/src/main/java/shop/alien/store/service/impl/StoreInfoServiceImpl.java
  38. 3 1
      alien-store/src/main/java/shop/alien/store/service/impl/StoreSalesDetailsServiceImpl.java
  39. 113 55
      alien-store/src/main/java/shop/alien/store/service/impl/StoreUserServiceImpl.java
  40. 121 5
      alien-store/src/main/java/shop/alien/store/task/ScheduledTask.java
  41. 61 44
      alien-store/src/main/java/shop/alien/store/util/FileUploadUtil.java
  42. 2 1
      alien-store/src/main/resources/bootstrap.yml
  43. 6 0
      alien-util/pom.xml
  44. 88 0
      alien-util/src/main/java/shop/alien/util/ali/AliOSSUtil.java
  45. 81 0
      alien-util/src/main/java/shop/alien/util/ali/Demo.java
  46. 17 22
      alien-util/src/main/java/shop/alien/util/common/safe/ImageModerationUtil.java
  47. 52 0
      alien-util/src/main/java/shop/alien/util/file/FileUtil.java

+ 67 - 0
alien-entity/src/main/java/shop/alien/entity/second/SecondGoodsAudit.java

@@ -0,0 +1,67 @@
+package shop.alien.entity.second;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 二手商品审核记录
+ */
+@Data
+@JsonInclude
+@TableName("second_goods_audit")
+public class SecondGoodsAudit implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    // 商品状态常量
+    public static final int GOODS_STATUS_SUCCESS = 1; // 审核成功
+    public static final int GOODS_STATUS_FAILED = 2;  // 审核失败
+
+    // 删除标记常量
+    public static final int DELETE_FLAG_NO = 0;  // 未删除
+    public static final int DELETE_FLAG_YES = 1; // 已删除
+
+    @TableId(value = "id", type = IdType.AUTO)
+    @ApiModelProperty(value = "主键ID")
+    private Integer id;
+
+    @TableField("goods_id")
+    @ApiModelProperty(value = "商品ID")
+    private Integer goodsId;
+
+    @TableField("goods_status")
+    @ApiModelProperty(value = "商品状态 1:审核成功 2:审核失败")
+    private Integer goodsStatus;
+
+    @TableField("failed_reason")
+    @ApiModelProperty(value = "审核描述(失败原因)")
+    private String failedReason;
+
+    @TableField("delete_flag")
+    @ApiModelProperty(value = "删除标记 0:未删除 1:已删除")
+    @TableLogic
+    private Integer deleteFlag;
+
+    @TableField(value = "created_time", fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ApiModelProperty(value = "创建时间")
+    private Date createdTime;
+
+    @TableField("created_user_id")
+    @ApiModelProperty(value = "创建人ID")
+    private Integer createdUserId;
+
+    @TableField(value = "updated_time", fill = FieldFill.UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ApiModelProperty(value = "修改时间")
+    private Date updatedTime;
+
+    @TableField("updated_user_id")
+    @ApiModelProperty(value = "修改人ID")
+    private Integer updatedUserId;
+}

+ 17 - 5
alien-entity/src/main/java/shop/alien/entity/second/SecondTradeRecord.java

@@ -61,12 +61,12 @@ public class SecondTradeRecord extends Model<SecondTradeRecord> {
     private BigDecimal transactionAmount;
     private BigDecimal transactionAmount;
 
 
     @ApiModelProperty(value = "买家是否签到  0-未签到  1-已签到")
     @ApiModelProperty(value = "买家是否签到  0-未签到  1-已签到")
-    @TableField("buyer_signin")
-    private Integer buyerSignin;
+    @TableField("buyer_sign_in")
+    private Integer buyerSignIn;
 
 
     @ApiModelProperty(value = "卖家是否签到  0-未签到  1-已签到")
     @ApiModelProperty(value = "卖家是否签到  0-未签到  1-已签到")
-    @TableField("seller_signin")
-    private Integer sellerSignin;
+    @TableField("seller_sign_in")
+    private Integer sellerSignIn;
 
 
     @ApiModelProperty(value = "买家交易状态  1-交易成功  2-交易失败")
     @ApiModelProperty(value = "买家交易状态  1-交易成功  2-交易失败")
     @TableField("buyer_transaction_status")
     @TableField("buyer_transaction_status")
@@ -76,7 +76,7 @@ public class SecondTradeRecord extends Model<SecondTradeRecord> {
     @TableField("seller_transaction_status")
     @TableField("seller_transaction_status")
     private Integer sellerTransactionStatus;
     private Integer sellerTransactionStatus;
 
 
-    @ApiModelProperty(value = "交易状态  0-待交易  1-交易成功  2-交易失败")
+    @ApiModelProperty(value = "交易状态  0-待交易  1-交易成功  2-交易失败  3-交易取消")
     @TableField("trade_status")
     @TableField("trade_status")
     private Integer tradeStatus;
     private Integer tradeStatus;
 
 
@@ -84,6 +84,18 @@ public class SecondTradeRecord extends Model<SecondTradeRecord> {
     @TableField("buyer_evaluate")
     @TableField("buyer_evaluate")
     private String buyerEvaluate;
     private String buyerEvaluate;
 
 
+    @ApiModelProperty(value = "取消交易id")
+    @TableField("cancel_id")
+    private Integer cancelId;
+
+    @ApiModelProperty(value = "取消交易原因(字典表_cancelTradeReason)")
+    @TableField("cancel_reason")
+    private String cancelReason;
+
+    @ApiModelProperty(value = "取消交易原因补充")
+    @TableField("cancel_reason_supplement")
+    private String cancelReasonSupplement;
+
     @ApiModelProperty(value = "卖家评价")
     @ApiModelProperty(value = "卖家评价")
     @TableField("seller_evaluate")
     @TableField("seller_evaluate")
     private String sellerEvaluate;
     private String sellerEvaluate;

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

@@ -34,7 +34,7 @@ public class LifeMessage {
     @ApiModelProperty(value = "发送内容")
     @ApiModelProperty(value = "发送内容")
     private String content;
     private String content;
 
 
-    @ApiModelProperty(value = "消息类型  1-文本  2-图片 3-链接  4-二手交易信息")
+    @ApiModelProperty(value = "消息类型  1-文本  2-图片 3-链接  4-二手交易创建/确认/拒绝  5-二手交易签到提醒  6-二手交易已签到")
     private String type;
     private String type;
 
 
     private Date currentTime;
     private Date currentTime;

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

@@ -45,6 +45,11 @@ public class LifeUserDynamics {
     private String address;
     private String address;
 
 
     /**
     /**
+     * 地址详情
+     */
+    private String addressContext;
+
+    /**
      * 地址名称
      * 地址名称
      */
      */
     private String addressName;
     private String addressName;

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

@@ -164,4 +164,12 @@ public class StoreInfo {
     @TableField(value = "logout_time", fill = FieldFill.INSERT)
     @TableField(value = "logout_time", fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private Date logoutTime;
     private Date logoutTime;
+
+    @ApiModelProperty(value = "抽成比例")
+    @TableField("commission_rate")
+    private String commissionRate;
+
+    @ApiModelProperty(value = "原因")
+    @TableField("reason")
+    private String reason;
 }
 }

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

@@ -148,4 +148,8 @@ public class StoreInfoDto {
     @ApiModelProperty(value = "行政区域区adcode")
     @ApiModelProperty(value = "行政区域区adcode")
     private String administrativeRegionDistrictAdcode;
     private String administrativeRegionDistrictAdcode;
 
 
+    @ApiModelProperty(value = "抽成比例")
+    @TableField("commission_rate")
+    private String commissionRate;
+
 }
 }

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

@@ -24,6 +24,9 @@ public class LifeMessageVo extends LifeMessage {
 
 
     @ApiModelProperty(value = "唯一标识")
     @ApiModelProperty(value = "唯一标识")
     private String phoneId;
     private String phoneId;
+
+    @ApiModelProperty(value = "用户id")
+    private Integer userId;
 //
 //
 //    @ApiModelProperty(value = "消息列表")
 //    @ApiModelProperty(value = "消息列表")
 //    private List<LifeMessage> messageList;
 //    private List<LifeMessage> messageList;

+ 2 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/LifeUserDynamicsVo.java

@@ -43,4 +43,6 @@ public class LifeUserDynamicsVo extends LifeUserDynamics {
     @ApiModelProperty(value = "内容")
     @ApiModelProperty(value = "内容")
     private String context;
     private String context;
 
 
+    @ApiModelProperty(value = "地址详情")
+    private String addressContext;
 }
 }

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

@@ -55,6 +55,9 @@ public class StoreSalesDetailsVo {
     @ApiModelProperty(value = "1-代金券  2-套餐")
     @ApiModelProperty(value = "1-代金券  2-套餐")
     private Integer type;
     private Integer type;
 
 
+    @ApiModelProperty(value = "代金券套餐类型 (查询用)")
+    private List<String> typeList;
+
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     @ApiModelProperty(value = "支付时间-开始时间")
     @ApiModelProperty(value = "支付时间-开始时间")
     private Date payStartTime;
     private Date payStartTime;
@@ -62,4 +65,10 @@ public class StoreSalesDetailsVo {
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     @ApiModelProperty(value = "支付时间-结束时间")
     @ApiModelProperty(value = "支付时间-结束时间")
     private Date payEndTime;
     private Date payEndTime;
+
+    @ApiModelProperty(value = "预计收入")
+    private String expecteDrevenue;
+
+    @ApiModelProperty(value = "实付款")
+    private String finalPrice;
 }
 }

+ 7 - 1
alien-entity/src/main/java/shop/alien/entity/store/vo/WebsocketVo.java

@@ -14,9 +14,15 @@ public class WebsocketVo {
     @ApiModelProperty(value = "接收者id")
     @ApiModelProperty(value = "接收者id")
     private String receiverId;
     private String receiverId;
 
 
-    @ApiModelProperty(value = "消息类型  1-文本  2-图片  3-链接")
+    @ApiModelProperty(value = "类别(消息-message 公告-notice 心跳-heartbeat)")
+    private String category;
+
+    @ApiModelProperty(value = "消息类型  1-文本  2-图片 3-链接  4-二手交易创建/确认/拒绝  5-二手交易签到提醒  6-二手交易已签到")
     private String type;
     private String type;
 
 
     @ApiModelProperty(value = "消息内容")
     @ApiModelProperty(value = "消息内容")
     private String text;
     private String text;
+
+    @ApiModelProperty(value = "消息id")
+    private Integer messageId;
 }
 }

+ 2 - 1
alien-entity/src/main/java/shop/alien/mapper/LifeBlacklistMapper.java

@@ -2,6 +2,7 @@ package shop.alien.mapper;
 
 
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 import org.apache.ibatis.annotations.Select;
 import shop.alien.entity.store.LifeBlacklist;
 import shop.alien.entity.store.LifeBlacklist;
 import shop.alien.entity.store.vo.LifeBlacklistVo;
 import shop.alien.entity.store.vo.LifeBlacklistVo;
@@ -34,5 +35,5 @@ public interface LifeBlacklistMapper extends BaseMapper<LifeBlacklist> {
             "left join life_user user on user.id = black.blocked_id and black.blocked_type = '2' and user.delete_flag = 0 " +
             "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 " +
             "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 ")
             "where black.blocker_type = #{userType} and black.blocker_id = #{userId} and black.delete_flag = 0 ")
-    List<LifeBlacklistVo> getPhoneIdByUserId(String userType, String userId);
+    List<LifeBlacklistVo> getPhoneIdByUserId(@Param("userType") String userType, @Param("userId") String userId);
 }
 }

+ 2 - 1
alien-entity/src/main/java/shop/alien/mapper/LifeMessageMapper.java

@@ -44,7 +44,8 @@ public interface LifeMessageMapper extends BaseMapper<LifeMessage> {
             ") " +
             ") " +
             "select message.id, message.type, message.phoneId, message.content, message.created_time createdTime, message.is_read, " +
             "select message.id, message.type, message.phoneId, message.content, message.created_time createdTime, message.is_read, " +
             "       if (message.flag = 'user', user.user_name, suser.name) userName, " +
             "       if (message.flag = 'user', user.user_name, suser.name) userName, " +
-            "       if (message.flag = 'user', user.user_image, img.img_url) userImage " +
+            "       if (message.flag = 'user', user.user_image, img.img_url) userImage," +
+            "       if (message.flag = 'user', user.id, suser.id) userId " +
             "from message_num message " +
             "from message_num message " +
             "left join life_user user on message.flag = 'user' and message.phone = user.user_phone and user.delete_flag = 0 " +
             "left join life_user user on message.flag = 'user' and message.phone = user.user_phone and user.delete_flag = 0 " +
             "left join store_user suser on message.flag = 'store' and message.phone = suser.phone and suser.delete_flag = 0 " +
             "left join store_user suser on message.flag = 'store' and message.phone = suser.phone and suser.delete_flag = 0 " +

+ 1 - 1
alien-entity/src/main/java/shop/alien/mapper/LifeUserDynamicsMapper.java

@@ -15,7 +15,7 @@ import java.util.List;
 public interface LifeUserDynamicsMapper extends BaseMapper<LifeUserDynamics> {
 public interface LifeUserDynamicsMapper extends BaseMapper<LifeUserDynamics> {
 
 
     @Select("with dynamice as( " +
     @Select("with dynamice as( " +
-            "    select id, title, phone_id phoneId, context, image_path, address, liulan_count, dianzan_count, type, created_time, substring_index(phone_id, '_', 1) flag, substring_index(phone_id, '_', -1) phone, draft " +
+            "    select id, title, phone_id phoneId, context, image_path, address,address_context, liulan_count, dianzan_count, type, created_time, substring_index(phone_id, '_', 1) flag, substring_index(phone_id, '_', -1) phone, draft " +
             "    from life_user_dynamics " +
             "    from life_user_dynamics " +
             "    where delete_flag = 0 and draft = 0 order by created_time desc" +
             "    where delete_flag = 0 and draft = 0 order by created_time desc" +
             ") " +
             ") " +

+ 2 - 1
alien-entity/src/main/java/shop/alien/mapper/StoreSalesDetailsMapper.java

@@ -18,7 +18,8 @@ import shop.alien.entity.store.vo.StoreSalesDetailsVo;
 @Mapper
 @Mapper
 public interface StoreSalesDetailsMapper extends BaseMapper<LifeUserOrder> {
 public interface StoreSalesDetailsMapper extends BaseMapper<LifeUserOrder> {
 
 
-    @Select("select coupon.name couponName, luser.user_phone userPhone, lorder.order_no orderNo, lorder.pay_time payTime, lorder.price, lorder.status " +
+    @Select("select coupon.name couponName, luser.user_phone userPhone, lorder.order_no orderNo, lorder.pay_time payTime, lorder.price, " +
+            "lorder.final_price finalPrice, (lorder.final_price*0.97)  expecteDrevenue, lorder.status " +
             "from life_user_order lorder " +
             "from life_user_order lorder " +
             "join life_coupon coupon on coupon.id = lorder.quan_id " +
             "join life_coupon coupon on coupon.id = lorder.quan_id " +
             "join life_user luser on luser.id = lorder.user_id ${ew.customSqlSegment}")
             "join life_user luser on luser.id = lorder.user_id ${ew.customSqlSegment}")

+ 25 - 0
alien-entity/src/main/java/shop/alien/mapper/second/SecondGoodsAuditMapper.java

@@ -0,0 +1,25 @@
+package shop.alien.mapper.second;
+
+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.second.SecondGoodsAudit;
+
+/**
+ * 二手商品审核记录映射器
+ */
+@Mapper
+public interface SecondGoodsAuditMapper extends BaseMapper<SecondGoodsAudit> {
+
+    /**
+     * 根据商品ID查询最新审核记录
+     *
+     * @param goodsId 商品ID
+     * @return 最新审核记录
+     */
+    @Select("SELECT * FROM second_goods_audit " +
+            "WHERE goods_id = #{goodsId} AND delete_flag = 0 " +
+            "ORDER BY created_time DESC LIMIT 1")
+    SecondGoodsAudit getLatestByGoodsId(@Param("goodsId") Integer goodsId);
+}

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

@@ -17,4 +17,5 @@ spring:
         username: nacos
         username: nacos
         password: ngfriend198092
         password: ngfriend198092
         group: DEFAULT_GROUP
         group: DEFAULT_GROUP
-        file-extension: yml
+        file-extension: yml
+#        namespace: 3cbb802a-b56e-47f7-b658-b5012ecafb1f

+ 12 - 0
alien-second/src/main/java/shop/alien/second/controller/SearchGoodsController.java

@@ -69,4 +69,16 @@ public class SearchGoodsController {
         return R.data(secondGoodsService.getCollectTop10(), "获取成功");
         return R.data(secondGoodsService.getCollectTop10(), "获取成功");
     }
     }
 
 
+    /**
+     * 查询商品列表
+     */
+    @GetMapping("/getGoodsListByUserId")
+    @ApiOperation("查询商品列表")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "goodsStatus", value = "商品状态 0:草稿 1:审核中 2:审核失败 3:已上架 4:已下架 5:已售出", dataType = "Integer", paramType = "query")})
+    public R<List<SecondGoods>> getGoodsListByUserId(Integer userId, Integer goodsStatus) {
+        return R.data(secondGoodsService.getGoodsListByUserId(userId, goodsStatus), "获取成功");
+    }
+
 }
 }

+ 50 - 12
alien-second/src/main/java/shop/alien/second/controller/SecondTradeRecordController.java

@@ -31,11 +31,11 @@ public class SecondTradeRecordController {
 
 
     private final SecondTradeRecordService secondTradeRecordService;
     private final SecondTradeRecordService secondTradeRecordService;
 
 
-    @ApiOperation("获取交易信息")
+    @ApiOperation("交易窗")
     @ApiOperationSupport(order = 1)
     @ApiOperationSupport(order = 1)
     @ApiImplicitParams({@ApiImplicitParam(name = "sideId", value = "对方的id", dataType = "Integer", paramType = "query", required = true)})
     @ApiImplicitParams({@ApiImplicitParam(name = "sideId", value = "对方的id", dataType = "Integer", paramType = "query", required = true)})
     @GetMapping("/getTradeRecord")
     @GetMapping("/getTradeRecord")
-    public R<List<SecondTradeRecord>> getTradeRecord(@RequestParam int sideId) {
+    public R<List<SecondTradeRecord>> getTradeRecord(@RequestParam int sideId) throws Exception {
         log.info("SecondTradeRecordController.getTradeRecord?sideId={}", sideId);
         log.info("SecondTradeRecordController.getTradeRecord?sideId={}", sideId);
         return R.data(secondTradeRecordService.getTradeRecord(sideId));
         return R.data(secondTradeRecordService.getTradeRecord(sideId));
     }
     }
@@ -43,32 +43,70 @@ public class SecondTradeRecordController {
     @ApiOperation("创建交易")
     @ApiOperation("创建交易")
     @ApiOperationSupport(order = 2)
     @ApiOperationSupport(order = 2)
     @PostMapping("/createTrade")
     @PostMapping("/createTrade")
-    public R<Boolean> createTrade(@RequestBody SecondTradeRecord entity) {
+    public R<Boolean> createTrade(@RequestBody SecondTradeRecord entity) throws Exception {
         log.info("SecondTradeRecordController.createTrade?entity={}", entity.toString());
         log.info("SecondTradeRecordController.createTrade?entity={}", entity.toString());
         if (secondTradeRecordService.createTrade(entity)) return R.success("创建成功");
         if (secondTradeRecordService.createTrade(entity)) return R.success("创建成功");
         return R.fail("创建失败");
         return R.fail("创建失败");
     }
     }
 
 
-    @ApiOperation("交易签到")
+
+    @ApiOperation("确认商品是否可以交易")
     @ApiOperationSupport(order = 3)
     @ApiOperationSupport(order = 3)
-    @ApiImplicitParams({@ApiImplicitParam(name = "tradeId", value = "交易id", dataType = "Integer", paramType = "query", required = true)})
-    @GetMapping("/tradeSignin")
-    public R<Boolean> tradeSignin(@RequestParam int tradeId) {
-        log.info("SecondTradeRecordController.tradeSignin?tradeId={}", tradeId);
-        if (secondTradeRecordService.tradeSignin(tradeId)) return R.success("签到成功");
-        return R.fail("签到失败");
+    @ApiImplicitParams({@ApiImplicitParam(name = "goodsId", value = "商品id", dataType = "Integer", paramType = "query", required = true)})
+    @GetMapping("/goodsTradeConfirm")
+    public R<Boolean> goodsTradeConfirm(@RequestParam int goodsId) throws Exception {
+        log.info("SecondTradeRecordController.goodsTradeConfirm?goodsId={}", goodsId);
+        return R.data(secondTradeRecordService.goodsTradeConfirm(goodsId));
     }
     }
 
 
-    @ApiOperation("交易确认")
+    @ApiOperation("交易签到")
     @ApiOperationSupport(order = 4)
     @ApiOperationSupport(order = 4)
     @ApiImplicitParams({
     @ApiImplicitParams({
             @ApiImplicitParam(name = "tradeId", value = "交易id", dataType = "Integer", paramType = "query", required = true),
             @ApiImplicitParam(name = "tradeId", value = "交易id", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "messageId", value = "消息id", dataType = "Integer", paramType = "query", required = true)})
+    @GetMapping("/tradeSignIn")
+    public R<Boolean> tradeSignIn(@RequestParam int tradeId, int messageId) throws Exception {
+        log.info("SecondTradeRecordController.tradeSignIn?tradeId={}, messageId={}", tradeId, messageId);
+        if (secondTradeRecordService.tradeSignIn(tradeId, messageId)) return R.success("签到成功");
+        return R.fail("签到失败");
+    }
+
+    @ApiOperation("确认拒绝交易")
+    @ApiOperationSupport(order = 5)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "tradeId", value = "交易id", dataType = "Integer", paramType = "query", required = true),
             @ApiImplicitParam(name = "type", value = "0-失败  1-成功", dataType = "Integer", paramType = "query", required = true),
             @ApiImplicitParam(name = "type", value = "0-失败  1-成功", dataType = "Integer", paramType = "query", required = true),
             @ApiImplicitParam(name = "evaluate", value = "评价", dataType = "String", paramType = "query")})
             @ApiImplicitParam(name = "evaluate", value = "评价", dataType = "String", paramType = "query")})
     @GetMapping("/tradeConfirm")
     @GetMapping("/tradeConfirm")
-    public R<Boolean> tradeConfirm(@RequestParam int tradeId, @RequestParam int type, @RequestParam String evaluate) {
+    public R<Boolean> tradeConfirm(@RequestParam int tradeId, @RequestParam int type, @RequestParam String evaluate) throws Exception {
         log.info("SecondTradeRecordController.tradeConfirm?tradeId={}, type={}, evaluate={}", tradeId, type, evaluate);
         log.info("SecondTradeRecordController.tradeConfirm?tradeId={}, type={}, evaluate={}", tradeId, type, evaluate);
         if (secondTradeRecordService.tradeConfirm(tradeId, type, evaluate)) return R.success("交易确认成功");
         if (secondTradeRecordService.tradeConfirm(tradeId, type, evaluate)) return R.success("交易确认成功");
         return R.fail("交易确认失败");
         return R.fail("交易确认失败");
     }
     }
+
+    @ApiOperation("交易完成确认")
+    @ApiOperationSupport(order = 6)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "tradeId", value = "交易id", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "type", value = "0-失败  1-成功", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "evaluate", value = "评价", dataType = "String", paramType = "query")})
+    @GetMapping("/tradeCompleteConfirm")
+    public R<Boolean> tradeCompleteConfirm(@RequestParam int tradeId, @RequestParam int type, @RequestParam String evaluate) throws Exception {
+        log.info("SecondTradeRecordController.tradeCompleteConfirm?tradeId={}, type={}, evaluate={}", tradeId, type, evaluate);
+        if (secondTradeRecordService.tradeCompleteConfirm(tradeId, type, evaluate)) return R.success("交易确认成功");
+        return R.fail("交易确认失败");
+    }
+
+    @ApiOperation("取消交易")
+    @ApiOperationSupport(order = 7)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "tradeId", value = "交易id", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "cancelReason", value = "取消原因", dataType = "String", paramType = "query", required = true),
+            @ApiImplicitParam(name = "cancelReasonSupplement", value = "取消原因补充", dataType = "String", paramType = "query")})
+    @GetMapping("/cancelTrade")
+    public R<Boolean> cancelTrade(@RequestParam int tradeId, @RequestParam String cancelReason, String cancelReasonSupplement) throws Exception {
+        log.info("SecondTradeRecordController.cancelTrade?tradeId={}, cancelReason={}, cancelReasonSupplement={}", tradeId, cancelReason, cancelReasonSupplement);
+        if (secondTradeRecordService.cancelTrade(tradeId, cancelReason, cancelReasonSupplement)) return R.success("取消交易成功");
+        return R.fail("取消交易失败");
+    }
 }
 }

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

@@ -2,6 +2,8 @@ package shop.alien.second.service;
 
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import io.swagger.models.auth.In;
+import org.springframework.transaction.annotation.Transactional;
 import shop.alien.entity.second.SecondGoods;
 import shop.alien.entity.second.SecondGoods;
 import shop.alien.entity.second.vo.SecondGoodsVo;
 import shop.alien.entity.second.vo.SecondGoodsVo;
 import shop.alien.entity.second.vo.SellGoodsVo;
 import shop.alien.entity.second.vo.SellGoodsVo;
@@ -19,6 +21,7 @@ public interface SecondGoodsService extends IService<SecondGoods> {
      * @param editFlag 编辑标识 0:创建 1:编辑
      * @param editFlag 编辑标识 0:创建 1:编辑
      * @return 是否成功保存
      * @return 是否成功保存
      */
      */
+    @Transactional
     boolean createBasicInfo(SecondGoodsVo goods, Integer editFlag) throws Exception;
     boolean createBasicInfo(SecondGoodsVo goods, Integer editFlag) throws Exception;
 
 
     /**
     /**
@@ -144,4 +147,6 @@ public interface SecondGoodsService extends IService<SecondGoods> {
      * @return 分页后的商品交易列表
      * @return 分页后的商品交易列表
      */
      */
     IPage<SellGoodsVo> getTransactionList(IPage<SellGoodsVo> page, Integer userId);
     IPage<SellGoodsVo> getTransactionList(IPage<SellGoodsVo> page, Integer userId);
+
+    List<SecondGoods> getGoodsListByUserId(Integer userId, Integer goodsStatus);
 }
 }

+ 9 - 4
alien-second/src/main/java/shop/alien/second/service/SecondTradeRecordService.java

@@ -16,12 +16,17 @@ import java.util.List;
  * @since 2025-07-07
  * @since 2025-07-07
  */
  */
 public interface SecondTradeRecordService extends IService<SecondTradeRecord> {
 public interface SecondTradeRecordService extends IService<SecondTradeRecord> {
-    List<SecondTradeRecord> getTradeRecord(int sideId);
+    List<SecondTradeRecord> getTradeRecord(int sideId) throws Exception;
 
 
-    boolean createTrade(SecondTradeRecord entity);
+    boolean createTrade(SecondTradeRecord entity) throws Exception;
 
 
-    boolean tradeSignin(int tradeId);
+    boolean tradeSignIn(int tradeId, int messageId) throws Exception;
 
 
-    boolean tradeConfirm(int tradeId, int type, String evaluate);
+    boolean tradeConfirm(int tradeId, int type, String evaluate) throws Exception;
 
 
+    boolean tradeCompleteConfirm(int tradeId, int type, String evaluate) throws Exception;
+
+    boolean goodsTradeConfirm(int goodsId) throws Exception;
+
+    boolean cancelTrade(int tradeId, String cancelReason, String cancelReasonSupplement) throws Exception;
 }
 }

+ 121 - 49
alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsServiceImpl.java

@@ -1,6 +1,7 @@
 package shop.alien.second.service.impl;
 package shop.alien.second.service.impl;
 
 
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.collection.CollectionUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -13,11 +14,13 @@ import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import org.springframework.util.StringUtils;
 import org.springframework.util.StringUtils;
 import shop.alien.entity.second.SecondGoods;
 import shop.alien.entity.second.SecondGoods;
+import shop.alien.entity.second.SecondGoodsAudit;
 import shop.alien.entity.second.vo.SecondGoodsVo;
 import shop.alien.entity.second.vo.SecondGoodsVo;
 import shop.alien.entity.second.vo.SellGoodsVo;
 import shop.alien.entity.second.vo.SellGoodsVo;
 import shop.alien.entity.store.*;
 import shop.alien.entity.store.*;
 import shop.alien.entity.store.vo.LifeUserVo;
 import shop.alien.entity.store.vo.LifeUserVo;
 import shop.alien.mapper.*;
 import shop.alien.mapper.*;
+import shop.alien.mapper.second.SecondGoodsAuditMapper;
 import shop.alien.mapper.second.SecondGoodsMapper;
 import shop.alien.mapper.second.SecondGoodsMapper;
 import shop.alien.second.service.SecondGoodsService;
 import shop.alien.second.service.SecondGoodsService;
 import shop.alien.util.common.VideoUtils;
 import shop.alien.util.common.VideoUtils;
@@ -56,6 +59,11 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
     private final SecondGoodsMapper secondGoodsMapper;
     private final SecondGoodsMapper secondGoodsMapper;
 
 
     /**
     /**
+     * 二手商品审核Mapper
+     */
+    private final SecondGoodsAuditMapper secondGoodsAuditMapper;
+
+    /**
      * 用户信息Mapper
      * 用户信息Mapper
      */
      */
     private final LifeUserMapper lifeUserMapper;
     private final LifeUserMapper lifeUserMapper;
@@ -111,60 +119,54 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
 
 
     @Override
     @Override
     public boolean createBasicInfo(SecondGoodsVo goodsDTO,Integer editFlag) throws Exception {
     public boolean createBasicInfo(SecondGoodsVo goodsDTO,Integer editFlag) throws Exception {
-        // 实现基本信息保存逻辑
-        SecondGoods goods = new SecondGoods();
-        BeanUtils.copyProperties(goodsDTO, goods);
-
-        if (editFlag == 1){
-            goods.setId(goodsDTO.getId());
-            // 保存商品基本信息
-            if (!updateById(goods)) {
-                return false; // 保存失败直接返回
-            }
-        } else {
-            // 保存商品基本信息
-            if (!save(goods)) {
-                return false; // 保存失败直接返回
+        try {
+            // 实现基本信息保存逻辑
+            SecondGoods goods = new SecondGoods();
+            BeanUtils.copyProperties(goodsDTO, goods);
+
+            if (editFlag == 1) {
+                goods.setId(goodsDTO.getId());
+                goods = secondGoodsMapper.selectById(goodsDTO.getId());
+                // 保存商品基本信息
+                if (!updateById(goods)) {
+                    return false; // 保存失败直接返回
+                }
+            } else {
+                // 保存商品基本信息
+                if (!save(goods)) {
+                    return false; // 保存失败直接返回
+                }
             }
             }
-        }
 
 
-        // 获取保存后的商品ID,用于后续业务处理
-        Integer savedGoodsId = goods.getId();
-        if (savedGoodsId == null) {
-            return false; // 如果获取不到ID,视为操作失败
-        }
-
-        // 保存商品图片信息
-        if (!saveStoreImages(savedGoodsId, goodsDTO.getImgUrl())) {
-            return false;
-        }
-        // 二手业务安全验证(调取阿里)
-        if (!checkSafety(goods)) {
-            return false;
-        }
+            // 获取保存后的商品ID,用于后续业务处理
+            Integer savedGoodsId = goods.getId();
+            if (savedGoodsId == null) {
+                return false; // 如果获取不到ID,视为操作失败
+            }
 
 
-        // 执行内容审核(图片和文本)
-        if (!performContentReviews(goods, goodsDTO)) {
-            return true; // 审核不通过时已设置状态,返回成功但标记为审核失败
-        }
+            // 保存商品图片信息
+            if (!saveStoreImages(savedGoodsId, goodsDTO.getImgUrl())) {
+                return false;
+            }
 
 
-        // 如果所有审核都通过,设置为上架状态
-        goods.setGoodsStatus(3); // 上架
-        goods.setReleaseTime(new Date()); // 上架时间
-        updateById(goods);
+            // 执行内容审核(图片和文本)
+            if (!performContentReviews(goods, goodsDTO)) {
+                return true; // 审核不通过时已设置状态,返回成功但标记为审核失败
+            }
 
 
-        // 发送消息
-        sendMessage(goods);
-        return true;
-    }
+            // 如果所有审核都通过,设置为上架状态
+            goods.setGoodsStatus(3); // 上架
+            goods.setReleaseTime(new Date()); // 上架时间
+            updateById(goods);
 
 
-    /**
-     * 二手业务安全验证 (调取阿里)
-     * @param goods 商品信息
-     * @return 验证结果
-     */
-    private boolean checkSafety(SecondGoods goods) {
-        return true;
+            // 发送消息
+            sendMessage(goods);
+            return true;
+        } catch (Exception e) {
+            // 记录异常日志
+            log.error("创建或更新二手商品基本信息时发生异常", e);
+            return false;
+        }
     }
     }
     /**
     /**
      * 执行内容审核(图片和文本)
      * 执行内容审核(图片和文本)
@@ -183,6 +185,10 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
             // 文本审核不通过或存在高风险
             // 文本审核不通过或存在高风险
             goods.setGoodsStatus(2); // 审核失败
             goods.setGoodsStatus(2); // 审核失败
             goods.setFailedReason("文本审核不通过:" + (textCheckResult.getRiskWords() != null ? textCheckResult.getRiskWords() : "存在高风险内容"));
             goods.setFailedReason("文本审核不通过:" + (textCheckResult.getRiskWords() != null ? textCheckResult.getRiskWords() : "存在高风险内容"));
+            // 插入审核记录
+            createGoodsAudit(goods, textCheckResult.getRiskWords());
+            // 发送审核失败消息
+            sendFailedMsg(goods);
             return false;
             return false;
         }
         }
 
 
@@ -196,6 +202,10 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
                     // 文本审核不通过或存在高风险
                     // 文本审核不通过或存在高风险
                     goods.setGoodsStatus(2); // 审核失败
                     goods.setGoodsStatus(2); // 审核失败
                     goods.setFailedReason("图片审核不通过:图片中包含" + (response.getDescriptions() != null ? response.getDescriptions() : "高风险内容"));
                     goods.setFailedReason("图片审核不通过:图片中包含" + (response.getDescriptions() != null ? response.getDescriptions() : "高风险内容"));
+                    // 插入审核记录
+                    createGoodsAudit(goods, response.getDescriptions());
+                    // 发送审核失败消息
+                    sendFailedMsg(goods);
                     return false;
                     return false;
                 }
                 }
             }
             }
@@ -208,6 +218,27 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
     }
     }
 
 
     /**
     /**
+     * 创建商品审核记录
+     *
+     * @param goods 商品
+     * @param riskWords 文本审核结果
+     */
+    private void createGoodsAudit(SecondGoods goods, String riskWords) {
+        // 保存审核结果
+        secondGoodsMapper.updateById(goods);
+        // 插入审核记录
+        SecondGoodsAudit auditRecord = new SecondGoodsAudit();
+        auditRecord.setGoodsId(goods.getId());
+        auditRecord.setGoodsStatus(2); // 审核失败
+        auditRecord.setFailedReason("文本审核不通过:" + (riskWords != null ? riskWords : "存在高风险内容"));
+        auditRecord.setCreatedUserId(goods.getUserId());
+        auditRecord.setUpdatedUserId(goods.getUserId());
+        auditRecord.setCreatedTime(new Date());
+        auditRecord.setUpdatedTime(new Date());
+        secondGoodsAuditMapper.insert(auditRecord);
+    }
+
+    /**
      * 保存商品图片信息
      * 保存商品图片信息
      * @param savedGoodsId 保存后的商品ID
      * @param savedGoodsId 保存后的商品ID
      * @param imgUrl 图片URL列表
      * @param imgUrl 图片URL列表
@@ -261,12 +292,36 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
         lifeNotice.setReceiverId("user_"+ phone);
         lifeNotice.setReceiverId("user_"+ phone);
         lifeNotice.setBusinessId(goods.getId());
         lifeNotice.setBusinessId(goods.getId());
         lifeNotice.setTitle("商品发布通知");
         lifeNotice.setTitle("商品发布通知");
-        lifeNotice.setContext("您有一笔新二手商品发成功,请及时查看");
+        lifeNotice.setContext("恭喜您的商品发成功");
         lifeNotice.setNoticeType(1); // 系统通知
         lifeNotice.setNoticeType(1); // 系统通知
         lifeNotice.setIsRead(0);
         lifeNotice.setIsRead(0);
         lifeNoticeMapper.insert(lifeNotice);
         lifeNoticeMapper.insert(lifeNotice);
     }
     }
 
 
+
+    /**
+     * 发送审核失败消息
+     * @param goods 商品审核信息
+     */
+    private void sendFailedMsg(SecondGoods goods) {
+        // 根据 goods.getUserId() 获取用户信息
+        LifeUser lifeUser = lifeUserMapper.selectById(goods.getUserId());
+        String phone = lifeUser.getUserPhone();
+        // 调取feign接口 发送消息 life_notice表
+        LifeNotice lifeNotice = new LifeNotice();
+        lifeNotice.setSenderId("system");
+        lifeNotice.setReceiverId("user_"+ phone);
+        lifeNotice.setBusinessId(goods.getId());
+        lifeNotice.setTitle("商品审核通知");
+        // TODO: 失败原因本期为固定文案,实际原因暂不保存
+//        lifeNotice.setContext("商品审核失败,原因为:" + goods.getFailedReason());
+        lifeNotice.setContext("抱歉您的商品发布失败,图片或文字存在违规行为。请您修改后从新发布");
+        lifeNotice.setNoticeType(1); // 系统通知
+        lifeNotice.setIsRead(0);
+        lifeNoticeMapper.insert(lifeNotice);
+    }
+
+
     /**
     /**
      * 判断并获取商品封面图(若第一个链接是视频,则取第一帧)
      * 判断并获取商品封面图(若第一个链接是视频,则取第一帧)
      * @param imgUrl 商品图片/视频链接列表
      * @param imgUrl 商品图片/视频链接列表
@@ -609,6 +664,23 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
         return result;
         return result;
     }
     }
 
 
+    @Override
+    public List<SecondGoods> getGoodsListByUserId(Integer userId, Integer goodsStatus) {
+        // 获取商品屏蔽列表
+        List<SecondGoods> shieldedGoodsList = getShieldedGoodsList(userId);
+        // 提取屏蔽商品ID
+        List<Integer> shieldedGoodsIds = shieldedGoodsList.stream()
+                .map(SecondGoods::getId)
+                .collect(Collectors.toList());
+
+        LambdaQueryWrapper<SecondGoods> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(SecondGoods::getUserId, userId);
+        queryWrapper.eq(SecondGoods::getGoodsStatus, goodsStatus);
+        queryWrapper.notIn(CollectionUtil.isNotEmpty(shieldedGoodsIds), SecondGoods::getId, shieldedGoodsIds);
+        queryWrapper.orderByDesc(SecondGoods::getReleaseTime);
+        return secondGoodsMapper.selectList(queryWrapper);
+    }
+
     /**
     /**
      * 查询搜索结果
      * 查询搜索结果
      * @param page 分页参数
      * @param page 分页参数

+ 69 - 14
alien-second/src/main/java/shop/alien/second/service/impl/SecondTradeRecordServiceImpl.java

@@ -1,5 +1,6 @@
 package shop.alien.second.service.impl;
 package shop.alien.second.service.impl;
 
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.RequiredArgsConstructor;
 import lombok.RequiredArgsConstructor;
@@ -7,6 +8,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import shop.alien.entity.second.SecondGoods;
 import shop.alien.entity.second.SecondGoods;
 import shop.alien.entity.second.SecondTradeRecord;
 import shop.alien.entity.second.SecondTradeRecord;
+import shop.alien.mapper.LifeMessageMapper;
 import shop.alien.mapper.second.SecondGoodsMapper;
 import shop.alien.mapper.second.SecondGoodsMapper;
 import shop.alien.mapper.second.SecondTradeRecordMapper;
 import shop.alien.mapper.second.SecondTradeRecordMapper;
 import shop.alien.second.service.SecondTradeRecordService;
 import shop.alien.second.service.SecondTradeRecordService;
@@ -30,9 +32,10 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
 
 
     private final SecondTradeRecordMapper secondTradeRecordMapper;
     private final SecondTradeRecordMapper secondTradeRecordMapper;
     private final SecondGoodsMapper secondGoodsMapper;
     private final SecondGoodsMapper secondGoodsMapper;
+    private final LifeMessageMapper lifeMessageMapper;
 
 
     @Override
     @Override
-    public List<SecondTradeRecord> getTradeRecord(int sideId) {
+    public List<SecondTradeRecord> getTradeRecord(int sideId) throws Exception {
         try {
         try {
             int userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
             int userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
             QueryWrapper<SecondTradeRecord> wrapper = new QueryWrapper<>();
             QueryWrapper<SecondTradeRecord> wrapper = new QueryWrapper<>();
@@ -40,8 +43,8 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
             wrapper.orderByDesc("created_time");
             wrapper.orderByDesc("created_time");
             return secondTradeRecordMapper.selectList(wrapper);
             return secondTradeRecordMapper.selectList(wrapper);
         } catch (Exception e) {
         } catch (Exception e) {
-            log.error("SecondTradeRecordServiceImpl.getTradeRecord===", e.fillInStackTrace());
-            return null;
+            log.error("SecondTradeRecordServiceImpl.getTradeRecord Error Mgs={}", e.getMessage());
+            throw new Exception(e);
         }
         }
     }
     }
 
 
@@ -51,7 +54,7 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
      * @return 操作结果
      * @return 操作结果
      */
      */
     @Override
     @Override
-    public boolean createTrade(SecondTradeRecord entity) {
+    public boolean createTrade(SecondTradeRecord entity) throws Exception {
         try {
         try {
             secondTradeRecordMapper.insert(entity);
             secondTradeRecordMapper.insert(entity);
             SecondGoods goods = new SecondGoods();
             SecondGoods goods = new SecondGoods();
@@ -60,34 +63,55 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
             secondGoodsMapper.updateById(goods);
             secondGoodsMapper.updateById(goods);
             return true;
             return true;
         } catch (Exception e) {
         } catch (Exception e) {
-            log.error("SecondTradeRecordServiceImpl.createTrade===", e.fillInStackTrace());
+            log.error("SecondTradeRecordServiceImpl.createTrade Error Mgs={}", e.getMessage());
+            throw new Exception(e);
         }
         }
-        return false;
     }
     }
 
 
     @Override
     @Override
-    public boolean tradeSignin(int tradeId) {
+    public boolean tradeSignIn(int tradeId, int messageId) throws Exception {
         try {
         try {
             int userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
             int userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
             SecondTradeRecord tradeRecord = secondTradeRecordMapper.selectById(tradeId);
             SecondTradeRecord tradeRecord = secondTradeRecordMapper.selectById(tradeId);
             SecondTradeRecord record = new SecondTradeRecord();
             SecondTradeRecord record = new SecondTradeRecord();
             record.setId(tradeId);
             record.setId(tradeId);
             if (userId == tradeRecord.getBuyerId()) {
             if (userId == tradeRecord.getBuyerId()) {
-                record.setBuyerSignin(1);
+                record.setBuyerSignIn(1);
             } else if (userId == tradeRecord.getSellerId()) {
             } else if (userId == tradeRecord.getSellerId()) {
-                record.setSellerSignin(1);
+                record.setSellerSignIn(1);
             } else {
             } else {
                 return false;
                 return false;
             }
             }
             secondTradeRecordMapper.updateById(record);
             secondTradeRecordMapper.updateById(record);
+
+//            LifeMessage message = new LifeMessage();
+//            message.setId(messageId);
+//            message.setContent(messageContent);
+//            message.setType("6");
+//            message.setCreatedTime(new Date());
+//            lifeMessageMapper.updateById(message);
+            lifeMessageMapper.deleteById(messageId);
+
+            return true;
+        } catch (Exception e) {
+            log.error("SecondTradeRecordServiceImpl.tradeSignIn Error Mgs={}", e.getMessage());
+            throw new Exception(e);
+        }
+    }
+
+    @Override
+    public boolean tradeConfirm(int tradeId, int type, String evaluate) throws Exception {
+        try {
+
+            return true;
         } catch (Exception e) {
         } catch (Exception e) {
-            log.error("SecondTradeRecordServiceImpl.tradeSignin===", e.fillInStackTrace());
+            log.error("SecondTradeRecordServiceImpl.tradeConfirm Error Mgs={}", e.getMessage());
+            throw new Exception(e);
         }
         }
-        return true;
     }
     }
 
 
     @Override
     @Override
-    public boolean tradeConfirm(int tradeId, int type, String evaluate) {
+    public boolean tradeCompleteConfirm(int tradeId, int type, String evaluate) throws Exception {
         try {
         try {
             int userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
             int userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
             SecondTradeRecord tradeRecord = secondTradeRecordMapper.selectById(tradeId);
             SecondTradeRecord tradeRecord = secondTradeRecordMapper.selectById(tradeId);
@@ -104,9 +128,40 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
                 return false;
                 return false;
             }
             }
             secondTradeRecordMapper.updateById(record);
             secondTradeRecordMapper.updateById(record);
+            return true;
+        } catch (Exception e) {
+            log.error("SecondTradeRecordServiceImpl.tradeCCompleteConfirm Error Mgs={}", e.getMessage());
+            throw new Exception(e);
+        }
+    }
+
+    @Override
+    public boolean goodsTradeConfirm(int goodsId) throws Exception {
+        try {
+            LambdaQueryWrapper<SecondTradeRecord> queryWrapper = new LambdaQueryWrapper<>();
+            queryWrapper.eq(SecondTradeRecord::getGoodsId, goodsId);
+            queryWrapper.in(SecondTradeRecord::getTradeStatus, 0, 1);
+            return secondTradeRecordMapper.selectCount(queryWrapper) == 0;
+        } catch (Exception e) {
+            log.error("SecondTradeRecordServiceImpl.goodsTrade Error Mgs={}", e.getMessage());
+            throw new Exception(e);
+        }
+    }
+
+    @Override
+    public boolean cancelTrade(int tradeId, String cancelReason, String cancelReasonSupplement) throws Exception {
+        try {
+            int userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
+            SecondTradeRecord record = new SecondTradeRecord();
+            record.setId(tradeId);
+            record.setTradeStatus(3);
+            record.setCancelId(userId);
+            record.setCancelReason(cancelReason);
+            record.setCancelReasonSupplement(cancelReasonSupplement);
+            return secondTradeRecordMapper.updateById(record) > 0;
         } catch (Exception e) {
         } catch (Exception e) {
-            log.error("SecondTradeRecordServiceImpl.tradeConfirm===", e.fillInStackTrace());
+            log.error("SecondTradeRecordServiceImpl.cancelTrade Error Mgs={}", e.getMessage());
+            throw new Exception(e);
         }
         }
-        return true;
     }
     }
 }
 }

+ 16 - 0
alien-store/src/main/java/shop/alien/store/config/BaseRedisService.java

@@ -4,8 +4,11 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.geo.*;
 import org.springframework.data.geo.*;
 import org.springframework.data.redis.connection.RedisGeoCommands;
 import org.springframework.data.redis.connection.RedisGeoCommands;
 import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.data.redis.core.script.DefaultRedisScript;
+import org.springframework.data.redis.core.script.RedisScript;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
 
 
+import java.util.Collections;
 import java.util.List;
 import java.util.List;
 import java.util.Set;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeUnit;
@@ -32,6 +35,19 @@ public class BaseRedisService {
     }
     }
 
 
     /**
     /**
+     * 取出并删除列表中的所有元素(原子操作)
+     */
+    public List<String> popBatchFromList(String key) {
+        String luaScript =
+                "local elements = redis.call('LRANGE', KEYS[1], 0, -1) " +
+                        "redis.call('DEL', KEYS[1]) " +
+                        "return elements ";
+
+        RedisScript<List> script = RedisScript.of(luaScript, List.class);
+        return stringRedisTemplate.execute(script, Collections.singletonList(key));
+    }
+
+    /**
      * 添加List, 所有
      * 添加List, 所有
      *
      *
      * @param key   键
      * @param key   键

+ 21 - 0
alien-store/src/main/java/shop/alien/store/config/SpringContext.java

@@ -0,0 +1,21 @@
+package shop.alien.store.config;
+
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SpringContext implements ApplicationContextAware {
+
+    private static ApplicationContext context;
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        context = applicationContext;
+    }
+
+    public static <T> T getBean(Class<T> beanClass) {
+        return context.getBean(beanClass);
+    }
+}

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

@@ -1,12 +1,9 @@
 package shop.alien.store.config;
 package shop.alien.store.config;
 
 
 import com.alibaba.fastjson2.JSONObject;
 import com.alibaba.fastjson2.JSONObject;
-import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
 import org.springframework.util.ObjectUtils;
 import org.springframework.util.ObjectUtils;
-import shop.alien.entity.result.R;
 import shop.alien.entity.store.LifeMessage;
 import shop.alien.entity.store.LifeMessage;
 import shop.alien.entity.store.vo.WebsocketVo;
 import shop.alien.entity.store.vo.WebsocketVo;
 import shop.alien.mapper.LifeMessageMapper;
 import shop.alien.mapper.LifeMessageMapper;
@@ -28,8 +25,9 @@ import java.util.concurrent.ConcurrentHashMap;
 @ServerEndpoint(value = "/socket/{sendId}")
 @ServerEndpoint(value = "/socket/{sendId}")
 public class WebSocketProcess {
 public class WebSocketProcess {
 
 
-    @Autowired
-    private LifeMessageMapper lifeMessageMapper;
+    private final LifeMessageMapper lifeMessageMapper = SpringContext.getBean(LifeMessageMapper.class);
+
+    private final BaseRedisService baseRedisService = SpringContext.getBean(BaseRedisService.class);
 
 
     /*
     /*
      * 持有每个webSocket对象,以key-value存储到线程安全ConcurrentHashMap,
      * 持有每个webSocket对象,以key-value存储到线程安全ConcurrentHashMap,
@@ -49,7 +47,7 @@ public class WebSocketProcess {
         //每新建立一个连接,就把当前客户id为key,this为value存储到map中
         //每新建立一个连接,就把当前客户id为key,this为value存储到map中
         this.session = session;
         this.session = session;
         concurrentHashMap.put(id, this);
         concurrentHashMap.put(id, this);
-        log.info("Open a websocket. id={}", id);
+        log.info("WebSocketProcess.onOpen() Open a websocket. id={}", id);
     }
     }
 
 
     /**
     /**
@@ -59,47 +57,52 @@ public class WebSocketProcess {
     public void onClose(Session session, @PathParam("sendId") String id) {
     public void onClose(Session session, @PathParam("sendId") String id) {
         //客户端连接关闭时,移除map中存储的键值对
         //客户端连接关闭时,移除map中存储的键值对
         concurrentHashMap.remove(id);
         concurrentHashMap.remove(id);
-        log.info("close a websocket, concurrentHashMap remove sessionId= {}", id);
+        log.info("WebSocketProcess.onClose() close a websocket, concurrentHashMap remove sessionId= {}", id);
+    }
+
+    /**
+     * 连接发生异常时候触发
+     */
+    @OnError
+    public void onError(Session session, Throwable error) {
+        log.error("WebSocketProcess.onError() Error Mgs=", error);
     }
     }
 
 
     /**
     /**
      * 接收到客户端消息时触发
      * 接收到客户端消息时触发
      */
      */
     @OnMessage
     @OnMessage
-    public R<String> onMessage(String message) throws Exception {
+    public void onMessage(String message) throws Exception {
         try {
         try {
+            // 过滤心跳
             WebsocketVo websocketVo = JSONObject.parseObject(message, WebsocketVo.class);
             WebsocketVo websocketVo = JSONObject.parseObject(message, WebsocketVo.class);
-            JSONObject jsonObject = new JSONObject();
-            jsonObject.put("type", websocketVo.getType());
-            jsonObject.put("text", websocketVo.getText());
-            sendMessage(websocketVo.getReceiverId(), jsonObject.toJSONString());
+            if (null == websocketVo || "heartbeat".equals(websocketVo.getCategory())) return;
+
+            // 记录已读消息id
+            if ("receipt".equals(websocketVo.getCategory())) {
+                baseRedisService.setListRight("readMessageIdKey", String.valueOf(websocketVo.getMessageId()));
+                return;
+            }
 
 
+            // 保存消息记录
             LifeMessage lifeMessage = new LifeMessage();
             LifeMessage lifeMessage = new LifeMessage();
             lifeMessage.setSenderId(websocketVo.getSenderId());
             lifeMessage.setSenderId(websocketVo.getSenderId());
             lifeMessage.setReceiverId(websocketVo.getReceiverId());
             lifeMessage.setReceiverId(websocketVo.getReceiverId());
             lifeMessage.setContent(websocketVo.getText());
             lifeMessage.setContent(websocketVo.getText());
             lifeMessage.setType(websocketVo.getType());
             lifeMessage.setType(websocketVo.getType());
             lifeMessageMapper.insert(lifeMessage);
             lifeMessageMapper.insert(lifeMessage);
-            return R.success("发送成功");
+
+            // 发送消息
+            websocketVo.setMessageId(lifeMessage.getId());
+            websocketVo.setCategory("message");
+            sendMessage(websocketVo.getReceiverId(), JSONObject.from(websocketVo).toJSONString());
         } catch (Exception e) {
         } catch (Exception e) {
-            log.error("WebSocketController_sendMsgToClientById Error Mgs={}", e.getMessage());
+            log.error("WebSocketProcess.onMessage() Error Mgs={}", e.getMessage());
         }
         }
-        return R.fail("发送失败");
-    }
-
-    /**
-     * 连接发生异常时候触发
-     */
-    @OnError
-    public void onError(Session session, Throwable error) {
-        log.error("Error while websocket. ", error);
     }
     }
 
 
     /**
     /**
      * 发送消息到指定客户端
      * 发送消息到指定客户端
-     *
-     * @param id
-     * @param message
      */
      */
     public void sendMessage(String id, String message) throws Exception {
     public void sendMessage(String id, String message) throws Exception {
         //根据id,从map中获取存储的webSocket对象
         //根据id,从map中获取存储的webSocket对象
@@ -109,10 +112,10 @@ public class WebSocketProcess {
             if (webSocketProcess.session.isOpen()) {
             if (webSocketProcess.session.isOpen()) {
                 webSocketProcess.session.getBasicRemote().sendText(message);
                 webSocketProcess.session.getBasicRemote().sendText(message);
             } else {
             } else {
-                log.error("websocket session={} is closed ", id);
+                log.error("WebSocketProcess.sendMessage() websocket session={} is closed ", id);
             }
             }
         } else {
         } else {
-            log.error("websocket session={} is not exit ", id);
+            log.error("WebSocketProcess.sendMessage() websocket session={} is not exit ", id);
         }
         }
     }
     }
 
 
@@ -120,7 +123,6 @@ public class WebSocketProcess {
      * 发送消息到所有客户端
      * 发送消息到所有客户端
      */
      */
     public void sendAllMessage(String msg) throws Exception {
     public void sendAllMessage(String msg) throws Exception {
-//        log.info("online client count={}", concurrentHashMap.size());
         Set<Map.Entry<String, WebSocketProcess>> entries = concurrentHashMap.entrySet();
         Set<Map.Entry<String, WebSocketProcess>> entries = concurrentHashMap.entrySet();
         for (Map.Entry<String, WebSocketProcess> entry : entries) {
         for (Map.Entry<String, WebSocketProcess> entry : entries) {
             String cid = entry.getKey();
             String cid = entry.getKey();

+ 19 - 8
alien-store/src/main/java/shop/alien/store/controller/AliController.java

@@ -1,20 +1,18 @@
 package shop.alien.store.controller;
 package shop.alien.store.controller;
 
 
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
-import com.alipay.api.AlipayApiException;
 import io.swagger.annotations.*;
 import io.swagger.annotations.*;
 import lombok.RequiredArgsConstructor;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.bind.annotation.CrossOrigin;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 import shop.alien.entity.result.R;
 import shop.alien.entity.result.R;
 import shop.alien.store.service.AliService;
 import shop.alien.store.service.AliService;
-import shop.alien.util.common.AlipayTradeAppPay;
-import shop.alien.util.common.AlipayTradeRefund;
 import shop.alien.store.util.ali.AliApi;
 import shop.alien.store.util.ali.AliApi;
 import shop.alien.store.util.ali.AliSms;
 import shop.alien.store.util.ali.AliSms;
+import shop.alien.util.ali.AliOSSUtil;
+import shop.alien.util.common.AlipayTradeAppPay;
+import shop.alien.util.common.AlipayTradeRefund;
 
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpServletResponse;
@@ -43,6 +41,8 @@ public class AliController {
 
 
     private final AlipayTradeRefund alipayTradeRefund;
     private final AlipayTradeRefund alipayTradeRefund;
 
 
+    private final AliOSSUtil aliOSSUtil;
+
     @ApiOperation("阿里回调")
     @ApiOperation("阿里回调")
     @ApiOperationSupport(order = 1)
     @ApiOperationSupport(order = 1)
     @GetMapping("/notify")
     @GetMapping("/notify")
@@ -182,8 +182,19 @@ public class AliController {
     }
     }
 
 
     @GetMapping("/returnPay")
     @GetMapping("/returnPay")
-    public void returnPay(String orderNo, String refundAmount) throws AlipayApiException {
+    public void returnPay(String orderNo, String refundAmount) {
         alipayTradeRefund.processRefund(orderNo, refundAmount, "退款");
         alipayTradeRefund.processRefund(orderNo, refundAmount, "退款");
     }
     }
 
 
+    @ApiOperation("跳转支付宝人脸核身查询记录")
+    @ApiOperationSupport(order = 11)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "file", value = "文件", dataType = "File", paramType = "query", required = true),
+            @ApiImplicitParam(name = "ossFilePath", value = "oss中的文件路径", dataType = "String", paramType = "query", required = true)
+    })
+    @GetMapping("/uploadFile")
+    public R<String> uploadFile(@RequestParam(value = "file") MultipartFile multipartFile, @RequestParam(value = "ossFilePath") String ossFilePath) {
+        return R.data(aliOSSUtil.uploadFile(multipartFile, ossFilePath));
+    }
+
 }
 }

+ 3 - 3
alien-store/src/main/java/shop/alien/store/controller/LifeGroupPackageController.java

@@ -118,7 +118,7 @@ public class LifeGroupPackageController {
             @RequestParam("status") String status,
             @RequestParam("status") String status,
             @RequestParam("couponCode") String couponCode,
             @RequestParam("couponCode") String couponCode,
             @RequestParam("name") String name) {
             @RequestParam("name") String name) {
-        log.info("LifeGroupPackageController.getGroupPackageList?pageNum={},pageSize={},storeId={},status={}", storeId, status, page, size);
+        log.info("LifeGroupPackageController.getGroupPackageList?pageNum={}&pageSize={}&storeId={}&status={}", page, size, storeId, status);
         return R.data(lifeGroupPackageService.getGroupPackageList(page, size, storeId, status, couponCode, name));
         return R.data(lifeGroupPackageService.getGroupPackageList(page, size, storeId, status, couponCode, name));
     }
     }
 
 
@@ -157,14 +157,14 @@ public class LifeGroupPackageController {
     @GetMapping("/getGroupPackageDetail")
     @GetMapping("/getGroupPackageDetail")
     private R<Map<String, Object>> getGroupPackageDetail(@RequestParam("id") String id, @RequestParam("userId") String userId) {
     private R<Map<String, Object>> getGroupPackageDetail(@RequestParam("id") String id, @RequestParam("userId") String userId) {
         log.info("LifeGroupPackageController.getGroupPackageDetail?id={}&userId={}", id, userId);
         log.info("LifeGroupPackageController.getGroupPackageDetail?id={}&userId={}", id, userId);
-        return R.data(lifeGroupPackageService.getGroupPackageDetail(id,userId));
+        return R.data(lifeGroupPackageService.getGroupPackageDetail(id, userId));
     }
     }
 
 
     @ApiOperation("酒店团购详情")
     @ApiOperation("酒店团购详情")
     @GetMapping("/getGroupHotelPackageDetail")
     @GetMapping("/getGroupHotelPackageDetail")
     private R<Map<String, Object>> getGroupHotelPackageDetail(@RequestParam("id") String id, @RequestParam("userId") String userId) {
     private R<Map<String, Object>> getGroupHotelPackageDetail(@RequestParam("id") String id, @RequestParam("userId") String userId) {
         log.info("LifeGroupPackageController.getGroupHotelPackageDetail?id={}&userId={}", id, userId);
         log.info("LifeGroupPackageController.getGroupHotelPackageDetail?id={}&userId={}", id, userId);
-        return R.data(lifeGroupPackageService.getGroupHotelPackageDetail(id,userId));
+        return R.data(lifeGroupPackageService.getGroupHotelPackageDetail(id, userId));
     }
     }
 
 
     @ApiOperation("猜你喜欢")
     @ApiOperation("猜你喜欢")

+ 15 - 5
alien-store/src/main/java/shop/alien/store/controller/LifeMessageController.java

@@ -6,6 +6,7 @@ import io.swagger.annotations.*;
 import io.swagger.models.auth.In;
 import io.swagger.models.auth.In;
 import lombok.RequiredArgsConstructor;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.lang.Nullable;
 import org.springframework.messaging.handler.annotation.MessageMapping;
 import org.springframework.messaging.handler.annotation.MessageMapping;
 import org.springframework.messaging.handler.annotation.SendTo;
 import org.springframework.messaging.handler.annotation.SendTo;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
@@ -14,6 +15,7 @@ import shop.alien.entity.store.LifeMessage;
 import shop.alien.entity.store.vo.LifeMessageVo;
 import shop.alien.entity.store.vo.LifeMessageVo;
 import shop.alien.mapper.LifeMessageMapper;
 import shop.alien.mapper.LifeMessageMapper;
 import shop.alien.store.service.LifeMessageService;
 import shop.alien.store.service.LifeMessageService;
+import shop.alien.store.task.ScheduledTask;
 
 
 import java.util.List;
 import java.util.List;
 
 
@@ -29,18 +31,20 @@ import java.util.List;
 public class LifeMessageController {
 public class LifeMessageController {
 
 
     private final LifeMessageService lifeMessageService;
     private final LifeMessageService lifeMessageService;
+    private final ScheduledTask scheduledTask;
 
 
     @ApiOperation("消息列表")
     @ApiOperation("消息列表")
     @ApiOperationSupport(order = 1)
     @ApiOperationSupport(order = 1)
     @ApiImplicitParams({
     @ApiImplicitParams({
             @ApiImplicitParam(name = "receiverId", value = "当前登录人", dataType = "String", paramType = "query"),
             @ApiImplicitParam(name = "receiverId", value = "当前登录人", dataType = "String", paramType = "query"),
-            @ApiImplicitParam(name = "friendType", value = "聊天类型 1-聊过 2-未聊过", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "friendType", value = "聊天类型  0-搜索 1-聊过 2-未聊过", dataType = "Integer", paramType = "query"),
             @ApiImplicitParam(name = "search", value = "搜索字段", dataType = "Integer", paramType = "query")})
             @ApiImplicitParam(name = "search", value = "搜索字段", dataType = "Integer", paramType = "query")})
     @GetMapping("/getMessageList")
     @GetMapping("/getMessageList")
     public R<List<LifeMessageVo>> getMessageList(@RequestParam String receiverId,
     public R<List<LifeMessageVo>> getMessageList(@RequestParam String receiverId,
                                                   @RequestParam int friendType,
                                                   @RequestParam int friendType,
-                                                  @RequestParam String search) throws Exception {
+                                                  String search) throws Exception {
         log.info("LifeMessageController.getMessageList?receiverId={}, friendType={}, search={}", receiverId, friendType, search);
         log.info("LifeMessageController.getMessageList?receiverId={}, friendType={}, search={}", receiverId, friendType, search);
+        scheduledTask.secondTradeRemind();
         return R.data(lifeMessageService.getMessageList(receiverId, friendType, search));
         return R.data(lifeMessageService.getMessageList(receiverId, friendType, search));
     }
     }
 
 
@@ -64,7 +68,9 @@ public class LifeMessageController {
 
 
     @ApiOperation("消息详情")
     @ApiOperation("消息详情")
     @ApiOperationSupport(order = 4)
     @ApiOperationSupport(order = 4)
-    @ApiImplicitParams({@ApiImplicitParam(name = "当前登录人", value = "receiverId", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "senderId", value = "聊天对方", dataType = "String", paramType = "query")})
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "当前登录人", value = "receiverId", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "senderId", value = "聊天对方", dataType = "String", paramType = "query")})
     @GetMapping("/getMessageListByReceiverId")
     @GetMapping("/getMessageListByReceiverId")
     public R<List<LifeMessageVo>> getMessageListByReceiverId(@RequestParam String receiverId, @RequestParam String senderId) throws Exception {
     public R<List<LifeMessageVo>> getMessageListByReceiverId(@RequestParam String receiverId, @RequestParam String senderId) throws Exception {
         log.info("LifeMessageController.getMessageListByReceiverId?receiverId={}, senderId={}", receiverId, senderId);
         log.info("LifeMessageController.getMessageListByReceiverId?receiverId={}, senderId={}", receiverId, senderId);
@@ -73,7 +79,9 @@ public class LifeMessageController {
 
 
     @ApiOperation("消息已读")
     @ApiOperation("消息已读")
     @ApiOperationSupport(order = 5)
     @ApiOperationSupport(order = 5)
-    @ApiImplicitParams({@ApiImplicitParam(name = "receiverId", value = "当前登录人", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "senderId", value = "聊天对方", dataType = "String", paramType = "query")})
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "receiverId", value = "当前登录人", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "senderId", value = "聊天对方", dataType = "String", paramType = "query")})
     @GetMapping("/read")
     @GetMapping("/read")
     public R<Boolean> read(@RequestParam String receiverId, @RequestParam String senderId) throws Exception {
     public R<Boolean> read(@RequestParam String receiverId, @RequestParam String senderId) throws Exception {
         log.info("LifeMessageController.read?receiverId={}, senderId={}", receiverId, senderId);
         log.info("LifeMessageController.read?receiverId={}, senderId={}", receiverId, senderId);
@@ -83,7 +91,9 @@ public class LifeMessageController {
 
 
     @ApiOperation("删除消息")
     @ApiOperation("删除消息")
     @ApiOperationSupport(order = 6)
     @ApiOperationSupport(order = 6)
-    @ApiImplicitParams({@ApiImplicitParam(name = "senderId", value = "聊天对方", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "receiverId", value = "当前登录人", dataType = "String", paramType = "query")})
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "senderId", value = "聊天对方", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "receiverId", value = "当前登录人", dataType = "String", paramType = "query")})
     @GetMapping("/deleteMessageByPhoneId")
     @GetMapping("/deleteMessageByPhoneId")
     public R<Integer> deleteMessageByPhoneId(@RequestParam String senderId, @RequestParam String receiverId) throws Exception {
     public R<Integer> deleteMessageByPhoneId(@RequestParam String senderId, @RequestParam String receiverId) throws Exception {
         log.info("LifeMessageController.deleteMessageByPhoneId?senderId={},receiverId={}", senderId, receiverId);
         log.info("LifeMessageController.deleteMessageByPhoneId?senderId={},receiverId={}", senderId, receiverId);

+ 6 - 6
alien-store/src/main/java/shop/alien/store/controller/StoreFileUploadController.java

@@ -32,7 +32,7 @@ public class StoreFileUploadController {
 
 
     private final FileUploadUtil fileUpload;
     private final FileUploadUtil fileUpload;
 
 
-    @ApiOperation("单个文件上传")
+    @ApiOperation("单个文件上传(图片或视频,返回路径)")
     @ApiOperationSupport(order = 1)
     @ApiOperationSupport(order = 1)
     @PostMapping("/upload")
     @PostMapping("/upload")
     public R<String> upload(@RequestParam("file") MultipartFile file) {
     public R<String> upload(@RequestParam("file") MultipartFile file) {
@@ -40,7 +40,7 @@ public class StoreFileUploadController {
         return R.data(fileUpload.uploadOneFile(file));
         return R.data(fileUpload.uploadOneFile(file));
     }
     }
 
 
-    @ApiOperation("多个文件上传")
+    @ApiOperation("多个文件上传(图片或视频,视频会截取第一秒图片,返回路径)")
     @ApiOperationSupport(order = 2)
     @ApiOperationSupport(order = 2)
     @PostMapping("/uploadMore")
     @PostMapping("/uploadMore")
     public R<List<String>> uploadMore(MultipartRequest multipartRequest) {
     public R<List<String>> uploadMore(MultipartRequest multipartRequest) {
@@ -48,19 +48,19 @@ public class StoreFileUploadController {
         return R.data(fileUpload.uploadMoreFile(multipartRequest));
         return R.data(fileUpload.uploadMoreFile(multipartRequest));
     }
     }
 
 
-    @ApiOperation("图片上传, 返回图片id")
+    @ApiOperation(value = "图片上传(其实也可以传视频,不会截图), 返回图片id", notes = "文件格式: file_0,file_1, list格式: [{\"storeId\":1,\"imgType\":3,\"imgDescription\":\"菜品1\",\"imgSort\":1},{\"storeId\":1,\"imgType\":3,\"imgDescription\":\"菜品2\",\"imgSort\":2}]")
     @ApiOperationSupport(order = 3)
     @ApiOperationSupport(order = 3)
     @PostMapping("/uploadImg")
     @PostMapping("/uploadImg")
     public R<List<Integer>> uploadImg(MultipartRequest multipartRequest, @RequestParam("list") String list) {
     public R<List<Integer>> uploadImg(MultipartRequest multipartRequest, @RequestParam("list") String list) {
         return R.data(fileUpload.uploadImg(multipartRequest, list));
         return R.data(fileUpload.uploadImg(multipartRequest, list));
     }
     }
 
 
-    @ApiOperation("上传app")
+    @ApiOperation("上传app(格式包含apk,ipa,wgt,返回路径)")
     @ApiOperationSupport(order = 4)
     @ApiOperationSupport(order = 4)
     @PostMapping("/uploadApp")
     @PostMapping("/uploadApp")
-    public R<Boolean> uploadApp(@RequestParam("file") MultipartFile file) {
+    public R<String> uploadApp(@RequestParam("file") MultipartFile file) {
         log.info("StoreFileUploadController.uploadApp fileName:{}", file.getOriginalFilename());
         log.info("StoreFileUploadController.uploadApp fileName:{}", file.getOriginalFilename());
-        return fileUpload.uploadApp(file);
+        return R.data(fileUpload.uploadApp(file));
     }
     }
 
 
 }
 }

+ 16 - 4
alien-store/src/main/java/shop/alien/store/controller/StoreInfoController.java

@@ -112,6 +112,17 @@ public class StoreInfoController {
         return R.fail("失败");
         return R.fail("失败");
     }
     }
 
 
+    @ApiOperation("web修改门店抽成")
+    @ApiOperationSupport(order = 3)
+    @PostMapping("/updateStoreCommissionRate")
+    public R updateStoreCommissionRate(@RequestBody StoreInfoDto storeInfoDto) {
+        log.info("StoreInfoController.updateStoreCommissionRate?storeInfoDto={}", storeInfoDto);
+        if (storeInfoService.editStoreCommissionRate(storeInfoDto) >  0) {
+            return R.data("成功");
+        }
+        return R.fail("失败");
+    }
+
     @ApiOperation("web端删除门店")
     @ApiOperation("web端删除门店")
     @ApiOperationSupport(order = 3)
     @ApiOperationSupport(order = 3)
     @PostMapping("/deleteStoreInfo")
     @PostMapping("/deleteStoreInfo")
@@ -342,12 +353,13 @@ public class StoreInfoController {
     @GetMapping("/approveStoreInfo")
     @GetMapping("/approveStoreInfo")
     @ApiImplicitParams({
     @ApiImplicitParams({
             @ApiImplicitParam(name = "id", value = "门店id", dataType = "String", paramType = "query"),
             @ApiImplicitParam(name = "id", value = "门店id", dataType = "String", paramType = "query"),
-            @ApiImplicitParam(name = "approvalStatus", value = "审批状态(1:审批成功,2:审批失败)", dataType = "int", paramType = "query")
+            @ApiImplicitParam(name = "approvalStatus", value = "审批状态(1:审批成功,2:审批失败)", dataType = "int", paramType = "query"),
+            @ApiImplicitParam(name = "reason", value = "原因", dataType = "String", paramType = "query")
     })
     })
     @ResponseBody
     @ResponseBody
-    public R approveStoreInfo(@RequestParam("id") String id, @RequestParam("approvalStatus") Integer approvalStatus) {
-        log.info("StoreInfoController.approveStoreInfo?id={}&approvalStatus={}", id, approvalStatus);
-        storeInfoService.approveStoreInfo(id, approvalStatus);
+    public R approveStoreInfo(@RequestParam("id") String id, @RequestParam("approvalStatus") Integer approvalStatus,@RequestParam(value = "reason",required = false) String reason) {
+        log.info("StoreInfoController.approveStoreInfo?id={}&approvalStatus={}&reason={}", id, approvalStatus,reason);
+        storeInfoService.approveStoreInfo(id, approvalStatus, reason);
         return R.success("审批完成");
         return R.success("审批完成");
     }
     }
 
 

+ 18 - 6
alien-store/src/main/java/shop/alien/store/controller/StoreUserController.java

@@ -96,22 +96,34 @@ public class StoreUserController {
     @ApiImplicitParams({@ApiImplicitParam(name = "phone", value = "手机号", dataType = "String", paramType = "query", required = true),
     @ApiImplicitParams({@ApiImplicitParam(name = "phone", value = "手机号", dataType = "String", paramType = "query", required = true),
             @ApiImplicitParam(name = "newPhone", value = "新手机号", dataType = "String", paramType = "query"),
             @ApiImplicitParam(name = "newPhone", value = "新手机号", dataType = "String", paramType = "query"),
             @ApiImplicitParam(name = "oldPassword", 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 = "confirmNewPassword", value = "新密码确认", dataType = "String", paramType = "query", required = true),
+            @ApiImplicitParam(name = "newPassword", value = "新密码", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "confirmNewPassword", value = "新密码确认", dataType = "String", paramType = "query"),
             @ApiImplicitParam(name = "verificationCode", 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)})
             @ApiImplicitParam(name = "type", value = "类型:0:忘记密码,1:修改密码,2:更换绑定手机号", dataType = "Integer", paramType = "query", required = true)})
     @GetMapping("/updatePassword")
     @GetMapping("/updatePassword")
-    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);
+    public R<Boolean> updatePassword(String phone,String newPhone, String oldPassword, String newPassword, String confirmNewPassword,String verificationCode,String newPhoneVerificationCode, Integer type) {
+        log.info("StoreUserController.updatePassword?phone={}&newPhone&oldPassword={}&newPassword={}&confirmNewPassword={}&verificationCode={}&type={}", phone, newPhone, oldPassword, newPassword, confirmNewPassword, verificationCode,  type);
         boolean flag = false;
         boolean flag = false;
         flag = storeUserService.forgetOrModifyPassword(phone, newPhone, oldPassword, newPassword, confirmNewPassword, verificationCode, type);
         flag = storeUserService.forgetOrModifyPassword(phone, newPhone, oldPassword, newPassword, confirmNewPassword, verificationCode, type);
         if(flag){
         if(flag){
-            return R.success("密码修改成功");
+            return R.success("修改成功");
         }else {
         }else {
-            return R.success("密码修改失败");
+            return R.success("修改失败");
         }
         }
     }
     }
 
 
+    @ApiOperation("更换绑定手机号效验原密码或验证码")
+    @ApiOperationSupport(order = 2)
+    @ApiImplicitParams({@ApiImplicitParam(name = "phone", value = "手机号", dataType = "String", paramType = "query", required = true),
+            @ApiImplicitParam(name = "oldPassword", value = "旧密码", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "verificationCode", value = "验证码", dataType = "String", paramType = "query")})
+    @GetMapping("/changePhoneVerification")
+    public R<Map<String, String>> changePhoneVerification(String phone, String oldPassword, String verificationCode) {
+        log.info("StoreUserController.changePhoneVerification?phone={}&oldPassword={}&verificationCode={}", phone,  oldPassword,  verificationCode);
+        return R.data(storeUserService.changePhoneVerification(phone, oldPassword, verificationCode));
+
+    }
+
     @ApiOperation("修改用户信息")
     @ApiOperation("修改用户信息")
     @ApiOperationSupport(order = 3)
     @ApiOperationSupport(order = 3)
     @PostMapping("/setUserInfo")
     @PostMapping("/setUserInfo")

+ 4 - 4
alien-store/src/main/java/shop/alien/store/job/StoreMembershipCardJob.java

@@ -130,10 +130,10 @@ public class StoreMembershipCardJob {
             if (null != storeUser.getLogoutTime()) {
             if (null != storeUser.getLogoutTime()) {
                 // 获取申请注销时间
                 // 获取申请注销时间
                 Date logoutTime = storeUser.getLogoutTime();
                 Date logoutTime = storeUser.getLogoutTime();
-                // 获取申请注销 7 天后的时间
+                // 获取申请注销 8 天后的时间
                 Calendar calendar = Calendar.getInstance();
                 Calendar calendar = Calendar.getInstance();
                 calendar.setTime(logoutTime);
                 calendar.setTime(logoutTime);
-                calendar.add(Calendar.DAY_OF_YEAR, 7);
+                calendar.add(Calendar.DAY_OF_YEAR, 8);
                 Date sevenDay = calendar.getTime();
                 Date sevenDay = calendar.getTime();
                 // 获取当前时间
                 // 获取当前时间
                 Date date = new Date();
                 Date date = new Date();
@@ -151,10 +151,10 @@ public class StoreMembershipCardJob {
             if (null != storeInfo.getLogoutTime()) {
             if (null != storeInfo.getLogoutTime()) {
                 // 获取申请注销时间
                 // 获取申请注销时间
                 Date logoutTime = storeInfo.getLogoutTime();
                 Date logoutTime = storeInfo.getLogoutTime();
-                // 获取申请注销 7 天后的时间
+                // 获取申请注销 8 天后的时间
                 Calendar calendar = Calendar.getInstance();
                 Calendar calendar = Calendar.getInstance();
                 calendar.setTime(logoutTime);
                 calendar.setTime(logoutTime);
-                calendar.add(Calendar.DAY_OF_YEAR, 7);
+                calendar.add(Calendar.DAY_OF_YEAR, 8);
                 Date sevenDay = calendar.getTime();
                 Date sevenDay = calendar.getTime();
                 // 获取当前时间
                 // 获取当前时间
                 Date date = new Date();
                 Date date = new Date();

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

@@ -186,10 +186,6 @@ public class LifeUserDynamicsService extends ServiceImpl<LifeUserDynamicsMapper,
                 }
                 }
                 vo.setCommentCount(count);
                 vo.setCommentCount(count);
             }
             }
-            // 默认视频上传的imagePath正确,图片则取第一个
-            if(vo.getImagePath().contains(",") && !vo.getImagePath().contains(".mp4")){
-                vo.setImagePath(vo.getImagePath().split(",")[0]);
-            }
         }
         }
 
 
         // 如果phoneId不为空,处理黑名单逻辑,过滤掉被拉黑用户的动态
         // 如果phoneId不为空,处理黑名单逻辑,过滤掉被拉黑用户的动态
@@ -431,12 +427,6 @@ public class LifeUserDynamicsService extends ServiceImpl<LifeUserDynamicsMapper,
 
 
     public List<LifeUserDynamicsVo> getDianZanList(String phoneId) {
     public List<LifeUserDynamicsVo> getDianZanList(String phoneId) {
         List<LifeUserDynamicsVo> lifeUserDynamicsVos = lifeUserDynamicsMapper.selectDianZanList(phoneId);
         List<LifeUserDynamicsVo> lifeUserDynamicsVos = lifeUserDynamicsMapper.selectDianZanList(phoneId);
-        for (LifeUserDynamicsVo lifeUserDynamicsVo : lifeUserDynamicsVos) {
-            if(lifeUserDynamicsVo.getImagePath().contains(",") && !lifeUserDynamicsVo.getImagePath().contains(".mp4")){
-                lifeUserDynamicsVo.setImagePath(lifeUserDynamicsVo.getImagePath().split(",")[0]);
-            }
-        }
-
         return  lifeUserDynamicsVos;
         return  lifeUserDynamicsVos;
     }
     }
 }
 }

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

@@ -163,7 +163,7 @@ public interface StoreInfoService extends IService<StoreInfo> {
     /**
     /**
      * web端审批结果
      * web端审批结果
      */
      */
-    void approveStoreInfo(String storeId, Integer approvalStatus);
+    void approveStoreInfo(String storeId, Integer approvalStatus, String reason);
 
 
     /**
     /**
      * web端导出商铺信息结果
      * web端导出商铺信息结果
@@ -206,4 +206,12 @@ public interface StoreInfoService extends IService<StoreInfo> {
      * @return List<StoreInfo>
      * @return List<StoreInfo>
      */
      */
     List<StoreInfo> getStoreInfoByStoreTel(String storeTel);
     List<StoreInfo> getStoreInfoByStoreTel(String storeTel);
+
+    /**
+     * 修改店铺佣金比率
+     *
+     * @param storeInfoDto
+     * @return
+     */
+    int editStoreCommissionRate(StoreInfoDto storeInfoDto);
 }
 }

+ 11 - 2
alien-store/src/main/java/shop/alien/store/service/StoreUserService.java

@@ -62,7 +62,16 @@ public interface StoreUserService extends IService<StoreUser> {
      * @param type 类型
      * @param type 类型
      * @return boolean
      * @return boolean
      */
      */
-    boolean forgetOrModifyPassword(String phone, String newPhone, String oldPassword, String newPassword,String confirmNewPassword,String verificationCode, Integer type);
+    boolean forgetOrModifyPassword(String phone, String newPhone, String oldPassword, String newPassword,String confirmNewPassword,String verificationCode,  Integer type);
+
+    /**
+     * 更换绑定手机号 效验原手机密码或者验证码
+     *
+     * @param phone   手机号
+     * @param oldPassword 原密码
+     * @param verificationCode 验证码
+     */
+    Map<String,String> changePhoneVerification(String phone, String oldPassword, String verificationCode);
 
 
     /**
     /**
      * 设置用户信息
      * 设置用户信息
@@ -153,7 +162,7 @@ public interface StoreUserService extends IService<StoreUser> {
     R<Boolean> register(String phone, String password);
     R<Boolean> register(String phone, String password);
 
 
     /**
     /**
-     *
+     * 效验商家端账号注销
      */
      */
     Map<String,String> storeCancelAccountVerification(StoreUserVo storeUserVo);
     Map<String,String> storeCancelAccountVerification(StoreUserVo storeUserVo);
 
 

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

@@ -229,6 +229,7 @@ public class LifeMessageServiceImpl extends ServiceImpl<LifeMessageMapper, LifeM
             LifeMessageVo vo = new LifeMessageVo();
             LifeMessageVo vo = new LifeMessageVo();
             if (!CollectionUtils.isEmpty(lifeMessagePageList)) {
             if (!CollectionUtils.isEmpty(lifeMessagePageList)) {
                 vo.setUserName(lifeMessagePageList.get(0).getUserName());
                 vo.setUserName(lifeMessagePageList.get(0).getUserName());
+                vo.setCreatedTime(lifeMessagePageList.get(0).getCreatedTime());
                 lifeMessagePageList = lifeMessagePageList.stream().filter(item -> !notDisturbList.contains(item.getPhoneId())).collect(Collectors.toList());
                 lifeMessagePageList = lifeMessagePageList.stream().filter(item -> !notDisturbList.contains(item.getPhoneId())).collect(Collectors.toList());
                 vo.setNotReadCount(lifeMessagePageList.stream().filter(item -> 0 == item.getIsRead()).count());
                 vo.setNotReadCount(lifeMessagePageList.stream().filter(item -> 0 == item.getIsRead()).count());
             }
             }
@@ -268,7 +269,7 @@ public class LifeMessageServiceImpl extends ServiceImpl<LifeMessageMapper, LifeM
             wrapper = new QueryWrapper<>();
             wrapper = new QueryWrapper<>();
             wrapper.eq("num", 1);
             wrapper.eq("num", 1);
             wrapper.apply("(sender_id not in (" + friendsIdsStr + ") and receiver_id not in (" + friendsIdsStr + "))");
             wrapper.apply("(sender_id not in (" + friendsIdsStr + ") and receiver_id not in (" + friendsIdsStr + "))");
-            wrapper.orderByDesc("created_time");
+            wrapper.orderByDesc("message.created_time");
 //        IPage<LifeMessageVo> ipage = new Page<>(1, Integer.MAX_VALUE);
 //        IPage<LifeMessageVo> ipage = new Page<>(1, Integer.MAX_VALUE);
             List<LifeMessageVo> lifeMessageVoList = lifeMessageMapper.getLifeMessagePageByPhoneId(receiverId, wrapper);
             List<LifeMessageVo> lifeMessageVoList = lifeMessageMapper.getLifeMessagePageByPhoneId(receiverId, wrapper);
 
 

+ 38 - 3
alien-store/src/main/java/shop/alien/store/service/impl/StoreInfoServiceImpl.java

@@ -32,7 +32,6 @@ import shop.alien.entity.store.vo.*;
 import shop.alien.mapper.*;
 import shop.alien.mapper.*;
 import shop.alien.store.config.BaseRedisService;
 import shop.alien.store.config.BaseRedisService;
 import shop.alien.store.config.GaoDeMapUtil;
 import shop.alien.store.config.GaoDeMapUtil;
-import shop.alien.store.service.LifeUserOrderService;
 import shop.alien.store.service.NearMeService;
 import shop.alien.store.service.NearMeService;
 import shop.alien.store.service.StoreInfoService;
 import shop.alien.store.service.StoreInfoService;
 import shop.alien.store.util.FileUploadUtil;
 import shop.alien.store.util.FileUploadUtil;
@@ -103,6 +102,8 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
 
 
     private final StoreInfoDraftMapper storeInfoDraftMapper;
     private final StoreInfoDraftMapper storeInfoDraftMapper;
 
 
+    private final LifeNoticeMapper lifeNoticeMapper;
+
     @Value("${spring.web.resources.excel-path}")
     @Value("${spring.web.resources.excel-path}")
     private String excelPath;
     private String excelPath;
 
 
@@ -326,7 +327,11 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
                     long daysToExpire = ChronoUnit.DAYS.between(nowLocal, expDate);
                     long daysToExpire = ChronoUnit.DAYS.between(nowLocal, expDate);
                     record.setDaysToExpire(daysToExpire);
                     record.setDaysToExpire(daysToExpire);
                 }
                 }
-
+                // 处理状态
+                if(record.getLogoutFlag() == 1){
+                    record.setStoreStatusStr("已注销");
+                    record.setStoreStatus(2);
+                }
                 // 根据八大类不同进行个性化操作
                 // 根据八大类不同进行个性化操作
                 if (StringUtils.isNotEmpty(businessSection)) {
                 if (StringUtils.isNotEmpty(businessSection)) {
                     switch (businessSection) {
                     switch (businessSection) {
@@ -414,6 +419,9 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
                 return false;
                 return false;
             }
             }
             store.setStorePosition(LonAndLat);
             store.setStorePosition(LonAndLat);
+            if(null == store.getCommissionRate()){
+                store.setCommissionRate("0.03");
+            }
             this.save(store);
             this.save(store);
             Set<String> fileNameSet = multipartRequest.getMultiFileMap().keySet();
             Set<String> fileNameSet = multipartRequest.getMultiFileMap().keySet();
             if (!fileNameSet.isEmpty()) {
             if (!fileNameSet.isEmpty()) {
@@ -511,6 +519,9 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
         EssentialCityCode essentialCityCode3 =
         EssentialCityCode essentialCityCode3 =
                 essentialCityCodeMapper.selectOne(new LambdaQueryWrapper<EssentialCityCode>().eq(EssentialCityCode::getAreaCode, storeInfo.getAdministrativeRegionDistrictAdcode()));
                 essentialCityCodeMapper.selectOne(new LambdaQueryWrapper<EssentialCityCode>().eq(EssentialCityCode::getAreaCode, storeInfo.getAdministrativeRegionDistrictAdcode()));
         storeInfo.setAdministrativeRegionDistrictName(essentialCityCode3.getAreaName());
         storeInfo.setAdministrativeRegionDistrictName(essentialCityCode3.getAreaName());
+        if(null == storeInfo.getCommissionRate()){
+            storeInfo.setCommissionRate("3");
+        }
         storeInfoMapper.insert(storeInfo);
         storeInfoMapper.insert(storeInfo);
         result.setId(storeInfo.getId());
         result.setId(storeInfo.getId());
         nearMeService.inGeolocation(new Point(Double.parseDouble(storeInfoDto.getStorePositionLongitude()),
         nearMeService.inGeolocation(new Point(Double.parseDouble(storeInfoDto.getStorePositionLongitude()),
@@ -1011,9 +1022,25 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
     }
     }
 
 
     @Override
     @Override
-    public void approveStoreInfo(String storeId, Integer approvalStatus) {
+    public void approveStoreInfo(String storeId, Integer approvalStatus, String reason) {
         StoreInfo storeInfo = storeInfoMapper.selectById(storeId);
         StoreInfo storeInfo = storeInfoMapper.selectById(storeId);
         storeInfo.setStoreApplicationStatus(approvalStatus);
         storeInfo.setStoreApplicationStatus(approvalStatus);
+        storeInfo.setReason(reason);
+        StoreUser storeUser = storeUserMapper.selectOne(new LambdaQueryWrapper<StoreUser>().eq(StoreUser::getStoreId, storeInfo.getId()).eq(StoreUser::getDeleteFlag,0));
+        // 发送审核通知
+        LifeNotice lifeNotice = new LifeNotice();
+        lifeNotice.setSenderId("system");
+        lifeNotice.setReceiverId("store_"+ storeUser.getPhone());
+        lifeNotice.setBusinessId(storeInfo.getId());
+        lifeNotice.setTitle("店铺审核通知");
+        if(2 == approvalStatus){
+            lifeNotice.setContext("您的店铺申请被驳回,原因为:"+reason);
+        } else {
+            lifeNotice.setContext("您的店铺申请已通过");
+        }
+        lifeNotice.setNoticeType(1); // 系统通知
+        lifeNotice.setIsRead(0);
+        lifeNoticeMapper.insert(lifeNotice);
         storeInfoMapper.updateById(storeInfo);
         storeInfoMapper.updateById(storeInfo);
     }
     }
 
 
@@ -1336,4 +1363,12 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
         queryWrapper.eq(StoreInfo::getStoreTel, storeTel);
         queryWrapper.eq(StoreInfo::getStoreTel, storeTel);
         return storeInfoMapper.selectList(queryWrapper);
         return storeInfoMapper.selectList(queryWrapper);
     }
     }
+
+    @Override
+    public int editStoreCommissionRate(StoreInfoDto storeInfoDto) {
+        LambdaUpdateWrapper<StoreInfo> wrapper = new LambdaUpdateWrapper<>();
+        wrapper.eq(StoreInfo::getId, storeInfoDto.getId());
+        wrapper.set(StoreInfo::getCommissionRate, storeInfoDto.getCommissionRate());
+        return storeInfoMapper.update(null, wrapper);
+    }
 }
 }

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

@@ -28,9 +28,11 @@ public class StoreSalesDetailsServiceImpl implements StoreSalesDetailsService {
         wrapper.eq("coupon.delete_flag", 0);
         wrapper.eq("coupon.delete_flag", 0);
         wrapper.eq("luser.delete_flag", 0);
         wrapper.eq("luser.delete_flag", 0);
         wrapper.eq(null != storeSalesDetailsVo.getStoreId(), "lorder.store_id", storeSalesDetailsVo.getStoreId());
         wrapper.eq(null != storeSalesDetailsVo.getStoreId(), "lorder.store_id", storeSalesDetailsVo.getStoreId());
-        wrapper.eq(null != storeSalesDetailsVo.getType(), "coupon.type", storeSalesDetailsVo.getType());
+        wrapper.in(CollectionUtils.isNotEmpty(storeSalesDetailsVo.getTypeList()), "coupon.type", storeSalesDetailsVo.getTypeList());
         wrapper.ge(null != storeSalesDetailsVo.getPayStartTime(), "lorder.pay_time", storeSalesDetailsVo.getPayStartTime());
         wrapper.ge(null != storeSalesDetailsVo.getPayStartTime(), "lorder.pay_time", storeSalesDetailsVo.getPayStartTime());
         if (null != storeSalesDetailsVo.getPayEndTime()) {
         if (null != storeSalesDetailsVo.getPayEndTime()) {
+            wrapper.le(null != storeSalesDetailsVo.getPayEndTime(), "lorder.pay_time", storeSalesDetailsVo.getPayEndTime());
+        }else{
             wrapper.le("lorder.pay_time", Date.from(storeSalesDetailsVo.getPayEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().plusHours(23).plusMinutes(59).plusSeconds(59).atZone(ZoneId.systemDefault()).toInstant()));
             wrapper.le("lorder.pay_time", Date.from(storeSalesDetailsVo.getPayEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().plusHours(23).plusMinutes(59).plusSeconds(59).atZone(ZoneId.systemDefault()).toInstant()));
         }
         }
         wrapper.eq(StringUtils.isNotEmpty(storeSalesDetailsVo.getStatus()), "lorder.status", storeSalesDetailsVo.getStatus());
         wrapper.eq(StringUtils.isNotEmpty(storeSalesDetailsVo.getStatus()), "lorder.status", storeSalesDetailsVo.getStatus());

+ 113 - 55
alien-store/src/main/java/shop/alien/store/service/impl/StoreUserServiceImpl.java

@@ -24,6 +24,7 @@ import shop.alien.entity.store.excelVo.util.ExcelGenerator;
 import shop.alien.entity.store.vo.StoreUserVo;
 import shop.alien.entity.store.vo.StoreUserVo;
 import shop.alien.mapper.*;
 import shop.alien.mapper.*;
 import shop.alien.store.config.BaseRedisService;
 import shop.alien.store.config.BaseRedisService;
+import shop.alien.store.service.NearMeService;
 import shop.alien.store.service.StoreUserService;
 import shop.alien.store.service.StoreUserService;
 import shop.alien.store.util.FunctionMagic;
 import shop.alien.store.util.FunctionMagic;
 import shop.alien.util.common.DateUtils;
 import shop.alien.util.common.DateUtils;
@@ -79,6 +80,8 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
 
 
     private final LifeMessageMapper lifeMessageMapper;
     private final LifeMessageMapper lifeMessageMapper;
 
 
+    private final NearMeService nearMeService;
+
     /**
     /**
      * 手机号获取
      * 手机号获取
      *
      *
@@ -91,7 +94,7 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
         lambdaQueryWrapper.eq(StoreUser::getPhone, phone);
         lambdaQueryWrapper.eq(StoreUser::getPhone, phone);
         StoreUser user = this.getOne(lambdaQueryWrapper);
         StoreUser user = this.getOne(lambdaQueryWrapper);
         StoreUserVo storeUserVo = new StoreUserVo();
         StoreUserVo storeUserVo = new StoreUserVo();
-        if(user.getStatus() == -1){
+        if (user.getStatus() == -1) {
             LocalDateTime localDateTime = user.getLogoutTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
             LocalDateTime localDateTime = user.getLogoutTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
             LocalDateTime future = localDateTime.plusDays(7);
             LocalDateTime future = localDateTime.plusDays(7);
             LocalDateTime now = LocalDateTime.now();
             LocalDateTime now = LocalDateTime.now();
@@ -198,7 +201,7 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
         boolean flag = false;
         boolean flag = false;
         //类型为0 忘记密码
         //类型为0 忘记密码
         if (type == 0) {
         if (type == 0) {
-            forgetPassword(phone, newPassword, verificationCode);
+            flag = forgetPassword(phone, newPassword, verificationCode);
         }
         }
         //修改密码
         //修改密码
         else if (type == 1) {
         else if (type == 1) {
@@ -212,7 +215,10 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
             //修改成功后同步删除redis缓存token
             //修改成功后同步删除redis缓存token
             if (flag) {
             if (flag) {
                 String token = "store_" + phone;
                 String token = "store_" + phone;
-                baseRedisService.delete(token);
+                String toKenStr = baseRedisService.getString(token);
+                if (toKenStr != null) {
+                    baseRedisService.delete(token);
+                }
             } else {
             } else {
                 log.error("密码修改失败");
                 log.error("密码修改失败");
                 throw new RuntimeException("密码修改失败");
                 throw new RuntimeException("密码修改失败");
@@ -221,11 +227,40 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
         }
         }
         //更换绑定手机号
         //更换绑定手机号
         else if (type == 2) {
         else if (type == 2) {
-            ChangeBoundPhone(phone, newPhone, verificationCode);
+            flag = ChangeBoundPhone(phone, newPhone, verificationCode);
         }
         }
         return flag;
         return flag;
     }
     }
 
 
+    @Override
+    public Map<String, String> changePhoneVerification(String phone, String oldPassword, String verificationCode) {
+        Map<String, String> changePhoneMap = new HashMap<>();
+
+        if (oldPassword != null || !oldPassword.equals("")) {
+            LambdaUpdateWrapper<StoreUser> userLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
+            userLambdaUpdateWrapper.eq(StoreUser::getPhone, phone);
+            StoreUser storeUser = this.getOne(userLambdaUpdateWrapper);
+            if (storeUser.getPassword().equals(oldPassword)) {
+                changePhoneMap.put("passwordStatus", "0");
+                return changePhoneMap;
+            } else {
+                changePhoneMap.put("passwordStatus", "1");
+                return changePhoneMap;
+            }
+        } else {
+            String oldPhoneVerification = "verification_" + phone;
+            //获取新手机号验证码
+            String redisVerificationCode = baseRedisService.getString(oldPhoneVerification);
+            if (redisVerificationCode.equals(verificationCode)) {
+                changePhoneMap.put("verificationStatus", "0");
+                return changePhoneMap;
+            } else {
+                changePhoneMap.put("verificationStatus", "1");
+                return changePhoneMap;
+            }
+        }
+    }
+
     private void passwordVerification(String phone, String password, String newPassword, String confirmNewPassword) {
     private void passwordVerification(String phone, String password, String newPassword, String confirmNewPassword) {
         LambdaUpdateWrapper<StoreUser> wrapperFans = new LambdaUpdateWrapper<>();
         LambdaUpdateWrapper<StoreUser> wrapperFans = new LambdaUpdateWrapper<>();
         wrapperFans.eq(StoreUser::getPhone, phone);
         wrapperFans.eq(StoreUser::getPhone, phone);
@@ -259,7 +294,10 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
             if (flag) {
             if (flag) {
                 log.info("密码修改成功");
                 log.info("密码修改成功");
                 String token = "store_" + phone;
                 String token = "store_" + phone;
-                baseRedisService.delete(token);
+                String tokenStr = baseRedisService.getString(token);
+                if (tokenStr != null) {
+                    baseRedisService.delete(token);
+                }
             }
             }
             if (!flag) {
             if (!flag) {
                 log.error("密码修改失败");
                 log.error("密码修改失败");
@@ -273,33 +311,33 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
 
 
     private boolean ChangeBoundPhone(String phone, String newPhone, String verificationCode) {
     private boolean ChangeBoundPhone(String phone, String newPhone, String verificationCode) {
         boolean flag = false;
         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) {
+        String newPhoneVerification = "verification_" + newPhone;
+        //获取新手机号验证码
+        String redisVerificationCode = baseRedisService.getString(newPhoneVerification);
+        if(!StringUtils.isEmpty(redisVerificationCode) && redisVerificationCode.equals(verificationCode)){
+            LambdaUpdateWrapper<StoreUser> updateWrapper = new LambdaUpdateWrapper<>();
+            updateWrapper.eq(StoreUser::getPhone, phone);
+            StoreUser storeUser = this.getOne(updateWrapper);
+            if(storeUser !=null){
                 storeUser.setPhone(newPhone);
                 storeUser.setPhone(newPhone);
                 flag = this.updateById(storeUser);
                 flag = this.updateById(storeUser);
+                if(flag){
+                    String token = "store_" + phone;
+                    String tokenStr = baseRedisService.getString(token);
+                    if (tokenStr != null) {
+                        baseRedisService.delete(token);
+                    }
+                }
             }
             }
-            if (flag) {
-                log.info("新手机号绑定成功");
-                String token = "store_" + phone;
-                baseRedisService.delete(token);
-            }
-            if (!flag) {
-                log.error("手机号更换绑定失败");
-                throw new RuntimeException("手机号更换绑定失败");
-            }
-            return flag;
-        } else {
+        }else{
             throw new RuntimeException("验证码错误");
             throw new RuntimeException("验证码错误");
         }
         }
+        return flag;
     }
     }
 
 
     /**
     /**
      * 设置用户信息
      * 设置用户信息
+     *
      * @return boolean
      * @return boolean
      */
      */
     @Override
     @Override
@@ -534,18 +572,18 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
         StoreUser storeUser = storeUserMapper.selectOne(storeUserLambdaQueryWrapper);
         StoreUser storeUser = storeUserMapper.selectOne(storeUserLambdaQueryWrapper);
         Map<String, String> storeMap = new HashMap<>();
         Map<String, String> storeMap = new HashMap<>();
         if (storeUser != null) {
         if (storeUser != null) {
+            storeMap.put("status", storeUser.getStatus().toString());
             if (null != storeUser.getStoreId()) {
             if (null != storeUser.getStoreId()) {
                 StoreInfo storeInfo = storeInfoMapper.selectById(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("accountStore", "0");
+            } else {
+                //vaule为1代表绑定店铺注销
+                storeMap.put("accountStore", "1");
+            }
+            if (storeUser.getMoney() != null && storeUser.getMoney() > 0) {
                 //vaule为0代表有未体现的现金
                 //vaule为0代表有未体现的现金
-                storeMap.put("accountMoney", "0");
+                storeMap.put("accountMoney", "1");
             } else {
             } else {
                 //vaule为1代表没有未体现的现金
                 //vaule为1代表没有未体现的现金
                 storeMap.put("accountMoney", "1");
                 storeMap.put("accountMoney", "1");
@@ -605,7 +643,10 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
         LambdaQueryWrapper<StoreUser> storeUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
         LambdaQueryWrapper<StoreUser> storeUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
         storeUserLambdaQueryWrapper.eq(StoreUser::getId, storeUserVo.getId());
         storeUserLambdaQueryWrapper.eq(StoreUser::getId, storeUserVo.getId());
         StoreUser storeUser = storeUserMapper.selectOne(storeUserLambdaQueryWrapper);
         StoreUser storeUser = storeUserMapper.selectOne(storeUserLambdaQueryWrapper);
-        if (storeUser != null) {
+        String key = "verification_" + storeUser.getPhone();
+        String redisVerificationCode = baseRedisService.getString(key);
+        if (redisVerificationCode.equals(storeUserVo.getVerificationCode())) {
+            if (storeUser != null) {
                 // 添加注销原因
                 // 添加注销原因
                 storeUser.setLogoutReason(storeUserVo.getLogoutReason());
                 storeUser.setLogoutReason(storeUserVo.getLogoutReason());
                 // 添加注销code
                 // 添加注销code
@@ -614,6 +655,8 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
                 storeUser.setStatus(-1);
                 storeUser.setStatus(-1);
                 // 添加注销申请时间
                 // 添加注销申请时间
                 storeUser.setLogoutTime(new Date());
                 storeUser.setLogoutTime(new Date());
+                // 更新logout_flag状态为1
+                storeUser.setLogoutFlag(1);
                 int num = storeUserMapper.updateById(storeUser);
                 int num = storeUserMapper.updateById(storeUser);
                 if (num > 0) {
                 if (num > 0) {
                     // 发送通知
                     // 发送通知
@@ -627,7 +670,10 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
                     lifeMessage.setIsRead(0);
                     lifeMessage.setIsRead(0);
                     lifeMessage.setNoticeType(1);
                     lifeMessage.setNoticeType(1);
                     lifeNoticeMapper.insert(lifeMessage);
                     lifeNoticeMapper.insert(lifeMessage);
+                }
             }
             }
+        } else {
+            throw new RuntimeException("验证码错误");
         }
         }
     }
     }
 
 
@@ -643,39 +689,51 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
         storeUser.setStatus(0);
         storeUser.setStatus(0);
         // 清空注销原因
         // 清空注销原因
         storeUser.setLogoutReason(null);
         storeUser.setLogoutReason(null);
+        // 清空注销code
+        storeUser.setLogoutCode(null);
         // 清空注销申请时间
         // 清空注销申请时间
         storeUser.setLogoutTime(null);
         storeUser.setLogoutTime(null);
+        // 更新logout_flag状态为0
+        storeUser.setLogoutFlag(0);
         int num = 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);
-            }
+        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
     @Override
     public void deleteStoreAccountInfo(StoreUserVo storeUserVo) {
     public void deleteStoreAccountInfo(StoreUserVo storeUserVo) {
         LambdaQueryWrapper<StoreUser> queryWrapper = new LambdaQueryWrapper<>();
         LambdaQueryWrapper<StoreUser> queryWrapper = new LambdaQueryWrapper<>();
         queryWrapper.eq(StoreUser::getId, storeUserVo.getId());
         queryWrapper.eq(StoreUser::getId, storeUserVo.getId());
+        queryWrapper.eq(StoreUser::getDeleteFlag, 0);
         StoreUser storeUser = storeUserMapper.selectOne(queryWrapper);
         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());
+        if (storeUser != null) {
+            storeUserMapper.deleteById(storeUserVo.getId());
+            nearMeService.removeGeolocation(Boolean.TRUE, storeUser.getId().toString());
+            String storePhone = "store_" + storeUserVo.getPhone();
+            String key = baseRedisService.getString(storePhone);
+            if (key != null) {
+                //删除用户redis中的token
+                baseRedisService.delete(key);
+            }
+            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());
+            }
         }
         }
     }
     }
 
 

+ 121 - 5
alien-store/src/main/java/shop/alien/store/task/ScheduledTask.java

@@ -1,22 +1,29 @@
 package shop.alien.store.task;
 package shop.alien.store.task;
 
 
+import cn.hutool.core.collection.CollectionUtil;
+import com.alibaba.fastjson2.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import lombok.RequiredArgsConstructor;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
+import shop.alien.entity.second.SecondTradeRecord;
 import shop.alien.entity.store.*;
 import shop.alien.entity.store.*;
-import shop.alien.mapper.LifeCouponMapper;
-import shop.alien.mapper.LifeMessageMapper;
-import shop.alien.mapper.LifeUserOrderMapper;
+import shop.alien.entity.store.vo.WebsocketVo;
+import shop.alien.mapper.*;
+import shop.alien.mapper.second.SecondTradeRecordMapper;
+import shop.alien.store.config.BaseRedisService;
+import shop.alien.store.config.WebSocketProcess;
 import shop.alien.store.service.*;
 import shop.alien.store.service.*;
+import shop.alien.store.util.ali.AliApi;
 import shop.alien.util.common.AlipayTradeRefund;
 import shop.alien.util.common.AlipayTradeRefund;
 import shop.alien.util.common.DateUtils;
 import shop.alien.util.common.DateUtils;
-import shop.alien.store.util.ali.AliApi;
 
 
 import java.math.BigDecimal;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.math.RoundingMode;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
 import java.util.*;
 import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
@@ -45,6 +52,16 @@ public class ScheduledTask {
 
 
     private final LifeUserService lifeUserService;
     private final LifeUserService lifeUserService;
 
 
+    private final SecondTradeRecordMapper secondTradeRecordMapper;
+
+    private final LifeNoticeMapper lifeNoticeMapper;
+
+    private final LifeUserMapper lifeUserMapper;
+
+    private final WebSocketProcess webSocketProcess;
+
+    private final BaseRedisService baseRedisService;
+
     @Scheduled(cron = "0 */10 * * * ?")
     @Scheduled(cron = "0 */10 * * * ?")
     public void sendDiscountCouponRemind() {
     public void sendDiscountCouponRemind() {
         //查询
         //查询
@@ -176,7 +193,7 @@ public class ScheduledTask {
      * 自动转账
      * 自动转账
      * 一分钟执行一次
      * 一分钟执行一次
      */
      */
-//    @Scheduled(cron = "0 */1 * * * ?")
+    @Scheduled(cron = "0 */1 * * * ?")
     public void autoTransferAccounts() {
     public void autoTransferAccounts() {
         //获取已到账期
         //获取已到账期
         LambdaQueryWrapper<StoreIncomeDetailsRecord> wrapper = new LambdaQueryWrapper<>();
         LambdaQueryWrapper<StoreIncomeDetailsRecord> wrapper = new LambdaQueryWrapper<>();
@@ -274,4 +291,103 @@ public class ScheduledTask {
             }
             }
         }
         }
     }
     }
+
+    /**
+     * 二手交易平台 - 交易时间前的十分钟和十五分钟之间  给买家和卖家发送通知提醒
+     */
+    @Scheduled(cron = "0 */5 * * * ?")
+    public void secondTradeRemind() throws Exception {
+        LocalDateTime now = LocalDateTime.now();
+        // 五分钟后
+        LocalDateTime fiveMinutesLater = now.plusMinutes(5);
+
+        // 查询所有待交易
+        LambdaQueryWrapper<SecondTradeRecord> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(SecondTradeRecord::getTradeStatus, 0);
+        List<SecondTradeRecord> tradeRecordList = secondTradeRecordMapper.selectList(wrapper);
+
+        for (SecondTradeRecord tradeRecord : tradeRecordList) {
+            // 十分钟前
+            LocalDateTime tenMinutesAgo = tradeRecord.getTransactionTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().minusMinutes(10);
+            // 交易时间前的十分钟和十五分钟之间
+            if ((now.isBefore(tenMinutesAgo) && fiveMinutesLater.isAfter(tenMinutesAgo))
+                    || now.isEqual(tenMinutesAgo) || fiveMinutesLater.isEqual(tenMinutesAgo)) {
+
+                // 给买家发送消息
+                LifeMessage lifeMessage = new LifeMessage();
+                lifeMessage.setSenderId(String.valueOf(tradeRecord.getSellerId()));
+                lifeMessage.setReceiverId(String.valueOf(tradeRecord.getBuyerId()));
+                lifeMessage.setContent("签到");
+                lifeMessage.setType("5");
+                lifeMessageMapper.insert(lifeMessage);
+
+                // 给卖家发送消息
+                lifeMessage = new LifeMessage();
+                lifeMessage.setSenderId(String.valueOf(tradeRecord.getBuyerId()));
+                lifeMessage.setReceiverId(String.valueOf(tradeRecord.getSellerId()));
+                lifeMessage.setContent("签到");
+                lifeMessage.setType("5");
+                lifeMessageMapper.insert(lifeMessage);
+
+                // 给买家发送通知
+                LifeNotice lifeNotice = new LifeNotice();
+                lifeNotice.setSenderId("system");
+                lifeNotice.setReceiverId(String.valueOf(tradeRecord.getBuyerId()));
+                lifeNotice.setBusinessId(tradeRecord.getId());
+                lifeNotice.setTitle("交易提醒");
+                lifeNotice.setContext("您有一笔交易即将开始, 请及时前往查看");
+                lifeNotice.setNoticeType(1);
+                lifeNoticeMapper.insert(lifeNotice);
+
+                // 给卖家发送通知
+                lifeNotice = new LifeNotice();
+                lifeNotice.setSenderId("system");
+                lifeNotice.setReceiverId(String.valueOf(tradeRecord.getSellerId()));
+                lifeNotice.setBusinessId(tradeRecord.getId());
+                lifeNotice.setTitle("交易提醒");
+                lifeNotice.setContext("您有一笔交易即将开始, 请及时前往查看");
+                lifeNotice.setNoticeType(1);
+                lifeNoticeMapper.insert(lifeNotice);
+
+                // 给买家推送通知
+                LifeUser user = lifeUserMapper.selectById(tradeRecord.getBuyerId());
+                WebsocketVo websocketVo = new WebsocketVo();
+                websocketVo.setSenderId("system");
+                websocketVo.setCategory("notice");
+                websocketVo.setType("5");
+                websocketVo.setText("签到");
+                if (user != null) {
+                    websocketVo.setReceiverId("user_" + user.getUserPhone());
+                    webSocketProcess.sendMessage("user_" + user.getUserPhone(), JSONObject.from(websocketVo).toJSONString());
+                }
+
+                // 给卖家推送通知
+                user = lifeUserMapper.selectById(tradeRecord.getSellerId());
+                if (user != null) {
+                    websocketVo.setReceiverId("user_" + user.getUserPhone());
+                    webSocketProcess.sendMessage("user_" + user.getUserPhone(), JSONObject.from(websocketVo).toJSONString());
+                }
+            }
+        }
+    }
+
+    /**
+     * 每分钟从redis中读取已读的消息id 并将数据库设为已读
+     */
+    @Scheduled(cron = "0 * * * * ?")
+    public void readMessage() {
+        try {
+            if (CollectionUtil.isEmpty(baseRedisService.getList("readMessageIdKey"))) return;
+
+            List<String> dataList = baseRedisService.popBatchFromList("readMessageIdKey");
+            if (CollectionUtil.isNotEmpty(dataList)) {
+                LambdaUpdateWrapper<LifeMessage> wrapper = new LambdaUpdateWrapper<>();
+                wrapper.in(LifeMessage::getId, dataList)
+                        .set(LifeMessage::getIsRead, 1);
+                lifeMessageMapper.update(null, wrapper);
+            }
+        } catch (Exception e) {
+            log.error("ScheduledTask.readMessage Error Mgs={}", e.getMessage());
+        }
+    }
 }
 }

+ 61 - 44
alien-store/src/main/java/shop/alien/store/util/FileUploadUtil.java

@@ -10,8 +10,10 @@ import org.springframework.web.multipart.MultipartRequest;
 import shop.alien.entity.result.R;
 import shop.alien.entity.result.R;
 import shop.alien.entity.store.vo.StoreImgVo;
 import shop.alien.entity.store.vo.StoreImgVo;
 import shop.alien.store.service.StoreImgService;
 import shop.alien.store.service.StoreImgService;
+import shop.alien.util.ali.AliOSSUtil;
 import shop.alien.util.common.RandomCreateUtil;
 import shop.alien.util.common.RandomCreateUtil;
 import shop.alien.util.common.VideoUtils;
 import shop.alien.util.common.VideoUtils;
+import shop.alien.util.file.FileUtil;
 
 
 import java.io.File;
 import java.io.File;
 import java.nio.file.Files;
 import java.nio.file.Files;
@@ -34,11 +36,7 @@ public class FileUploadUtil {
     @Value("${spring.web.resources.static-locations}")
     @Value("${spring.web.resources.static-locations}")
     private String uploadDir;
     private String uploadDir;
 
 
-    @Value("${spring.web.resources.app-locations}")
-    private String uploadAppDir;
-
-    @Value("${spring.web.resources.url}")
-    private String fileUrl;
+    private final AliOSSUtil aliOSSUtil;
 
 
     List<String> imageFileType = Arrays.asList("jpg", "jpeg", "png", "bmp", "webp", "gif", "svg");
     List<String> imageFileType = Arrays.asList("jpg", "jpeg", "png", "bmp", "webp", "gif", "svg");
     List<String> videoFileType = Arrays.asList("mp4", "avi", "flv", "mkv", "rmvb", "wmv", "3gp", "mov");
     List<String> videoFileType = Arrays.asList("mp4", "avi", "flv", "mkv", "rmvb", "wmv", "3gp", "mov");
@@ -47,22 +45,19 @@ public class FileUploadUtil {
     /**
     /**
      * 上传文件
      * 上传文件
      *
      *
-     * @param file 文件名
+     * @param multipartFile 文件名
      * @return 文件路径
      * @return 文件路径
      */
      */
-    public String uploadOneFile(MultipartFile file) {
+    public String uploadOneFile(MultipartFile multipartFile) {
         try {
         try {
-            String cleanUploadDir = uploadDir.replace("\\", "/");
+            Map<String, String> fileNameAndType = FileUtil.getFileNameAndType(multipartFile);
             String prefix = "";
             String prefix = "";
-            String type = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.') + 1);
-            if (imageFileType.contains(type.toLowerCase())) {
-                cleanUploadDir += "/image";
+            if (imageFileType.contains(fileNameAndType.get("type").toLowerCase())) {
                 prefix = "image/";
                 prefix = "image/";
-            } else if (videoFileType.contains(type.toLowerCase())) {
-                cleanUploadDir += "/video";
+            } else if (videoFileType.contains(fileNameAndType.get("type").toLowerCase())) {
                 prefix = "video/";
                 prefix = "video/";
             }
             }
-            return copyFile(cleanUploadDir, prefix, file);
+            return aliOSSUtil.uploadFile(multipartFile, prefix + fileNameAndType.get("name") + RandomCreateUtil.getRandomNum(6) + "." + fileNameAndType.get("type"));
         } catch (Exception e) {
         } catch (Exception e) {
             log.error("FileUpload.uploadOneFile ERROR Msg={}", e.getMessage());
             log.error("FileUpload.uploadOneFile ERROR Msg={}", e.getMessage());
             throw new RuntimeException(e);
             throw new RuntimeException(e);
@@ -72,21 +67,21 @@ public class FileUploadUtil {
     /**
     /**
      * 上传app文件
      * 上传app文件
      *
      *
-     * @param file 文件名
+     * @param multipartFile 文件名
      * @return 文件路径
      * @return 文件路径
      */
      */
-    public R<Boolean> uploadApp(MultipartFile file) {
+    public String uploadApp(MultipartFile multipartFile) {
         try {
         try {
-            String type = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf('.') + 1);
-            if (!appFileType.contains(type)) {
-                return R.fail("该文件不是app格式文件");
+            Map<String, String> fileNameAndType = FileUtil.getFileNameAndType(multipartFile);
+            if (!appFileType.contains(fileNameAndType.get("type").toLowerCase())) {
+                log.error("FileUpload.uploadApp ERROR 该文件不是app格式文件");
+                return null;
             }
             }
-            String cleanUploadDir = uploadAppDir.replace("\\", "/");
             String prefix = "app/";
             String prefix = "app/";
-            return R.success(copyFile(cleanUploadDir, prefix, file));
+            return aliOSSUtil.uploadFile(multipartFile, prefix + fileNameAndType.get("name") + RandomCreateUtil.getRandomNum(6) + "." + fileNameAndType.get("type"));
         } catch (Exception e) {
         } catch (Exception e) {
             log.error("FileUpload.uploadApp ERROR Msg={}", e.getMessage());
             log.error("FileUpload.uploadApp ERROR Msg={}", e.getMessage());
-            throw new RuntimeException(e);
+            return null;
         }
         }
     }
     }
 
 
@@ -106,28 +101,32 @@ public class FileUploadUtil {
                 log.info("FileUpload.uploadMoreFile fileName={}", multipartFile.getOriginalFilename());
                 log.info("FileUpload.uploadMoreFile fileName={}", multipartFile.getOriginalFilename());
                 String uploadDir = this.uploadDir.replace("file:///", "").replace("\\", "/");
                 String uploadDir = this.uploadDir.replace("file:///", "").replace("\\", "/");
                 String prefix;
                 String prefix;
-                String type = multipartFile.getOriginalFilename().substring(multipartFile.getOriginalFilename().lastIndexOf('.') + 1);
+                Map<String, String> fileNameAndType = FileUtil.getFileNameAndType(multipartFile);
                 //区分文件类型
                 //区分文件类型
-                if (imageFileType.contains(type.toLowerCase())) {
+                if (imageFileType.contains(fileNameAndType.get("type").toLowerCase())) {
                     uploadDir += "/image";
                     uploadDir += "/image";
                     prefix = "image/";
                     prefix = "image/";
                     log.info("FileUpload.uploadMoreFile 获取到图片文件准备复制 {} {} {}", uploadDir, prefix, multipartFile.getOriginalFilename());
                     log.info("FileUpload.uploadMoreFile 获取到图片文件准备复制 {} {} {}", uploadDir, prefix, multipartFile.getOriginalFilename());
-                    filePathList.add(copyFile(uploadDir, prefix, multipartFile));
-                } else if (videoFileType.contains(type.toLowerCase())) {
-                    uploadDir += "/video";
+                    filePathList.add(aliOSSUtil.uploadFile(multipartFile, prefix + fileNameAndType.get("name") + RandomCreateUtil.getRandomNum(6) + "." + fileNameAndType.get("type")));
+                    ;
+                } else if (videoFileType.contains(fileNameAndType.get("type").toLowerCase())) {
+                    uploadDir += "/video/";
                     prefix = "video/";
                     prefix = "video/";
+                    //上传视频文件
                     log.info("FileUpload.uploadMoreFile 获取到视频文件准备复制 {} {} {}", uploadDir, prefix, multipartFile.getOriginalFilename());
                     log.info("FileUpload.uploadMoreFile 获取到视频文件准备复制 {} {} {}", uploadDir, prefix, multipartFile.getOriginalFilename());
-                    String localFileName = copyFile(uploadDir, prefix, multipartFile);
-                    filePathList.add(localFileName);
+                    String videoFileName = fileNameAndType.get("name") + RandomCreateUtil.getRandomNum(6);
+                    String cacheVideoPath = copyFile(uploadDir, multipartFile);
+                    filePathList.add(aliOSSUtil.uploadFile(multipartFile, prefix + videoFileName + "." + fileNameAndType.get("type")));
+                    //缓存视频截图使用
+                    File videoFile = new File(cacheVideoPath);
                     //获取视频某帧截图
                     //获取视频某帧截图
-                    log.info("FileUpload.uploadMoreFile 视频文件复制完毕, 获取第一秒图片 {}", localFileName);
-                    String videoPath = videoUtils.getImg(uploadDir + "/" + new File(localFileName).getName());
+                    log.info("FileUpload.uploadMoreFile 视频文件复制完毕, 获取第一秒图片 {}", videoFile.getName());
+                    String videoPath = videoUtils.getImg(uploadDir + "/" + videoFile.getName());
                     log.info("FileUpload.uploadMoreFile 视频文件复制完毕, 图片位置 {}", videoPath);
                     log.info("FileUpload.uploadMoreFile 视频文件复制完毕, 图片位置 {}", videoPath);
                     if (!videoPath.isEmpty()) {
                     if (!videoPath.isEmpty()) {
                         File videoImgFile = new File(videoPath);
                         File videoImgFile = new File(videoPath);
-                        String videoImgFileUrl = fileUrl + prefix + videoImgFile.getName();
-                        log.info("FileUpload.uploadMoreFile 视频图片获取完毕 {}", videoImgFileUrl);
-                        filePathList.add(videoImgFileUrl);
+                        Map<String, String> videoImg = FileUtil.getFileNameAndType(videoImgFile);
+                        filePathList.add(aliOSSUtil.uploadFile(videoImgFile, prefix + videoFileName + "." + videoImg.get("type")));
                     } else {
                     } else {
                         throw new RuntimeException("视频截图失败");
                         throw new RuntimeException("视频截图失败");
                     }
                     }
@@ -165,18 +164,16 @@ public class FileUploadUtil {
         for (StoreImgVo storeImgVo : storeImgList) {
         for (StoreImgVo storeImgVo : storeImgList) {
             //获取文件
             //获取文件
             MultipartFile multipartFile = multipartRequest.getFileMap().get(storeImgVo.getName());
             MultipartFile multipartFile = multipartRequest.getFileMap().get(storeImgVo.getName());
-            String uploadDir = this.uploadDir.replace("file:///", "").replace("\\", "/");
+            Map<String, String> fileInfo = FileUtil.getFileNameAndType(multipartFile);
+            String videoFileName = fileInfo.get("name") + RandomCreateUtil.getRandomNum(6);
             String prefix;
             String prefix;
-            String type = multipartFile.getOriginalFilename().substring(multipartFile.getOriginalFilename().lastIndexOf('.') + 1);
             String filePath = "";
             String filePath = "";
-            if (imageFileType.contains(type.toLowerCase())) {
-                uploadDir += "/image";
+            if (imageFileType.contains(fileInfo.get("type").toLowerCase())) {
                 prefix = "image/";
                 prefix = "image/";
-                filePath = copyFile(uploadDir, prefix, multipartFile);
-            } else if (videoFileType.contains(type.toLowerCase())) {
-                uploadDir += "/video";
+                filePath = aliOSSUtil.uploadFile(multipartFile, prefix + videoFileName + "." + fileInfo.get("type"));
+            } else if (videoFileType.contains(fileInfo.get("type").toLowerCase())) {
                 prefix = "video/";
                 prefix = "video/";
-                filePath = copyFile(uploadDir, prefix, multipartFile);
+                filePath = aliOSSUtil.uploadFile(multipartFile, prefix + videoFileName + "." + fileInfo.get("type"));
             }
             }
             storeImgVo.setImgUrl(filePath);
             storeImgVo.setImgUrl(filePath);
             storeImgService.save(storeImgVo);
             storeImgService.save(storeImgVo);
@@ -189,10 +186,30 @@ public class FileUploadUtil {
      * 复制文件, 返回url链接
      * 复制文件, 返回url链接
      *
      *
      * @param localFilePath 本地路径
      * @param localFilePath 本地路径
-     * @param urlPath       拼接的url路劲
      * @param file          文件
      * @param file          文件
      * @return 访问url路径
      * @return 访问url路径
      */
      */
+    private String copyFile(String localFilePath, MultipartFile file) {
+        try {
+            File cacheFilePath = new File(localFilePath);
+            if (!cacheFilePath.exists()) {
+                cacheFilePath.mkdirs();
+            }
+            String fileName = file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf('.'));
+            log.info("FileUpload.copyFile fileName={}", fileName);
+            String fileType = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.'));
+            log.info("FileUpload.copyFile fileType={}", fileType);
+            System.out.println(file.getOriginalFilename());
+            Path path = Paths.get(localFilePath, file.getOriginalFilename());
+            Files.createDirectories(path.getParent());
+            Files.write(path, file.getBytes());
+            return localFilePath + file.getOriginalFilename();
+        } catch (Exception e) {
+            log.error("FileUpload.copyFile ERROR Msg={}", e.getMessage());
+            return e.getMessage();
+        }
+    }
+
     private String copyFile(String localFilePath, String urlPath, MultipartFile file) {
     private String copyFile(String localFilePath, String urlPath, MultipartFile file) {
         try {
         try {
             String fileName = file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf('.'));
             String fileName = file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf('.'));
@@ -206,7 +223,7 @@ public class FileUploadUtil {
             Path path = Paths.get(localFilePath, newFileName);
             Path path = Paths.get(localFilePath, newFileName);
             Files.createDirectories(path.getParent());
             Files.createDirectories(path.getParent());
             Files.write(path, file.getBytes());
             Files.write(path, file.getBytes());
-            return fileUrl + urlPath + newFileName;
+            return urlPath + newFileName;
         } catch (Exception e) {
         } catch (Exception e) {
             log.error("FileUpload.copyFile ERROR Msg={}", e.getMessage());
             log.error("FileUpload.copyFile ERROR Msg={}", e.getMessage());
             return e.getMessage();
             return e.getMessage();

+ 2 - 1
alien-store/src/main/resources/bootstrap.yml

@@ -17,4 +17,5 @@ spring:
         username: nacos
         username: nacos
         password: ngfriend198092
         password: ngfriend198092
         group: DEFAULT_GROUP
         group: DEFAULT_GROUP
-        file-extension: yml
+        file-extension: yml
+#        namespace: 3cbb802a-b56e-47f7-b658-b5012ecafb1f

+ 6 - 0
alien-util/pom.xml

@@ -317,6 +317,12 @@
             <version>0.9.0</version>
             <version>0.9.0</version>
         </dependency>
         </dependency>
 
 
+        <dependency>
+            <groupId>com.aliyun.oss</groupId>
+            <artifactId>aliyun-sdk-oss</artifactId>
+            <version>3.17.4</version>
+        </dependency>
+
     </dependencies>
     </dependencies>
 
 
     <build>
     <build>

+ 88 - 0
alien-util/src/main/java/shop/alien/util/ali/AliOSSUtil.java

@@ -0,0 +1,88 @@
+package shop.alien.util.ali;
+
+import com.aliyun.oss.ClientBuilderConfiguration;
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.OSSClientBuilder;
+import com.aliyun.oss.common.comm.SignVersion;
+import com.aliyun.oss.model.PutObjectRequest;
+import com.aliyun.oss.model.PutObjectResult;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+import shop.alien.util.file.FileUtil;
+
+import java.io.File;
+
+/**
+ * 阿里云oss工具类
+ *
+ * @author ssk
+ * @version 1.0
+ * @date 2025/7/17 8:51
+ */
+@Slf4j
+@Component
+public class AliOSSUtil {
+
+    @Value("${ali.oss.accessKeyId}")
+    private String accessKeyId;
+
+    @Value("${ali.oss.accessKeySecret}")
+    private String accessKeySecret;
+
+    @Value("${ali.oss.endPoint}")
+    private String endPoint;
+
+    @Value("${ali.oss.bucketName}")
+    private String bucketName;
+
+    /**
+     * oss上传文件
+     *
+     * @param multipartFile 前端上传的文件
+     * @param ossFilePath   oss中文件全路径(image/xxx.jpg)
+     * @return filePath
+     */
+    public String uploadFile(MultipartFile multipartFile, String ossFilePath) {
+        File convertFile = FileUtil.convert(multipartFile);
+        return uploadFile(convertFile, ossFilePath);
+    }
+
+    /**
+     * oss上传文件
+     *
+     * @param file        后端文件
+     * @param ossFilePath oss中文件全路径(image/xxx.jpg)
+     * @return filePath
+     */
+    public String uploadFile(File file, String ossFilePath) {
+        // 创建OSSClient实例。
+        // 当OSSClient实例不再使用时,调用shutdown方法以释放资源。
+        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
+        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
+        OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret);
+        try {
+            // 创建PutObjectRequest对象。
+            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, ossFilePath, file);
+            // 上传文件
+            PutObjectResult result = ossClient.putObject(putObjectRequest);
+            String eTag = result.getETag();
+            if (StringUtils.isNotEmpty(eTag)) {
+                //删除临时文件
+                file.delete();
+                return "https://" + bucketName + "." + endPoint + "/" + ossFilePath;
+            }
+            return null;
+        } catch (Exception e) {
+            log.error("AliOSSUtil.uploadFile ERROR: {}", e.getMessage());
+            return null;
+        } finally {
+            if (ossClient != null) {
+                ossClient.shutdown();
+            }
+        }
+    }
+
+}

+ 81 - 0
alien-util/src/main/java/shop/alien/util/ali/Demo.java

@@ -0,0 +1,81 @@
+package shop.alien.util.ali;
+
+import com.aliyun.oss.*;
+import com.aliyun.oss.common.auth.CredentialsProviderFactory;
+import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
+import com.aliyun.oss.common.comm.SignVersion;
+import com.aliyun.oss.model.PutObjectRequest;
+import com.aliyun.oss.model.PutObjectResult;
+
+import java.io.File;
+
+public class Demo {
+
+    public static void main(String[] args) throws Exception {
+
+        String accessKeyId = "LTAI5tG6wSYrSgN3Cwek17Du"; // 你的AccessKey ID
+        String accessKeySecret = "PQDPdTtDy0v848p0Bl9vT5yHmpt79H"; // 你的AccessKey Secret
+
+        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
+        String endpoint = "oss-cn-beijing.aliyuncs.com";
+        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
+        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
+        // 填写Bucket名称,例如examplebucket。
+        String bucketName = "alien-volume";
+        // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
+        String objectName = "image/微信图片_2025-07-15_104613_218.jpg";
+        // 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
+        // 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
+        String filePath = "C:\\Users\\17238\\Pictures\\微信图片_2025-07-15_104613_218.jpg";
+        // 填写Bucket所在地域。以华东1(杭州)为例,Region填写为cn-hangzhou。
+        String region = "cn-beijing";
+
+        // 创建OSSClient实例。
+        // 当OSSClient实例不再使用时,调用shutdown方法以释放资源。
+        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
+        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
+//        OSS ossClient = OSSClientBuilder.create()
+//                .endpoint(endpoint)
+//                .credentialsProvider(credentialsProvider)
+//                .clientConfiguration(clientBuilderConfiguration)
+//                .region(region)
+//                .build();
+
+        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+
+        try {
+            // 创建PutObjectRequest对象。
+            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new File(filePath));
+            // 默认使用Bucket的ACL设置(推荐生产环境使用Private)
+//            ObjectMetadata metadata = new ObjectMetadata();
+//             metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
+//             metadata.setObjectAcl(CannedAccessControlList.PublicRead);
+//             putObjectRequest.setMetadata(metadata);
+
+            // 上传文件。
+            PutObjectResult result = ossClient.putObject(putObjectRequest);
+            String fileUrl = "https://" + bucketName + "." + endpoint + "/" + objectName;
+            System.out.println("文件访问地址: " + fileUrl);
+        } catch (OSSException oe) {
+            System.out.println("Caught an OSSException, which means your request made it to OSS, "
+                    + "but was rejected with an error response for some reason.");
+            System.out.println("Error Message:" + oe.getErrorMessage());
+            System.out.println("Error Code:" + oe.getErrorCode());
+            System.out.println("Request ID:" + oe.getRequestId());
+            System.out.println("Host ID:" + oe.getHostId());
+        } catch (ClientException ce) {
+            System.out.println("Caught an ClientException, which means the client encountered "
+                    + "a serious internal problem while trying to communicate with OSS, "
+                    + "such as not being able to access the network.");
+            System.out.println("Error Message:" + ce.getMessage());
+        } finally {
+            if (ossClient != null) {
+                ossClient.shutdown();
+            }
+        }
+
+
+    }
+
+
+}

+ 17 - 22
alien-util/src/main/java/shop/alien/util/common/safe/ImageModerationUtil.java

@@ -1,21 +1,12 @@
 package shop.alien.util.common.safe;
 package shop.alien.util.common.safe;
+
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONObject;
 import com.aliyun.green20220302.Client;
 import com.aliyun.green20220302.Client;
-import com.aliyun.green20220302.models.ImageBatchModerationResponse;
-import com.aliyun.green20220302.models.ImageModerationRequest;
-import com.aliyun.green20220302.models.ImageModerationResponse;
-import com.aliyun.green20220302.models.ImageBatchModerationRequest;
-import com.aliyun.green20220302.models.ImageBatchModerationResponse;
-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.green20220302.models.*;
 import com.aliyun.teaopenapi.models.Config;
 import com.aliyun.teaopenapi.models.Config;
 import com.aliyun.teautil.models.RuntimeOptions;
 import com.aliyun.teautil.models.RuntimeOptions;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Lists;
-import jdk.nashorn.internal.runtime.logging.Logger;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
 
 
@@ -25,7 +16,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map;
 import java.util.UUID;
 import java.util.UUID;
 
 
-@Logger
+@Slf4j
 @Component
 @Component
 public class ImageModerationUtil {
 public class ImageModerationUtil {
 
 
@@ -40,7 +31,8 @@ public class ImageModerationUtil {
 
 
     /**
     /**
      * 创建请求客户端
      * 创建请求客户端
-     * @return  Client
+     *
+     * @return Client
      * @throws Exception 创建客户端异常
      * @throws Exception 创建客户端异常
      */
      */
     public Client createClient() throws Exception {
     public Client createClient() throws Exception {
@@ -63,12 +55,12 @@ public class ImageModerationUtil {
     /**
     /**
      * 提供给service调用的方法
      * 提供给service调用的方法
      *
      *
-     * @param imageUrl 图片地址
+     * @param imageUrl    图片地址
      * @param serviceEnum Service类型
      * @param serviceEnum Service类型
      * @return 检测结果
      * @return 检测结果
      * @throws Exception 检测异常
      * @throws Exception 检测异常
      */
      */
-    public ImageModerationResponse invokeFunction(String imageUrl,String serviceEnum) throws Exception {
+    public ImageModerationResponse invokeFunction(String imageUrl, String serviceEnum) throws Exception {
         //注意,此处实例化的client请尽可能重复使用,避免重复建立连接,提升检测性能。
         //注意,此处实例化的client请尽可能重复使用,避免重复建立连接,提升检测性能。
         Client client = createClient();
         Client client = createClient();
 
 
@@ -100,12 +92,12 @@ public class ImageModerationUtil {
     /**
     /**
      * 批量图片检测
      * 批量图片检测
      *
      *
-     * @param imageUrl 图片地址
+     * @param imageUrl    图片地址
      * @param serviceEnum Service类型 服务名逗号拼接
      * @param serviceEnum Service类型 服务名逗号拼接
      * @return 检测结果
      * @return 检测结果
      * @throws Exception 检测异常
      * @throws Exception 检测异常
      */
      */
-    public ImageBatchModerationResponse invokeBeachFunction(String imageUrl,String serviceEnum) throws Exception {
+    public ImageBatchModerationResponse invokeBeachFunction(String imageUrl, String serviceEnum) throws Exception {
         Client client = createClient();
         Client client = createClient();
         RuntimeOptions runtime = new RuntimeOptions();
         RuntimeOptions runtime = new RuntimeOptions();
         Map<String, String> serviceParameters = new HashMap<>();
         Map<String, String> serviceParameters = new HashMap<>();
@@ -122,6 +114,7 @@ public class ImageModerationUtil {
         }
         }
         return response;
         return response;
     }
     }
+
     /**
     /**
      * 发布商品场景检测
      * 发布商品场景检测
      * 顺序调用内容治理检测、AIGC图片风险检测、图片万物识别
      * 顺序调用内容治理检测、AIGC图片风险检测、图片万物识别
@@ -139,10 +132,10 @@ public class ImageModerationUtil {
         // TODO 后续配置到数据库 中
         // TODO 后续配置到数据库 中
         servicesList.add(ImageReviewServiceEnum.TONALITY_IMPROVE.getService());
         servicesList.add(ImageReviewServiceEnum.TONALITY_IMPROVE.getService());
         servicesList.add(ImageReviewServiceEnum.AIGC_CHECK.getService());
         servicesList.add(ImageReviewServiceEnum.AIGC_CHECK.getService());
-        for (String service : servicesList){
-            if (isSpecialService(service)){
+        for (String service : servicesList) {
+            if (isSpecialService(service)) {
                 serviceBatchEnum.append(service).append(",");
                 serviceBatchEnum.append(service).append(",");
-            }else {
+            } else {
                 serviceEnum.append(service).append(",");
                 serviceEnum.append(service).append(",");
             }
             }
         }
         }
@@ -176,7 +169,7 @@ public class ImageModerationUtil {
                     if ("high".equals(riskLevel)) {
                     if ("high".equals(riskLevel)) {
                         for (ImageBatchModerationResponseBody.ImageBatchModerationResponseBodyDataResult result : results) {
                         for (ImageBatchModerationResponseBody.ImageBatchModerationResponseBodyDataResult result : results) {
                             // 触发多个,如果置信分高于80 则拼接描述
                             // 触发多个,如果置信分高于80 则拼接描述
-                            if (result.getConfidence() > 80 ) {
+                            if (result.getConfidence() > 80) {
                                 String label = result.getLabel();
                                 String label = result.getLabel();
                                 String description = result.getDescription();
                                 String description = result.getDescription();
                                 // 拼接标签
                                 // 拼接标签
@@ -229,6 +222,7 @@ public class ImageModerationUtil {
 
 
     /**
     /**
      * 调用DeepSeek接口生成商品文案
      * 调用DeepSeek接口生成商品文案
+     *
      * @param prompt 提示信息
      * @param prompt 提示信息
      * @return 生成的文案
      * @return 生成的文案
      * @throws IOException 调用异常
      * @throws IOException 调用异常
@@ -240,6 +234,7 @@ public class ImageModerationUtil {
 
 
     /**
     /**
      * 判断服务是否为特殊服务,若是可以调取阿里多service审核服务,返回多个场景的总审核结果
      * 判断服务是否为特殊服务,若是可以调取阿里多service审核服务,返回多个场景的总审核结果
+     *
      * @param service 服务名称
      * @param service 服务名称
      * @return 是否为特殊服务
      * @return 是否为特殊服务
      */
      */

+ 52 - 0
alien-util/src/main/java/shop/alien/util/file/FileUtil.java

@@ -2,6 +2,7 @@ package shop.alien.util.file;
 
 
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.FileUtils;
+import org.springframework.web.multipart.MultipartFile;
 
 
 import java.io.File;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileInputStream;
@@ -459,4 +460,55 @@ public class FileUtil {
         return filePath.replace("\\", "/");
         return filePath.replace("\\", "/");
     }
     }
 
 
+
+    /**
+     * 文件转换
+     *
+     * @param multipartFile 前端上传的文件
+     * @return File
+     */
+    public static File convert(MultipartFile multipartFile) {
+        try {
+            // 创建一个临时文件
+            File tempFile = File.createTempFile("upload-", ".tmp");
+            // 将MultipartFile内容转存到临时文件中
+            multipartFile.transferTo(tempFile);
+            return tempFile;
+        } catch (IOException e) {
+            log.error("FileUtil.convert ERROR: {}", e.getMessage());
+            return null;
+        }
+    }
+
+    /**
+     * 获取文件名称和类型
+     *
+     * @param multipartFile
+     * @return
+     */
+    public static Map<String, String> getFileNameAndType(MultipartFile multipartFile) {
+        String originalFilename = multipartFile.getOriginalFilename();
+        Map<String, String> map = new HashMap<>();
+        String fileName = originalFilename.substring(0, originalFilename.lastIndexOf('.'));
+        String fileType = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
+        map.put("name", fileName);
+        map.put("type", fileType);
+        return map;
+    }
+
+    /**
+     * 获取文件名称和类型
+     *
+     * @param file
+     * @return
+     */
+    public static Map<String, String> getFileNameAndType(File file) {
+        String originalFilename = file.getName();
+        Map<String, String> map = new HashMap<>();
+        String fileName = originalFilename.substring(0, originalFilename.lastIndexOf('.'));
+        String fileType = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
+        map.put("name", fileName);
+        map.put("type", fileType);
+        return map;
+    }
 }
 }