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

Merge branch 'dev' of http://8.152.195.41:3000/alien/alien_cloud into zjy

zjy 1 місяць тому
батько
коміт
ee45651050
100 змінених файлів з 3034 додано та 145 видалено
  1. 120 0
      alien-config/src/main/java/shop/alien/config/properties/RiskControlProperties.java
  2. 50 0
      alien-entity/src/main/java/shop/alien/entity/second/LifeUserLog.java
  3. 90 0
      alien-entity/src/main/java/shop/alien/entity/second/SecondRiskControlRecord.java
  4. 54 0
      alien-entity/src/main/java/shop/alien/entity/second/SecondUserCredit.java
  5. 56 0
      alien-entity/src/main/java/shop/alien/entity/second/SecondUserCreditRecord.java
  6. 56 0
      alien-entity/src/main/java/shop/alien/entity/second/enums/RiskControlRuleTypeEnum.java
  7. 89 0
      alien-entity/src/main/java/shop/alien/entity/store/ExpertImg.java
  8. 12 0
      alien-entity/src/main/java/shop/alien/entity/store/LifeUser.java
  9. 13 0
      alien-entity/src/main/java/shop/alien/entity/store/LifeUserDynamics.java
  10. 30 0
      alien-entity/src/main/java/shop/alien/entity/store/LifeUserExpert.java
  11. 39 0
      alien-entity/src/main/java/shop/alien/entity/store/LifeUserExpertOrder.java
  12. 76 0
      alien-entity/src/main/java/shop/alien/entity/store/StoreAliPayErrorLog.java
  13. 2 0
      alien-entity/src/main/java/shop/alien/entity/store/StoreAliPayLog.java
  14. 4 0
      alien-entity/src/main/java/shop/alien/entity/store/StoreCashOutRecord.java
  15. 63 0
      alien-entity/src/main/java/shop/alien/entity/store/StoreCommentSummaryInterest.java
  16. 49 0
      alien-entity/src/main/java/shop/alien/entity/store/StoreInfoUserMiddle.java
  17. 64 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/ExpertImgVo.java
  18. 9 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/LifeUserDynamicsVo.java
  19. 64 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/LifeUserExpertOrderVo.java
  20. 33 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/LifeUserExpertVo.java
  21. 4 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/LifeUserOrderVo.java
  22. 3 1
      alien-entity/src/main/java/shop/alien/entity/store/vo/ManagementInfoVo.java
  23. 1 1
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreCommentAppealVo.java
  24. 4 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreCommentVo.java
  25. 1 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreInfoVo.java
  26. 20 0
      alien-entity/src/main/java/shop/alien/mapper/ExpertImgMapper.java
  27. 16 0
      alien-entity/src/main/java/shop/alien/mapper/LifeCouponMapper.java
  28. 20 2
      alien-entity/src/main/java/shop/alien/mapper/LifeGroupBuyMainMapper.java
  29. 37 5
      alien-entity/src/main/java/shop/alien/mapper/LifeUserDynamicsMapper.java
  30. 23 4
      alien-entity/src/main/java/shop/alien/mapper/LifeUserExpertMapper.java
  31. 45 2
      alien-entity/src/main/java/shop/alien/mapper/LifeUserExpertOrderMapper.java
  32. 1 2
      alien-entity/src/main/java/shop/alien/mapper/LifeUserOrderMapper.java
  33. 2 0
      alien-entity/src/main/java/shop/alien/mapper/ManagementInfoMapper.java
  34. 15 0
      alien-entity/src/main/java/shop/alien/mapper/StoreAliPayErrorLogMapper.java
  35. 1 1
      alien-entity/src/main/java/shop/alien/mapper/StoreCommentAppealMapper.java
  36. 40 0
      alien-entity/src/main/java/shop/alien/mapper/StoreCommentSummaryInterestMapper.java
  37. 13 0
      alien-entity/src/main/java/shop/alien/mapper/StoreInfoMapper.java
  38. 9 0
      alien-entity/src/main/java/shop/alien/mapper/StoreInfoUserMiddleMapper.java
  39. 10 0
      alien-entity/src/main/java/shop/alien/mapper/second/SecondRiskControlRecordMapper.java
  40. 4 4
      alien-entity/src/main/java/shop/alien/mapper/second/SecondTradeRecordMapper.java
  41. 12 0
      alien-entity/src/main/java/shop/alien/mapper/second/SecondUserCreditMapper.java
  42. 12 0
      alien-entity/src/main/java/shop/alien/mapper/second/SecondUserCreditRecordMapper.java
  43. 27 0
      alien-entity/src/main/resources/mapper/ExpertImgMapper.xml
  44. 29 2
      alien-entity/src/main/resources/mapper/LifeUserDynamicsMapper.xml
  45. 8 1
      alien-entity/src/main/resources/mapper/LifeUserExpertMapper.xml
  46. 12 3
      alien-entity/src/main/resources/mapper/LifeUserExpertOrderMapper.xml
  47. 9 3
      alien-entity/src/main/resources/mapper/LifeUserOrderMapper.xml
  48. 33 2
      alien-entity/src/main/resources/mapper/ManagementInfoMapper.xml
  49. 5 0
      alien-gateway/pom.xml
  50. 2 0
      alien-gateway/src/main/java/shop/alien/gateway/AlienGatewayApplication.java
  51. 4 3
      alien-gateway/src/main/java/shop/alien/gateway/controller/LifeUserController.java
  52. 36 0
      alien-gateway/src/main/java/shop/alien/gateway/feign/SecondServiceFeign.java
  53. 27 0
      alien-gateway/src/main/java/shop/alien/gateway/mapper/LifeUserLogMapper.java
  54. 51 1
      alien-gateway/src/main/java/shop/alien/gateway/service/LifeUserService.java
  55. 22 0
      alien-gateway/src/main/resources/bootstrap-uat.yml
  56. 1 1
      alien-job/src/main/java/shop/alien/job/feign/AlienStoreFeign.java
  57. 106 0
      alien-job/src/main/java/shop/alien/job/store/AiTagJob.java
  58. 2 2
      alien-job/src/main/java/shop/alien/job/store/LifeUserOrderJob.java
  59. 3 2
      alien-job/src/main/java/shop/alien/job/store/StoreMembershipCardJob.java
  60. 22 0
      alien-job/src/main/resources/bootstrap-uat.yml
  61. 1 0
      alien-second/src/main/java/shop/alien/second/AlienSecondApplication.java
  62. 34 0
      alien-second/src/main/java/shop/alien/second/controller/RiskControlController.java
  63. 5 0
      alien-second/src/main/java/shop/alien/second/controller/SecondGoodsController.java
  64. 81 0
      alien-second/src/main/java/shop/alien/second/controller/SecondUserPointsController.java
  65. 60 0
      alien-second/src/main/java/shop/alien/second/controller/SecondUserPointsRecordController.java
  66. 39 0
      alien-second/src/main/java/shop/alien/second/platform/PlatformSecondUserFreezeController.java
  67. 36 0
      alien-second/src/main/java/shop/alien/second/service/RiskControlService.java
  68. 9 0
      alien-second/src/main/java/shop/alien/second/service/SecondGoodsService.java
  69. 24 0
      alien-second/src/main/java/shop/alien/second/service/SecondUserCreditRecordService.java
  70. 33 0
      alien-second/src/main/java/shop/alien/second/service/SecondUserCreditService.java
  71. 75 0
      alien-second/src/main/java/shop/alien/second/service/impl/RiskControlServiceImpl.java
  72. 174 16
      alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsServiceImpl.java
  73. 59 0
      alien-second/src/main/java/shop/alien/second/service/impl/SecondUserCreditRecordServiceImpl.java
  74. 124 0
      alien-second/src/main/java/shop/alien/second/service/impl/SecondUserCreditServiceImpl.java
  75. 22 0
      alien-second/src/main/resources/bootstrap-uat.yml
  76. 5 0
      alien-store/pom.xml
  77. 2 0
      alien-store/src/main/java/shop/alien/store/AlienStoreApplication.java
  78. 2 1
      alien-store/src/main/java/shop/alien/store/controller/AliController.java
  79. 8 4
      alien-store/src/main/java/shop/alien/store/controller/LifePromotionPackageController.java
  80. 35 0
      alien-store/src/main/java/shop/alien/store/controller/LifeUserController.java
  81. 33 1
      alien-store/src/main/java/shop/alien/store/controller/LifeUserDynamicsController.java
  82. 121 6
      alien-store/src/main/java/shop/alien/store/controller/LifeUserExpertController.java
  83. 15 3
      alien-store/src/main/java/shop/alien/store/controller/LifeUserExpertOrderController.java
  84. 0 23
      alien-store/src/main/java/shop/alien/store/controller/LifeUserOrderController.java
  85. 10 0
      alien-store/src/main/java/shop/alien/store/controller/ManagementInfoController.java
  86. 14 1
      alien-store/src/main/java/shop/alien/store/controller/StoreInfoController.java
  87. 16 0
      alien-store/src/main/java/shop/alien/store/controller/StoreUserExpertController.java
  88. 36 0
      alien-store/src/main/java/shop/alien/store/feign/SecondServiceFeign.java
  89. 1 0
      alien-store/src/main/java/shop/alien/store/service/LifeDictService.java
  90. 100 11
      alien-store/src/main/java/shop/alien/store/service/LifeUserDynamicsService.java
  91. 3 1
      alien-store/src/main/java/shop/alien/store/service/LifeUserExpertOrderService.java
  92. 16 1
      alien-store/src/main/java/shop/alien/store/service/LifeUserExpertService.java
  93. 34 14
      alien-store/src/main/java/shop/alien/store/service/LifeUserOrderService.java
  94. 41 1
      alien-store/src/main/java/shop/alien/store/service/LifeUserService.java
  95. 57 12
      alien-store/src/main/java/shop/alien/store/service/LifeUserStoreService.java
  96. 2 0
      alien-store/src/main/java/shop/alien/store/service/ManagementInfoService.java
  97. 2 1
      alien-store/src/main/java/shop/alien/store/service/PromotionPackageService.java
  98. 15 0
      alien-store/src/main/java/shop/alien/store/service/StoreAliPayErrorLogService.java
  99. 6 0
      alien-store/src/main/java/shop/alien/store/service/StoreUserExpertService.java
  100. 19 7
      alien-store/src/main/java/shop/alien/store/service/impl/LifeGroupBuyServiceImpl.java

+ 120 - 0
alien-config/src/main/java/shop/alien/config/properties/RiskControlProperties.java

@@ -0,0 +1,120 @@
+package shop.alien.config.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
+import org.springframework.stereotype.Component;
+
+@Data
+@Component
+@RefreshScope
+@ConfigurationProperties(prefix = "risk-control")
+public class RiskControlProperties {
+
+    /**
+     * 洗钱嫌疑规则配置
+     */
+    private MoneyLaundering moneyLaundering = new MoneyLaundering();
+
+    /**
+     * 账号异常规则配置
+     */
+    private AccountAbnormal accountAbnormal = new AccountAbnormal();
+
+    /**
+     * 交易欺诈规则配置
+     */
+    private TradeFraud tradeFraud = new TradeFraud();
+
+    /**
+     * 异常发布规则配置
+     */
+    private AbnormalPublish abnormalPublish = new AbnormalPublish();
+
+    @Data
+    public static class MoneyLaundering {
+        /**
+         * 每天交易次数阈值
+         */
+        private int dailyCount = 5;
+
+        /**
+         * 每笔交易金额阈值(元)
+         */
+        private double amountThreshold = 200.0;
+
+        /**
+         * 风险类型
+         */
+        private String riskType = "洗钱嫌疑";
+
+        /**
+         * 检测指标
+         */
+        private String detectIndicator = "高频高价交易";
+    }
+
+    @Data
+    public static class AccountAbnormal {
+        /**
+         * 24小时内同一设备/mac注册账号数量阈值
+         */
+        private int regCount24h = 3;
+
+        /**
+         * 风险类型
+         */
+        private String riskType = "账号异常";
+
+        /**
+         * 检测指标
+         */
+        private String detectIndicator = "同一设备24小时内注册超过3个账号";
+    }
+
+    @Data
+    public static class TradeFraud {
+        /**
+         * 24小时内发布成功记录次数阈值
+         */
+        private int publishCount24h = 3;
+
+        /**
+         * 时间窗口(小时)
+         */
+        private int timeWindowHours = 24;
+
+        /**
+         * 风险类型
+         */
+        private String riskType = "交易欺诈";
+
+        /**
+         * 检测指标
+         */
+        private String detectIndicator = "用户频繁修改商品";
+    }
+
+    @Data
+    public static class AbnormalPublish {
+        /**
+         * 24小时内发布同类商品数量阈值
+         */
+        private int sameCategoryCount24h = 10;
+        
+        /**
+         * 时间窗口(小时)
+         */
+        private int timeWindowHours = 24;
+
+        /**
+         * 风险类型
+         */
+        private String riskType = "异常发布";
+
+        /**
+         * 检测指标
+         */
+        private String detectIndicator = "短时间大量发布同类商品";
+    }
+}

+ 50 - 0
alien-entity/src/main/java/shop/alien/entity/second/LifeUserLog.java

@@ -0,0 +1,50 @@
+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("life_user_log")
+public class LifeUserLog implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @TableField("user_id")
+    private Integer userId;
+
+    @TableField("user_name")
+    private String userName;
+
+    @TableField("mac_ip")
+    private String macIp;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(value = "created_time", fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createdTime;
+
+    @ApiModelProperty(value = "创建人ID")
+    @TableField("created_user_id")
+    private Integer createdUserId;
+
+    @ApiModelProperty(value = "修改时间")
+    @TableField(value = "updated_time", fill = FieldFill.UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updatedTime;
+
+    @ApiModelProperty(value = "修改人ID")
+    @TableField("updated_user_id")
+    private Integer updatedUserId;
+}

+ 90 - 0
alien-entity/src/main/java/shop/alien/entity/second/SecondRiskControlRecord.java

@@ -0,0 +1,90 @@
+package shop.alien.entity.second;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+@JsonInclude
+@TableName("second_risk_control_record")
+public class SecondRiskControlRecord extends Model<SecondRiskControlRecord> {
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    @ApiModelProperty(value = "主键ID")
+    private Integer id;
+
+    @TableField("user_id")
+    @ApiModelProperty(value = "用户ID")
+    private Integer userId;
+
+    @TableField("rule_type")
+    @ApiModelProperty(value = "规则类型 1:洗钱嫌疑 2:账号异常 3:交易欺诈 4:异常发布")
+    private Integer ruleType;
+
+    @TableField("rule_name")
+    @ApiModelProperty(value = "规则名称")
+    private String ruleName;
+
+    @TableField("rule_type")
+    @ApiModelProperty(value = "风控执行状态 0 未执行,1-已执行 2-已忽略")
+    private Integer riskStatus;
+
+//
+//    @TableField("trigger_count")
+//    @ApiModelProperty(value = "触发次数")
+//    private Integer triggerCount;
+//
+//    @TableField("time_window_hours")
+//    @ApiModelProperty(value = "时间窗口(小时)")
+//    private Integer timeWindowHours;
+//
+//    @TableField("threshold_value")
+//    @ApiModelProperty(value = "阈值")
+//    private Integer thresholdValue;
+//
+//    @TableField("actual_value")
+//    @ApiModelProperty(value = "实际值")
+//    private Integer actualValue;
+
+    @TableField("business_id")
+    @ApiModelProperty(value = "业务ID(如商品ID、交易ID等)")
+    private String businessId;
+
+//    @TableField("business_type")
+//    @ApiModelProperty(value = "业务类型 1:二手商品 2:交易记录")
+//    private Integer businessType;
+
+    @TableField("detail_info")
+    @ApiModelProperty(value = "详细信息(JSON格式)")
+    private String detailInfo;
+
+    @TableField("delete_flag")
+    @ApiModelProperty(value = "删除标记 0:未删除 1:已删除")
+    private Integer deleteFlag;
+
+    @TableField("created_time")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ApiModelProperty(value = "创建时间")
+    private Date createdTime;
+
+    @TableField(value = "created_user_id", fill = FieldFill.INSERT)
+    @ApiModelProperty(value = "创建人ID")
+    private Integer createdUserId;
+
+    @TableField("updated_time")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ApiModelProperty(value = "修改时间")
+    private Date updatedTime;
+
+    @TableField(value = "updated_user_id", fill = FieldFill.INSERT_UPDATE)
+    @ApiModelProperty(value = "修改人ID")
+    private Integer updatedUserId;
+}

+ 54 - 0
alien-entity/src/main/java/shop/alien/entity/second/SecondUserCredit.java

@@ -0,0 +1,54 @@
+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_user_credit")
+public class SecondUserCredit implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @TableField("user_id")
+    private Integer userId;
+
+    @TableField("user_points")
+    private Integer userPoints;
+
+    @TableField("delete_flag")
+    private Integer deleteFlag;
+
+    @ApiModelProperty(value = "冻结时间")
+    @TableField("freeze_time")
+    private Date freezeTime;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(value = "created_time", fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createdTime;
+
+    @ApiModelProperty(value = "创建人ID")
+    @TableField("created_user_id")
+    private Integer createdUserId;
+
+    @ApiModelProperty(value = "修改时间")
+    @TableField(value = "updated_time", fill = FieldFill.UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updatedTime;
+
+    @ApiModelProperty(value = "修改人ID")
+    @TableField("updated_user_id")
+    private Integer updatedUserId;
+}

+ 56 - 0
alien-entity/src/main/java/shop/alien/entity/second/SecondUserCreditRecord.java

@@ -0,0 +1,56 @@
+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_user_credit_record")
+public class SecondUserCreditRecord implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @TableField("user_id")
+    private Integer userId;
+
+    @TableField("points")
+    private Integer points;
+
+    @TableField("points_type")
+    private Integer pointsType;
+
+    @TableField("user_points")
+    private Integer userPoints;
+
+    @TableField("delete_flag")
+    private Integer deleteFlag;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(value = "created_time", fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createdTime;
+
+    @ApiModelProperty(value = "创建人ID")
+    @TableField("created_user_id")
+    private Integer createdUserId;
+
+    @ApiModelProperty(value = "修改时间")
+    @TableField(value = "updated_time", fill = FieldFill.UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updatedTime;
+
+    @ApiModelProperty(value = "修改人ID")
+    @TableField("updated_user_id")
+    private Integer updatedUserId;
+}

+ 56 - 0
alien-entity/src/main/java/shop/alien/entity/second/enums/RiskControlRuleTypeEnum.java

@@ -0,0 +1,56 @@
+package shop.alien.entity.second.enums;
+
+import lombok.Getter;
+
+/**
+ * 风控规则类型枚举
+ * @see RiskControlRuleTypeEnum 风控规则类型枚举
+ */
+@Getter
+public enum RiskControlRuleTypeEnum {
+    /**
+     * 洗钱嫌疑: 高频高价交易(>5次/天,>200元/笔)
+     */
+    MONEY_LAUNDERING_SUSPICION(1, "洗钱嫌疑", "24h>5次>200元"),
+
+    /**
+     * 账号异常: 同一设备/mac 24小时内注册超过3个账号
+     */
+    ACCOUNT_ABNORMAL(2, "账号异常", "24h同设备>3账号"),
+
+    /**
+     * 交易欺诈: 用户频繁修改商品 发布成功的记录(24小时 3次 - 调取接口发当前时间 倒推24小时)
+     */
+    TRANSACTION_FRAUD(3, "交易欺诈", "24h修改商品>3次"),
+
+    /**
+     * 异常发布: 短时间大量发布同类商品(如24小时发布10个同二级分类触发- 调取接口发当前时间 倒推24小时)
+     */
+    ABNORMAL_PUBLISH(4, "异常发布", "24h同分类>10商品");
+
+
+    private final Integer ruleType;
+    private final String ruleName;
+    private final String description;
+
+    RiskControlRuleTypeEnum(Integer ruleType, String ruleName, String description) {
+        this.ruleType = ruleType;
+        this.ruleName = ruleName;
+        this.description = description;
+    }
+
+    /**
+     * 根据ruleType获取枚举
+     *
+     * @param ruleType 规则类型
+     * @return 对应的枚举值
+     */
+    public static RiskControlRuleTypeEnum fromRuleType(Integer ruleType) {
+        for (RiskControlRuleTypeEnum rule : RiskControlRuleTypeEnum.values()) {
+            if (rule.getRuleType().equals(ruleType)) {
+                return rule;
+            }
+        }
+        return null;
+    }
+}

+ 89 - 0
alien-entity/src/main/java/shop/alien/entity/store/ExpertImg.java

@@ -0,0 +1,89 @@
+package shop.alien.entity.store;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.util.Date;
+
+/**
+ * <p>
+ * 达人图片表
+ * </p>
+ *
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value="ExpertImg对象", description="达人图片表")
+public class ExpertImg extends Model<ExpertImg> {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "主键id")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty(value = "达人id")
+    @TableField(value = "expert_id")
+    private Integer expertId;
+
+    @ApiModelProperty(value = "达人码")
+    @TableField("expert_code")
+    private Integer expertCode;
+
+    @ApiModelProperty(value = "用户id(life_user表id)")
+    @TableField("user_id")
+    private Integer userId;
+
+
+    @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
+    @TableField("delete_flag")
+    @TableLogic
+    private Integer deleteFlag;
+
+
+    @ApiModelProperty(value = "图片类型 0 申请成为达人上传的图片")
+    @TableField("img_type")
+    private Integer imgType;
+
+    @ApiModelProperty(value = "图片描述")
+    @TableField("img_description")
+    private String imgDescription;
+
+    @ApiModelProperty(value = "图片排序")
+    @TableField("img_sort")
+    private Integer imgSort;
+
+    @ApiModelProperty(value = "图片路径")
+    @TableField("img_url")
+    private String imgUrl;
+
+    @ApiModelProperty(value = "补充说明")
+    @TableField(value = "add_explanation")
+    private String addExplanation;
+
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(value = "created_time", fill = FieldFill.INSERT)
+    private Date createdTime;
+
+
+    @ApiModelProperty(value = "修改时间")
+    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
+    private Date updatedTime;
+
+
+
+
+
+
+
+
+
+
+}

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

@@ -121,4 +121,16 @@ public class LifeUser implements Serializable {
     @ApiModelProperty(value = "绑定他人邀请码")
     @TableField("bind_invite_code")
     private String bindInviteCode;
+
+    @ApiModelProperty(value = "支付宝账号")
+    @TableField("alipay_account")
+    private String alipayAccount;
+
+    @ApiModelProperty(value = "用户余额")
+    @TableField("money")
+    private Integer money;
+
+    @ApiModelProperty(value = "支付密码")
+    @TableField("pay_password")
+    private String payPassword;
 }

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

@@ -6,6 +6,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
+import java.math.BigDecimal;
 import java.util.Date;
 
 /**
@@ -112,4 +113,16 @@ public class LifeUserDynamics {
     @ApiModelProperty(value = "启用状态0-启用,1-禁用")
     @TableField("enable_status")
     private Integer enableStatus;
+
+    @ApiModelProperty(value = "订单GMV (达人发布动态使用的)")
+    @TableField("order_gmv")
+    private BigDecimal orderGmv;
+
+    @ApiModelProperty(value = "业务id")
+    @TableField("business_id")
+    private Integer businessId;
+
+    @ApiModelProperty(value = "根据动态进入店铺详情浏览数")
+    @TableField("store_count")
+    private Integer storeCount;
 }

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

@@ -66,4 +66,34 @@ public class LifeUserExpert extends Model<LifeUserExpert> {
     @TableField(value = "updated_user_id", fill = FieldFill.INSERT_UPDATE)
     private Integer updatedUserId;
 
+    @ApiModelProperty(value = "审核状态  0审核通过 1审核中 2审核未通过")
+    @TableField(value = "expert_status")
+    private Integer expertStatus;
+
+    @ApiModelProperty(value = "补充说明 ")
+    @TableField(value = "add_explanation")
+    private String addExplanation;
+
+    @ApiModelProperty(value = "拒绝原因 ")
+    @TableField(value = "refuse_because")
+    private String refuseBecause;
+
+    @ApiModelProperty(value = "审核时间 ")
+    @TableField(value = "review_time")
+    private Date reviewTime;
+
+    @ApiModelProperty(value = "佣金比例 ")
+    @TableField(value = "commission_rate")
+    private Integer commissionRate;
+
+    @ApiModelProperty(value = "预付款比例 ")
+    @TableField(value = "advance_rate")
+    private Integer advanceRate;
+
+    @ApiModelProperty(value = "推广类型 ")
+    @TableField(value = "promote_type")
+    private String promoteType;
+
+
+
 }

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

@@ -46,6 +46,10 @@ public class LifeUserExpertOrder extends Model<LifeUserExpertOrder> {
     @TableField("store_id")
     private Integer storeId;
 
+    @ApiModelProperty(value = "推广套餐id")
+    @TableField("package_id")
+    private Integer packageId;
+
     @ApiModelProperty(value = "订单金额")
     @TableField("order_money")
     private BigDecimal orderMoney;
@@ -78,6 +82,10 @@ public class LifeUserExpertOrder extends Model<LifeUserExpertOrder> {
     @TableField("order_gmv")
     private BigDecimal orderGmv;
 
+    @ApiModelProperty(value = "临时测试")
+    @TableField("actual_gmv")
+    private BigDecimal actualGmv;
+
     @ApiModelProperty(value = "状态(1-待完成  2-已完成)")
     @TableField("status")
     private Integer status;
@@ -103,4 +111,35 @@ public class LifeUserExpertOrder extends Model<LifeUserExpertOrder> {
     @TableField(value = "updated_user_id", fill = FieldFill.INSERT_UPDATE)
     private Integer updatedUserId;
 
+    @ApiModelProperty(value = "预付款审核状态 预付款审核  0审核通过  1待审核  2审核拒绝")
+    @TableField(value = "advance_payment_status")
+    private String advancePaymentStatus;
+
+    @ApiModelProperty(value = "申请尾款按钮状态 0未点击  1已点击审核中  2已点击审核通过  3已点击审核拒绝")
+    @TableField(value = "end_funds_button")
+    private String endFundsButton;
+
+    @ApiModelProperty(value = "预付款审核拒绝原因")
+    @TableField(value = "reason_refusal")
+    private String reasonRefusal;
+
+    @ApiModelProperty(value = "预付款审核时间")
+    @TableField(value = "advance_payment_time")
+    private Date advancePaymentTime;
+
+    @ApiModelProperty(value = "点击申请尾款按钮时间")
+    @TableField(value = "end_funds_time")
+    private Date endFundsTime;
+
+    @ApiModelProperty(value = "尾款审核时间")
+    @TableField(value = "end_payment_time")
+    private Date endPaymentTime;
+
+    @ApiModelProperty(value = "尾款拒绝原因")
+    @TableField(value = "end_payment_refusal")
+    private String endPaymentRefusal;
+
+    @ApiModelProperty(value = "支付时间")
+    @TableField("pay_time")
+    private Date payTime;
 }

+ 76 - 0
alien-entity/src/main/java/shop/alien/entity/store/StoreAliPayErrorLog.java

@@ -0,0 +1,76 @@
+package shop.alien.entity.store;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 支付宝转账记录错误信息表
+ * qxy
+ */
+@Data
+@JsonInclude
+@ApiModel(value = "StoreAliPayErrorLog对象", description = "支付宝转账记录错误信息表")
+public class StoreAliPayErrorLog extends Model<StoreAliPayErrorLog> {
+
+    @ApiModelProperty(value = "主键")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty(value = "商户ID")
+    @TableField("store_user_id")
+    private Integer storeUserId;
+
+    @ApiModelProperty(value = "用户ID")
+    @TableField("life_user_id")
+    private Integer lifeUserId;
+
+    @ApiModelProperty(value = "订单总金额")
+    @TableField("trans_amount")
+    private String transAmount;
+
+    @ApiModelProperty(value = "阿里返回错误信息")
+    @TableField("sub_msg")
+    private String subMsg;
+
+    @ApiModelProperty(value = "阿里返回状态码")
+    @TableField("sub_code")
+    private String subCode;
+
+    @ApiModelProperty(value = "阿里返回参数具体内容")
+    @TableField("biz_content")
+    private String bizContent;
+
+    @ApiModelProperty(value = "错误信息")
+    @TableField("information")
+    private String information;
+
+    @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
+    @TableField("delete_flag")
+    @TableLogic
+    private Integer deleteFlag;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(value = "created_time", fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createdTime;
+
+    @ApiModelProperty(value = "创建人ID")
+    @TableField("created_user_id")
+    private Integer createdUserId;
+
+    @ApiModelProperty(value = "修改时间")
+    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updatedTime;
+
+    @ApiModelProperty(value = "修改人ID")
+    @TableField("updated_user_id")
+    private Integer updatedUserId;
+}

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

@@ -74,4 +74,6 @@ public class StoreAliPayLog extends Model<StoreAliPayLog> {
     @TableField("updated_user_id")
     private Integer updatedUserId;
 
+    private StoreAliPayErrorLog storeAliPayErrorLog;
+
 }

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

@@ -113,4 +113,8 @@ public class StoreCashOutRecord extends Model<StoreCashOutRecord> {
     @ApiModelProperty(value = "结算账户")
     @TableField(value = "settlement_account")
     private String settlementAccount;
+
+    @ApiModelProperty(value = "拒绝原因")
+    @TableField(value = "approve_fail_reason")
+    private String approveFailReason;
 }

+ 63 - 0
alien-entity/src/main/java/shop/alien/entity/store/StoreCommentSummaryInterest.java

@@ -0,0 +1,63 @@
+package shop.alien.entity.store;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * AI服务 店铺推荐趣味信息表
+ */
+@Data
+@JsonInclude
+@TableName("store_comment_summary_interest")
+@ApiModel(value = "store_comment_summary_interest", description = "store_comment_summary_interest")
+public class StoreCommentSummaryInterest {
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty(value = "店铺ID(新增字段)")
+    @TableField("store_id")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "店铺名称(对应表格“店铺名称”)")
+    @TableField("store_name")
+    private String storeName;
+
+    @ApiModelProperty(value = "总结内容(对应表格“总结内容”,允许为空)")
+    @TableField("summary")
+    private String summary;
+
+    @ApiModelProperty(value = "任务唯一标识(如 UUID,新增字段)")
+    @TableField("task_id")
+    private String taskId;
+
+    @ApiModelProperty(value = "删除标识")
+    @TableLogic
+    @TableField("delete_flag")
+    private Integer  deleteFlag;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(value = "created_time", fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createdTime;
+
+    @ApiModelProperty(value = "创建人ID")
+    @TableField("created_user_id")
+    private Integer createdUserId;
+
+    @ApiModelProperty(value = "修改时间")
+    @TableField(value = "updated_time", fill = FieldFill.UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updatedTime;
+
+    @ApiModelProperty(value = "修改人ID")
+    @TableField("updated_user_id")
+    private Integer updatedUserId;
+}

+ 49 - 0
alien-entity/src/main/java/shop/alien/entity/store/StoreInfoUserMiddle.java

@@ -0,0 +1,49 @@
+package shop.alien.entity.store;
+
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+@JsonInclude
+@TableName("store_info_user_middle")
+@ApiModel(value = "StoreInfoUserMiddle", description = "商户和商铺中间关系表")
+public class StoreInfoUserMiddle {
+
+    @ApiModelProperty(value = "主键")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty(value = "商户(store_user 表 id)")
+    @TableField("user_id")
+    private Integer userId;
+
+    @ApiModelProperty(value = "商铺(store_info 表 id)")
+    @TableField("store_id")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
+    @TableField("delete_flag")
+    @TableLogic
+    private Integer deleteFlag;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(value = "created_time", fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createdTime;
+
+    @ApiModelProperty(value = "创建人ID")
+    @TableField("created_user_id")
+    private Integer createdUserId;
+
+    @ApiModelProperty(value = "修改时间")
+    @TableField(value = "updated_time", fill = FieldFill.UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updatedTime;
+}

+ 64 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/ExpertImgVo.java

@@ -0,0 +1,64 @@
+package shop.alien.entity.store.vo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+import shop.alien.entity.store.LifeUserExpertOrder;
+
+import java.util.Date;
+
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value="ExpertImgVo", description="达人申请图片vo")
+public class ExpertImgVo extends LifeUserExpertOrder {
+
+    @ApiModelProperty(value = "主键id")
+    private Integer id;
+
+    @ApiModelProperty(value = "达人id")
+    private Integer expertId;
+
+    @ApiModelProperty(value = "达人码")
+    private Integer expertCode;
+
+    @ApiModelProperty(value = "用户id(life_user表id)")
+    private Integer userId;
+
+
+    @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
+    private Integer deleteFlag;
+
+
+    @ApiModelProperty(value = "图片类型 0 申请成为达人上传的图片")
+    private Integer imgType;
+
+    @ApiModelProperty(value = "图片描述")
+    private String imgDescription;
+
+    @ApiModelProperty(value = "图片排序")
+    private Integer imgSort;
+
+    @ApiModelProperty(value = "图片路径")
+    private String imgUrl;
+
+    @ApiModelProperty(value = "补充说明")
+    private String addExplanation;
+
+
+    @ApiModelProperty(value = "创建时间")
+    private Date createdTime;
+
+
+    @ApiModelProperty(value = "修改时间")
+    private Date updatedTime;
+
+    @ApiModelProperty(value = "推广类型")
+    private String promoteType;
+
+
+}

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

@@ -68,4 +68,13 @@ public class LifeUserDynamicsVo extends LifeUserDynamics {
 
     @ApiModelProperty(value = "商家名称")
     private String storeName;
+
+    @ApiModelProperty(value = "商家评分")
+    private String scoreAvg;
+
+    @ApiModelProperty(value = "门店id")
+    private String storeId;
+
+    @ApiModelProperty(value = "门店经营板块")
+    private String businessSection;
 }

+ 64 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/LifeUserExpertOrderVo.java

@@ -44,6 +44,9 @@ public class LifeUserExpertOrderVo extends LifeUserExpertOrder {
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private Date earliestCreatedTime;
 
+    @ApiModelProperty(value = "订单金额")
+    private BigDecimal orderMoney;
+
     @ApiModelProperty(value = "到账总金额")
     private BigDecimal accountMoney;
 
@@ -59,5 +62,66 @@ public class LifeUserExpertOrderVo extends LifeUserExpertOrder {
     @ApiModelProperty(value = "进店浏览数")
     private Integer storeVisitViewCount;
 
+    @ApiModelProperty(value = "套餐名称")
+    private String name;
+
+    @ApiModelProperty(value = "申请首款按钮")
+    @TableField(value = "first_funds_button")
+    private String firstFundsButton;
+
+    @ApiModelProperty(value = "申请尾款按钮")
+    @TableField(value = "end_funds_button")
+    private String endFundsButton;
+
+    @ApiModelProperty(value = "推广类型")
+    @TableField(value = "promote_type")
+    private String promoteType;
+
+    @ApiModelProperty(value = "用户真实姓名")
+    @TableField(value = "real_name")
+    private String realName;
+
+    @ApiModelProperty(value = "用户手机号")
+    @TableField(value = "user_phone")
+    private String userPhone;
+
+    @ApiModelProperty(value = "佣金")
+    private BigDecimal commission;
+
+    @ApiModelProperty(value = "预付款")
+    private BigDecimal advance;
+
+    @ApiModelProperty(value = "预付款比例")
+    @TableField(value = "advance_rate")
+    private Integer advanceRate;
+
+    @ApiModelProperty(value = "佣金比例")
+    @TableField(value = "commission_rate")
+    private Integer commissionRate;
+
+    @ApiModelProperty(value = "预付款审核状态  0审核通过  1待审核  2审核拒绝")
+    @TableField(value = "advance_payment_status")
+    private String advancePaymentStatus;
+
+    @ApiModelProperty(value = "身份证号")
+    private String idCard;
+
+    @ApiModelProperty(value = "预付款审核时间")
+    @TableField(value = "advance_payment_time")
+    private Date advancePaymentTime;
+
+    @ApiModelProperty(value = "门店电话")
+    private String storeTel;
+
+    @ApiModelProperty(value = "订单GMV  订单表gmv数据保存两位小数")
+    private String orderNewGmv;
+
+    @ApiModelProperty(value = "达人昵称")
+    private String userName;
+
+    @ApiModelProperty(value = "尾款比例")
+    private Integer endPaymentRate;
 
+    @ApiModelProperty(value = "尾款金额")
+    private BigDecimal endPayment;
 }

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

@@ -1,5 +1,6 @@
 package shop.alien.entity.store.vo;
 
+import com.baomidou.mybatisplus.annotation.TableField;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
@@ -97,4 +98,36 @@ public class LifeUserExpertVo extends LifeUserExpert {
 
     @ApiModelProperty(value = "性别占比")
     private List<Map<String, String>> sexPercentageList;
+
+    @ApiModelProperty(value = "审核状态  0审核通过 1审核中 2审核未通过")
+    private Integer expertStatus;
+
+    @ApiModelProperty(value = "推广类型")
+    private String promoteType;
+
+    @ApiModelProperty(value = "补充说明")
+    private String addExplanation;
+
+    @ApiModelProperty(value = "图片路径")
+    private String imgUrl;
+
+    @ApiModelProperty(value = "拒绝原因")
+    private String refuseBecause;
+
+    @ApiModelProperty(value = "审核时间")
+    private Date reviewTime;
+
+    @ApiModelProperty(value = "佣金比例 ")
+    private Integer commissionRate;
+
+    @ApiModelProperty(value = "预付款比例 ")
+    private Integer advanceRate;
+
+    @ApiModelProperty(value = "完成时间 ")
+    private Date completeTime;
+
+    @ApiModelProperty(value = "店铺名称")
+    private String storeName;
+
+
 }

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

@@ -182,4 +182,8 @@ public class LifeUserOrderVo {
     @ApiModelProperty(value = "修改人ID")
     @TableField("updated_user_id")
     private Integer updatedUserId;
+
+    @ApiModelProperty(value = "用户GMV")
+    @TableField("orderGmv")
+    private Integer orderGmv;
 }

+ 3 - 1
alien-entity/src/main/java/shop/alien/entity/store/vo/ManagementInfoVo.java

@@ -83,7 +83,7 @@ public class ManagementInfoVo {
     private Integer orderTransactionNumber;
     @ApiModelProperty(value = "详情-核验金额")
     private Double verificationAmount;
-    @ApiModelProperty(value = "提现申请-申请类型")
+    @ApiModelProperty(value = "提现申请-申请类型0:手动, 1:自动")
     private Integer cashOutType;
     @ApiModelProperty(value = "提现申请-申请类型名称")
     private String cashOutTypeName;
@@ -147,4 +147,6 @@ public class ManagementInfoVo {
     private Date payTime;
     @ApiModelProperty(value = "订单id")
     private Integer orderId;
+    @ApiModelProperty(value = "拒绝原因")
+    private String approveFailReason;
 }

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

@@ -25,7 +25,7 @@ public class StoreCommentAppealVo extends StoreCommentAppeal {
     @ApiModelProperty(value = "评论图片链接")
     private List<String> commentImgList;
 
-    @ApiModelProperty(value = "商家申诉图片id")
+    @ApiModelProperty(value = "评论图片id")
     private String commentImgId;
 
     @ApiModelProperty(value = "申诉状态字符串")

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

@@ -57,5 +57,9 @@ public class StoreCommentVo extends StoreComment {
     @ApiModelProperty(value = "标签")
     private List<String> labels;
 
+    @ApiModelProperty(value = "商家or用户(0商家/1用户)")
+    private Integer storeUserFlag;
 
+    private String storeUserName;
+    private String storeUserImg;
 }

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

@@ -174,6 +174,7 @@ public class StoreInfoVo extends StoreInfo {
     private Integer totalDynamicsNum;
 
     private StoreBusinessInfo storeBusinessInfo;
+    private List<StoreBusinessInfo> storeBusinessInfos;
 
     @ApiModelProperty(value = "是否营业中(0否1是)")
     private Integer yyFlag;

+ 20 - 0
alien-entity/src/main/java/shop/alien/mapper/ExpertImgMapper.java

@@ -0,0 +1,20 @@
+package shop.alien.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import shop.alien.entity.store.ExpertImg;
+
+
+
+/**
+ * <p>
+ * 用户达人表 Mapper 接口
+ * </p>
+ *
+ * @author ssk
+ * @since 2025-02-19
+ */
+public interface ExpertImgMapper extends BaseMapper<ExpertImg> {
+
+
+}

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

@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.core.toolkit.Constants;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
 import shop.alien.entity.store.LifeCoupon;
 import shop.alien.entity.store.vo.LifeCouponVo;
 
@@ -64,4 +65,19 @@ public interface LifeCouponMapper extends BaseMapper<LifeCoupon> {
 
     @Select("SELECT * FROM life_coupon ${ew.customSqlSegment}")
     List<LifeCoupon> getList(@Param(Constants.WRAPPER) LambdaQueryWrapper<LifeCoupon> lambdaQueryWrapper);
+
+    @Update(" UPDATE life_coupon\n" +
+            "    SET \n" +
+            "        single_qty = single_qty - #{buyCount},\n" +
+            "        status = CASE WHEN (single_qty - #{buyCount}) = 0 \n" +
+            "                     THEN #{soldOutStatus} \n" +
+            "                     ELSE status END\n" +
+            "    WHERE \n" +
+            "        id = #{couponId} \n" +
+            "        AND single_qty >= #{buyCount}")
+    int deductInventoryAtomically(
+            @Param("couponId") Integer couponId,
+            @Param("buyCount") int buyCount,
+            @Param("soldOutStatus") int soldOutStatus
+    );
 }

+ 20 - 2
alien-entity/src/main/java/shop/alien/mapper/LifeGroupBuyMainMapper.java

@@ -1,14 +1,14 @@
 package shop.alien.mapper;
 
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Constants;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
 import shop.alien.entity.store.LifeGroupBuyMain;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import shop.alien.entity.store.vo.LifeGroupBuyThaliVo;
 
 /**
@@ -28,6 +28,24 @@ public interface LifeGroupBuyMainMapper extends BaseMapper<LifeGroupBuyMain> {
             "        coupon_id,delete_flag,created_time,updated_time,created_user_id,\n" +
             "        updated_user_id from life_group_buy_main ${ew.customSqlSegment}")
     IPage<LifeGroupBuyThaliVo> selectPageByThaliVo(IPage<LifeGroupBuyThaliVo> lifeGroupBuyThaliVoIPage,@Param(Constants.WRAPPER) QueryWrapper<LifeGroupBuyThaliVo> queryWrapper);
+
+
+    @Update("UPDATE life_group_buy_main\n" +
+            "SET \n" +
+            "  status = CASE \n" +
+            "    WHEN (inventory_num - #{buyCount}) = 0 THEN #{soldOutStatus}  \n" +
+            "    ELSE status \n" +
+            "  END,\n" +
+            "  inventory_num = inventory_num - #{buyCount}\n" +
+            "WHERE \n" +
+            "   id = #{couponId}\n" +
+            "\t AND inventory_num >= #{buyCount}"
+    )
+    int deductInventoryAtomically(
+            @Param("couponId") Integer couponId,
+            @Param("buyCount") int buyCount,
+            @Param("soldOutStatus") int soldOutStatus
+    );
 }
 
 

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

@@ -43,15 +43,47 @@ public interface LifeUserDynamicsMapper extends BaseMapper<LifeUserDynamics> {
             "${ew.customSqlSegment}")
     List<LifeUserDynamicsVo> getStoreDynamicslist(@Param("userId") String userId, @Param(Constants.WRAPPER) QueryWrapper<LifeUserDynamics> dynamicsWrapper);
 
-    @Select("select lud.*,'1' isLike\n" +
-            "from life_user_dynamics lud \n" +
-            "where lud.delete_flag = 0 \n" +
-            "and lud.id in (select llr.huifu_id from life_like_record llr where llr.dianzan_id = #{phoneId} and llr.delete_flag = 0) \n"+
-            "and lud.phone_id not in (select lb.blocked_phone_id  from life_blacklist lb where lb.blocker_phone_id = #{phoneId} and lb.delete_flag = 0)")
+    @Select("with middle_lud as (\n" +
+            "  select distinct  \n" +
+            "    lud.*,\n" +
+            "    '1' as isLike  \n" +
+            "  from life_user_dynamics lud\n" +
+            "  inner join (\n" +
+            "    select distinct huifu_id  \n" +
+            "    from life_like_record llr\n" +
+            "    where llr.dianzan_id = #{phoneId}\n" +
+            "      and llr.delete_flag = 0\n" +
+            "  ) llr_sub on lud.id = llr_sub.huifu_id\n" +
+            "  where lud.delete_flag = 0\n" +
+            "    and not exists (  -- 替代NOT IN,避免NULL问题\n" +
+            "      select 1 from life_blacklist lb\n" +
+            "      where lb.blocker_phone_id = #{phoneId}\n" +
+            "        and lb.delete_flag = 0\n" +
+            "        and lb.blocked_phone_id = lud.phone_id\n" +
+            "    )\n" +
+            ")\n" +
+            "select middle_lud.*,\n" +
+            "  CASE \n" +
+            "    WHEN lf.id is not null THEN 1\n" +
+            "    ELSE 0                        \n" +
+            "  END AS isFollowThis,  \n" +
+            "  CASE \n" +
+            "    WHEN lf1.id is not null THEN 1\n" +
+            "    ELSE 0                        \n" +
+            "  END AS isFollowMe  \n" +
+            "from middle_lud\n" +
+            "left join life_fans lf on lf.fans_id = #{phoneId} \n" +
+            "                      and lf.followed_id = middle_lud.phone_id\n" +
+            "                      and lf.delete_flag = '0'" +
+            "left join life_fans lf1 on lf1.fans_id = middle_lud.phone_id \n" +
+            "                      and lf1.followed_id = #{phoneId}\n" +
+            "                      and lf1.delete_flag = '0'")
     List<LifeUserDynamicsVo> selectDianZanList(String phoneId);
 
     List<LifeUserDynamicsVo> getDynamicsList(@Param("nickName") String nickName, @Param("userType") String userType, @Param("dynamicsType") Integer dynamicsType, @Param("releaseStartTime") String releaseStartTime, @Param("releaseEndTime") String releaseEndTime);
 
     List<LifeUserDynamicsVo> getDynamicsDetail(@Param("id") Integer id);
 
+    List<LifeUserDynamicsVo> getExpertDynamicsDetail(@Param("id") Integer id);
+
 }

+ 23 - 4
alien-entity/src/main/java/shop/alien/mapper/LifeUserExpertMapper.java

@@ -42,7 +42,7 @@ public interface LifeUserExpertMapper extends BaseMapper<LifeUserExpert> {
             "    where delete_flag = 0 " +
             "    group by expert_id " +
             ") " +
-            "select expert.id, expert.expert_code, user.user_name, ifnull(fans.num, 0) fansNum, ifnull(works.worksNum, 0) worksNum, ifnull(works.likeNum, 0) likeNum, ifnull(works.playNum, 0) playNum, " +
+            "select expert.id, expert.expert_code,expert.expert_status, user.user_phone,user.user_name, ifnull(fans.num, 0) fansNum, ifnull(works.worksNum, 0) worksNum, ifnull(works.likeNum, 0) likeNum, ifnull(works.playNum, 0) playNum, " +
             "       ifnull(orders.orderMoney, 0) orderMoney, ifnull(orders.accountMoney, 0) accountMoney, (ifnull(orders.orderMoney, 0) - ifnull(orders.accountMoney, 0)) pendMoney " +
             "from life_user_expert expert " +
             "join life_user user on user.id = expert.user_id " +
@@ -155,8 +155,8 @@ public interface LifeUserExpertMapper extends BaseMapper<LifeUserExpert> {
     List<LifeUserExpertVo> getFanPortrait(Integer expertId);
 
     @Select("select expert.id, expert.expert_code, " +
-            "expert.delete_flag, expert.created_time, expert.created_user_id, expert.updated_time, expert.updated_user_id," +
-            "user.user_name, user.province, user.city, user.district, user.user_brithday, user.user_sex " +
+            "expert.delete_flag, expert.created_time, expert.expert_status,expert.created_user_id, expert.updated_time, expert.updated_user_id,expert.commission_rate,expert.advance_rate," +
+            "user_name, user.province, user.city, user.district, user.user_brithday, user.user_sex " +
             " from life_user_expert expert " +
             " left join life_user user on user.id = expert.user_id " +
             " left join life_fans fans on fans.followed_id = concat('user_', user.user_phone)  " +
@@ -190,7 +190,26 @@ public interface LifeUserExpertMapper extends BaseMapper<LifeUserExpert> {
     @Select("select * from life_user_expert where user_id = #{userId} and delete_flag = 1")
     LifeUserExpert selectIsExpert(Integer userId);
 
-    @Update("update life_user_expert set expert_type = #{expertType},delete_flag = '0'" +
+    @Select("select * from life_user_expert where id = #{id} ")
+    LifeUserExpert selectIsExpertById(Integer id);
+
+    @Update("update life_user_expert set expert_code = #{expertCode},expert_status = #{expertStatus},delete_flag = '0',review_time =#{reviewTime} ,commission_rate =#{commissionRate},refuse_because=#{refuseBecause},advance_rate=#{advanceRate} " +
             "where id = #{id}")
     Boolean updateExpert(LifeUserExpert lifeUserExpert);
+
+    @Select(
+            "select   expert.*,user.* "+
+                    "from life_user_expert expert " +
+                    "join life_user user on user.id = expert.user_id " +
+                    "${ew.customSqlSegment}")
+    List<LifeUserExpertVo> getApplicationExpertList(@Param(Constants.WRAPPER) QueryWrapper<LifeUserExpertVo> wrapper);
+
+
+    @Select(
+            "select   expert.* ,user.* "+
+                    "from life_user_expert expert " +
+                    "join life_user user on user.id = expert.user_id " +
+                    "where expert.user_id=#{userId}")
+    LifeUserExpertVo getViewDetails(Integer userId);
+
 }

+ 45 - 2
alien-entity/src/main/java/shop/alien/mapper/LifeUserExpertOrderMapper.java

@@ -6,9 +6,12 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Constants;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
 import shop.alien.entity.store.LifeUserExpertOrder;
 import shop.alien.entity.store.vo.LifeUserExpertOrderVo;
+import shop.alien.entity.store.vo.LifeUserExpertVo;
 
+import java.util.Date;
 import java.util.List;
 
 /**
@@ -45,10 +48,11 @@ public interface LifeUserExpertOrderMapper extends BaseMapper<LifeUserExpertOrde
     List<LifeUserExpertOrderVo> getExpertOrderDetails(@Param("expertId") Long expertId);
 
 
-    @Select("select orders.id, orders.order_no, store.store_name, orders.order_money, orders.account_money, if (orders.status = '1', '待完成', '已完成') statusName, " +
+    @Select("select orders.id, orders.order_no, store.store_name, orders.order_money, package.name,orders.account_money,orders.end_funds_button, if (orders.status = '1', '待完成', '已完成') statusName, " +
             "       orders.order_time, orders.complete_time  " +
             "from life_user_expert_order orders " +
             "left join store_info store on store.id = orders.store_id " +
+            "left join life_promotion_package package on package.id = orders.package_id " +
             "WHERE orders.expert_id = #{expertId}")
     List<LifeUserExpertOrderVo> getPromotionOrderInfoList(@Param("expertId") Long expertId);
 
@@ -57,11 +61,12 @@ public interface LifeUserExpertOrderMapper extends BaseMapper<LifeUserExpertOrde
             "earliest_works AS (SELECT order_id, MIN(created_time) AS earliest_created_time FROM life_user_expert_works GROUP BY order_id), " +
             "purchase AS (SELECT order_id, SUM(CASE WHEN STATUS = 1 THEN 1 ELSE 0 END) completedOrdersNumber, SUM(purchase_amount) amount FROM life_user_expert_purchase WHERE delete_flag = 0 GROUP BY order_id), " +
             "record AS (SELECT order_id, COUNT(order_id) storeVisitViewCount FROM life_browse_record WHERE delete_flag = 0 GROUP BY order_id) " +
-            "SELECT orders.id, orders.order_no, store.store_name, orders.order_money, ew.earliest_created_time, orders.account_money, IF(orders.STATUS = '1', '待完成', '已完成') AS statusName, " +
+            "SELECT orders.id, orders.order_no, store.store_name, orders.order_money, orders.first_funds_button,orders.end_funds_button,package.name,ew.earliest_created_time, orders.account_money, IF(orders.STATUS = '1', '待完成', '已完成') AS statusName, " +
             "orders.order_time, orders.first_payment_time, orders.final_payment_time, orders.complete_time, orders.order_play_count, orders.order_gmv, " +
             "IFNULL(works.playCount, 0) AS actualPlayCount, IFNULL(purchase.amount, 0) AS actualGmv, IFNULL(purchase.completedOrdersNumber, 0) AS completedOrdersNumber, " +
             "IFNULL(purchase.amount, 0) AS transactionAmount, IFNULL(record.storeVisitViewCount, 0) AS storeVisitViewCount, ew.earliest_created_time AS firstWorkTime " +
             "FROM life_user_expert_order orders " +
+            "left join life_promotion_package package on package.id = orders.package_id " +
             "LEFT JOIN store_info store ON store.id = orders.store_id " +
             "LEFT JOIN works ON works.order_id = orders.id " +
             "LEFT JOIN purchase ON purchase.order_id = orders.id " +
@@ -82,4 +87,42 @@ public interface LifeUserExpertOrderMapper extends BaseMapper<LifeUserExpertOrde
             "FROM life_user_expert_order " +
             "WHERE order_id = #{orderId}")
     LifeUserExpertOrderVo selectByOrderId(Integer orderId);
+
+    //增加一个updateButton的方法,通过订单id来更新按钮状态
+//    @Update("UPDATE " +
+//            "life_user_expert_order " +
+//            "SET update_button = #{updateButton} " +
+//            "WHERE order_id = #{orderId}")
+//    Integer updateButton(@Param("orderId") String orderId, @Param("updateButton") String updateButton);
+
+
+    @Update("UPDATE " +
+            "life_user_expert_order " +
+            "SET end_funds_time = #{date}, " +
+            "end_funds_button = #{endButton} " +
+            "WHERE order_no = #{orderNo}")
+    void updateButton(@Param("firstButton") Date date, @Param("endButton") String endButton, @Param("orderNo") String orderNo);
+
+
+
+    @Select("SELECT ccc.* ,info.store_name,info.store_tel,user.real_name,user.user_name,expert.promote_type,expert.advance_rate,expert.commission_rate,user.user_phone,user.id_card,package.name " +
+            "FROM life_user_expert_order ccc " +
+            "LEFT JOIN store_info info on info.id = ccc.store_id " +
+            "left join life_user_expert expert on expert.id = ccc.expert_id " +
+            "left join life_user user on user.id = expert.user_id " +
+            "left join life_promotion_package package on package.id = ccc.package_id " +
+            " ${ew.customSqlSegment}")
+
+    List<LifeUserExpertOrderVo> getAdvancePaymentList(@Param(Constants.WRAPPER) QueryWrapper<LifeUserExpertVo> wrapper);
+
+
+
+    @Select("SELECT ccc.* ,info.store_name,info.store_tel,user.real_name,user.user_name,expert.promote_type,expert.advance_rate,expert.commission_rate,user.user_phone,user.id_card,package.name " +
+            "FROM life_user_expert_order ccc " +
+            "LEFT JOIN store_info info on info.id = ccc.store_id " +
+            "left join life_user_expert expert on expert.id = ccc.expert_id " +
+            "left join life_user user on user.id = expert.user_id " +
+            "left join life_promotion_package package on package.id = ccc.package_id " +
+            " ${ew.customSqlSegment}")
+    List<LifeUserExpertOrderVo> getFinalPaymentList(@Param(Constants.WRAPPER) QueryWrapper<LifeUserExpertVo> wrapper);
 }

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

@@ -1,7 +1,6 @@
 package shop.alien.mapper;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Constants;
@@ -71,5 +70,5 @@ public interface LifeUserOrderMapper extends BaseMapper<LifeUserOrder> {
      * @param selectWrapper
      * @return
      */
-    List<LifeUserOrderVo> selectRefundList(LambdaUpdateWrapper<LifeUserOrder> selectWrapper);
+    List<LifeUserOrderVo> selectRefundList(@Param(Constants.WRAPPER) QueryWrapper<LifeUserOrder> selectWrapper);
 }

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

@@ -34,6 +34,8 @@ public interface ManagementInfoMapper {
 
     IPage<ManagementInfoVo> getApplicationForWithdrawal(IPage<ManagementInfoVo> iPage, @Param("storeId") Integer storeId, @Param("storeName") String storeName);
 
+    ManagementInfoVo getCashOutDetail( @Param("id") Integer id);
+
     IPage<ManagementInfoVo> getStoreOrderDetail(IPage<ManagementInfoVo> iPage, @Param("storeId") String storeId, @Param("orderNo") String orderNo, @Param("userId") String userId, @Param("userName") String userName);
 
     //获取平台净利润

+ 15 - 0
alien-entity/src/main/java/shop/alien/mapper/StoreAliPayErrorLogMapper.java

@@ -0,0 +1,15 @@
+package shop.alien.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import shop.alien.entity.store.StoreAliPayErrorLog;
+
+/**
+ * <p>
+ * 支付宝转账错误记录表 Mapper 接口
+ * </p>
+ *
+ * @author qxy
+ * @since 2025-10-27
+ */
+public interface StoreAliPayErrorLogMapper extends BaseMapper<StoreAliPayErrorLog> {
+}

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

@@ -26,7 +26,7 @@ public interface StoreCommentAppealMapper extends BaseMapper<StoreCommentAppeal>
      * @param queryWrapper 查询条件
      * @return IPage<StoreCommentAppealVo>
      */
-    @Select("select a.*, b.dict_detail appeal_status_str, c.comment_content, c.comment_star, c.score score, c.other_score,c.is_anonymous, d.user_name, d.user_image, e.store_name, f.phone store_phone, f.name store_contact, e.store_type " +
+    @Select("select a.*, b.dict_detail appeal_status_str, c.comment_content, c.comment_star, c.score score, c.other_score,c.is_anonymous,c.img_id commentImgId, d.user_name, d.user_image, e.store_name, f.phone store_phone, f.name store_contact, e.store_type " +
             "from store_comment_appeal a " +
             "left join store_dictionary b on a.appeal_status = b.dict_id and b.type_name = 'appealStatus' and b.delete_flag = 0 " +
             "left join store_comment c on a.comment_id = c.id " +

+ 40 - 0
alien-entity/src/main/java/shop/alien/mapper/StoreCommentSummaryInterestMapper.java

@@ -0,0 +1,40 @@
+package shop.alien.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Insert;
+import org.apache.ibatis.annotations.Mapper;
+import shop.alien.entity.store.StoreCommentSummaryInterest;
+
+import java.util.List;
+
+/**
+ * qxy
+ * AI 服务 店铺趣味信息
+ */
+@Mapper
+public interface StoreCommentSummaryInterestMapper extends BaseMapper<StoreCommentSummaryInterest> {
+    @Insert({
+            "<script>", // 开启动态 SQL 脚本
+            "INSERT INTO store_comment_summary_interest (",
+            "  id, store_id, store_name, summary, task_id, delete_flag, created_time, created_user_id,",
+            "  updated_time, updated_user_id",
+            ")",
+            "VALUES",
+            "<foreach collection='list' item='item' separator=','>",
+            "(",
+            "  #{item.id},",
+            "  #{item.storeId},",
+            "  #{item.storeName},",
+            "  #{item.summary},",
+            "  #{item.taskId},",
+            "  #{item.deleteFlag},",
+            "  #{item.createdTime},",
+            "  #{item.createdUserId},",
+            "  #{item.updatedTime},",
+            "  #{item.updatedUserId}",
+            ")",
+            "</foreach>",
+            "</script>" // 关闭动态 SQL 脚本
+    })
+    int insertBatchStoreCommentSummaryInterest(List<StoreCommentSummaryInterest> storeCommentSummaryInterests);
+}

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

@@ -53,6 +53,19 @@ public interface StoreInfoMapper extends BaseMapper<StoreInfo> {
             " ${ew.customSqlSegment}")
     List<StoreInfoVo> getStoreInfoVoList(@Param(Constants.WRAPPER) QueryWrapper<StoreInfoVo> queryWrapper);
 
+    @Select("with menu as (select store_id,GROUP_CONCAT(dish_name) dish_name from store_menu GROUP BY store_id) " +
+            "select a.*, b.name store_contact, b.phone store_phone, b.password, c.dish_name, a.store_type, img.img_url entranceImage, d.img_url, dict.dict_detail storeTypeStr, dict2.dict_detail businessStatusStr," +
+            "            ROUND(ST_Distance_Sphere(ST_GeomFromText(CONCAT('POINT(', REPLACE(#{position}, ',', ' '), ')' )), ST_GeomFromText(CONCAT('POINT(', REPLACE(a.store_position, ',', ' '), ')' ))) / 1000, 2) dist " +
+            "from store_info a " +
+            "left join store_user b on a.id = b.store_id  AND b.delete_flag = 0 " +
+            "left join menu c on a.id = c.store_id " +
+            "left join store_img img on img.store_id = a.id and img.img_type = 1 and img.delete_flag = 0 " +
+            "left join store_dictionary dict on dict.type_name = 'storeType' and dict.dict_id = a.store_type and dict.delete_flag = 0 " +
+            "left join store_dictionary dict2 on dict2.type_name = 'businessStatus' and a.business_status = dict2.dict_id and dict2.delete_flag = 0 " +
+            "left join store_img d on d.store_id = a.id and d.img_type = 10 and d.delete_flag = 0" +
+            " ${ew.customSqlSegment}")
+    List<StoreInfoVo> getStoreInfoVoListNew(@Param(Constants.WRAPPER) QueryWrapper<StoreInfoVo> queryWrapper,  @Param("position") String position);
+
     /**
      * web端-门店列表
      *

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

@@ -0,0 +1,9 @@
+package shop.alien.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import shop.alien.entity.store.StoreInfoUserMiddle;
+
+@Mapper
+public interface StoreInfoUserMiddleMapper extends BaseMapper<StoreInfoUserMiddle> {
+}

+ 10 - 0
alien-entity/src/main/java/shop/alien/mapper/second/SecondRiskControlRecordMapper.java

@@ -0,0 +1,10 @@
+package shop.alien.mapper.second;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import shop.alien.entity.second.SecondRiskControlRecord;
+
+/**
+ * 二手商品风控记录映射器
+ */
+public interface SecondRiskControlRecordMapper extends BaseMapper<SecondRiskControlRecord> {
+}

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

@@ -55,13 +55,13 @@ public interface SecondTradeRecordMapper extends BaseMapper<SecondTradeRecord> {
     SecondTradeRecordVo getTradeRecordById(@Param("id") Integer id);
 
     @Select("with record as ( " +
-            "    select buyer_id userId, count(1) num, 'buyer' flag " +
+            "    select buyer_id userId, count(1) num, 'buyer' flag, max(transaction_time) time " +
             "    from second_trade_record " +
             "    where delete_flag = 0 and trade_status = 4 and failure_flag = 0 " +
             "    and transaction_time >= #{beginTime} and transaction_time <= #{endTime} " +
             "    group by buyer_id " +
             "    union all " +
-            "    select seller_id userId, count(1) num, 'seller' flag " +
+            "    select seller_id userId, count(1) num, 'seller' flag, max(transaction_time) time " +
             "    from second_trade_record " +
             "    where delete_flag = 0 and trade_status = 4 and failure_flag = 0 " +
             "    and transaction_time >= #{beginTime} and transaction_time <= #{endTime} " +
@@ -69,14 +69,14 @@ public interface SecondTradeRecordMapper extends BaseMapper<SecondTradeRecord> {
             ") " +
             "select a.*, ifnull(b.num, 0) buyer, ifnull(c.num, 0) seller, user.user_name userName, concat('user_', user.user_phone) phoneId, user.user_phone userPhone " +
             "from ( " +
-            "    select userId, sum(num) num " +
+            "    select userId, sum(num) num, max(time) time " +
             "    from record " +
             "    group by userId " +
             ") a " +
             "left join record b on a.userId = b.userId and b.flag = 'buyer' " +
             "left join record c on a.userId = c.userId and c.flag = 'seller' " +
             "join life_user user on user.id = a.userId and user.delete_flag = 0 " +
-            "order by a.num desc " +
+            "order by a.num desc, a.time " +
             "limit 20 ")
     List<JSONObject> getRankingList(@Param("beginTime") String beginTime, @Param("endTime") String endTime);
 }

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

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

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

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

+ 27 - 0
alien-entity/src/main/resources/mapper/ExpertImgMapper.xml

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="shop.alien.mapper.ExpertImgMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="shop.alien.entity.store.ExpertImg">
+        <id column="id" property="id" />
+        <result column="expert_id" property="expertId" />
+        <result column="expert_code" property="expertCode" />
+        <result column="user_id" property="userId" />
+        <result column="delete_flag" property="deleteFlag" />
+        <result column="img_type" property="imgType" />
+        <result column="img_description" property="imgDescription" />
+        <result column="img_sort" property="imgSort" />
+        <result column="img_url" property="imgUrl" />
+        <result column="add_explanation" property="addExplanation" />
+        <result column="created_time" property="createdTime" />
+        <result column="updated_time" property="updatedTime" />
+
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, expert_id ,expert_code,user_id, delete_flag,img_type, img_description, img_sort, img_url,add_explanation,created_time, updated_time
+    </sql>
+
+</mapper>

+ 29 - 2
alien-entity/src/main/resources/mapper/LifeUserDynamicsMapper.xml

@@ -4,7 +4,7 @@
 
     <select id="getDynamicsList" resultType="shop.alien.entity.store.vo.LifeUserDynamicsVo">
         select dyna1.*, COUNT(dyna1.id) AS fansCount from (
-        select dyna.*,COUNT(lc.id) AS commentCount,  COUNT(lm.id) AS transferNum from (
+        select dyna.*,COUNT(sc.id) AS commentCount,  COUNT(lm.id) AS transferNum from (
         with dynamice as(
         select
         CASE
@@ -28,6 +28,7 @@
         left join life_user_expert  lue on lue.user_id = user.id and lue.delete_flag = 0
         where dynamice.userType = 'user') dyna
         left join life_comment lc on lc.dongtai_shequ_id = dyna.id
+        left join store_comment sc on sc.business_id = dyna.id and sc.business_type = 2 and sc.delete_flag = 0
         left join life_message lm on lm.business_id = dyna.id
         GROUP BY dyna.id order by  dyna.created_time desc) dyna1
         left join life_fans lf1 on lf1.followed_id =  dyna1.phoneId
@@ -56,7 +57,7 @@
 
     <select id="getDynamicsDetail" resultType="shop.alien.entity.store.vo.LifeUserDynamicsVo">
         select dyna1.*, COUNT(dyna1.id) AS fansCount from (
-        select dyna.*,COUNT(lc.id) AS commentCount,  COUNT(lm.id) AS transferNum from (
+        select dyna.*,COUNT(sc.id) AS commentCount,  COUNT(lm.id) AS transferNum from (
         with dynamice as(
         select
         CASE
@@ -80,10 +81,36 @@
         left join life_user_expert  lue on lue.user_id = user.id and lue.delete_flag = 0
         where dynamice.userType = 'user') dyna
         left join life_comment lc on lc.dongtai_shequ_id = dyna.id
+        left join store_comment sc on sc.business_id = dyna.id and sc.business_type = 2 and sc.delete_flag = 0
         left join life_message lm on lm.business_id = dyna.id
         GROUP BY dyna.id order by  dyna.created_time desc) dyna1
         left join life_fans lf1 on lf1.followed_id =  dyna1.phoneId
         GROUP by dyna1.id order by dyna1.top_status desc, dyna1.top_time desc
     </select>
 
+    <select id="getExpertDynamicsDetail" resultType="shop.alien.entity.store.vo.LifeUserDynamicsVo">
+        SELECT
+        dy.*,
+        info.score_avg as scoreAvg,
+        info.store_name as storeName,
+        info.id as storeId,
+        info.business_section as businessSection,
+        COUNT(comment.id) AS commentCount
+        FROM
+        life_user_dynamics AS dy
+        INNER JOIN life_user_expert_order AS expertOrder
+        ON dy.business_id = expertOrder.id
+        AND expertOrder.delete_flag = 0
+        INNER JOIN store_info AS info
+        ON expertOrder.store_id = info.id
+        AND info.delete_flag = 0
+        LEFT JOIN store_comment AS comment
+        ON comment.store_id = info.id
+        AND comment.delete_flag = 0
+        AND comment.business_type in ( 5 )
+        WHERE
+        dy.id = #{id}
+        AND dy.delete_flag = 0
+    </select>
+
 </mapper>

+ 8 - 1
alien-entity/src/main/resources/mapper/LifeUserExpertMapper.xml

@@ -12,11 +12,18 @@
         <result column="created_user_id" property="createdUserId" />
         <result column="updated_time" property="updatedTime" />
         <result column="updated_user_id" property="updatedUserId" />
+        <result column="expert_status" property="expertStatus" />
+        <result column="add_explanation" property="addExplanation" />
+        <result column="refuse_because" property="refuseBecause" />
+        <result column="review_time" property="reviewTime" />
+        <result column="commission_rate" property="commissionRate" />
+        <result column="advance_rate" property="advanceRate" />
+        <result column="promote_type" property="promoteType" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, user_id, expert_code, delete_flag, created_time, created_user_id, updated_time, updated_user_id
+        id, user_id, expert_code, delete_flag, created_time, created_user_id, updated_time, updated_user_id,expert_status, add_explanation,refuse_because,review_time,commission_rate,advance_rate,promote_type
     </sql>
 
 </mapper>

+ 12 - 3
alien-entity/src/main/resources/mapper/LifeUserExpertOrderMapper.xml

@@ -5,9 +5,10 @@
     <!-- 通用查询映射结果 -->
     <resultMap id="BaseResultMap" type="shop.alien.entity.store.LifeUserExpertOrder">
         <id column="id" property="id" />
-        <result column="order_id" property="orderId" />
+        <result column="order_no" property="orderNo" />
         <result column="expert_id" property="expertId" />
         <result column="store_id" property="storeId" />
+        <result column="package_id" property="packageId" />
         <result column="order_money" property="orderMoney" />
         <result column="account_money" property="accountMoney" />
         <result column="order_time" property="orderTime" />
@@ -15,7 +16,7 @@
         <result column="first_payment_time" property="firstPaymentTime" />
         <result column="final_payment_time" property="finalPaymentTime" />
         <result column="order_play_count" property="orderPlayCount" />
-        <result column="actual_play_count" property="actualPlayCount" />
+<!--        <result column="actual_play_count" property="actualPlayCount" />-->
         <result column="order_gmv" property="orderGmv" />
         <result column="actual_gmv" property="actualGmv" />
         <result column="status" property="status" />
@@ -24,11 +25,19 @@
         <result column="created_user_id" property="createdUserId" />
         <result column="updated_time" property="updatedTime" />
         <result column="updated_user_id" property="updatedUserId" />
+        <result column="advance_payment_status" property="advancePaymentStatus" />
+        <result column="end_funds_button" property="endFundsButton" />
+        <result column="reason_refusal" property="reasonRefusal" />
+        <result column="advance_payment_time" property="advancePaymentTime" />
+        <result column="end_funds_time" property="endFundsTime" />
+        <result column="end_payment_time" property="endPaymentTime" />
+        <result column="end_payment_refusal" property="endPaymentRefusal" />
+
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, order_id, expert_id, store_id, order_money, account_money, order_time, complete_time, first_payment_time, final_payment_time, order_play_count, actual_play_count, order_gmv, actual_gmv, status, delete_flag, created_time, created_user_id, updated_time, updated_user_id
+        id, order_id, expert_id, package_id , store_id, order_money, account_money, order_time, complete_time, first_payment_time, final_payment_time, order_play_count, order_gmv, actual_gmv, status, delete_flag, created_time, created_user_id, updated_time, updated_user_id, advance_payment_status, end_funds_button ,reason_refusal,advancePaymentTime,endFundsTime,endPaymentTime,endPaymentRefusal
     </sql>
 
 </mapper>

+ 9 - 3
alien-entity/src/main/resources/mapper/LifeUserOrderMapper.xml

@@ -43,6 +43,8 @@
         <result column="total_refund_time" property="totalRefundTime"/>
         <result column="business_status" property="businessStatus"/>
         <result column="type" property="type"/>
+        <result column="store_type" property="storeType"/>
+        <result column="store_status" property="storeStatus"/>
 
         <result column="business_type" property="businessType"/>
         <result column="collect_num" property="collectNum"/>
@@ -61,6 +63,7 @@
             <result column="refund_time" property="refundTime"/>
             <result column="refund_reason" property="refundReason"/>
             <result column="refundPrice" property="price"/>
+            <result column="used_time" property="usedTime"/>
         </collection>
     </resultMap>
 
@@ -82,7 +85,7 @@
         ldc.nominal_value,ldc.type,
         lu.user_phone,lu.user_name,lu.id user_id,
         ocm.id ocmId,ocm.status,ocm.coupon_code,ocm.refund_time,ocm.refund_reason,ocm.price refundPrice,
-        si.id store_id,si.store_name,si.commission_rate,si.store_address,si.store_tel,si.business_status,si.collect_num,
+        si.id store_id,si.store_name,si.commission_rate,si.store_address,si.store_tel,si.business_status,si.collect_num,si.business_section store_type,si.store_status,
         <if test="position != null and position != ''">
             ROUND(
             ST_Distance_Sphere(
@@ -129,13 +132,16 @@
         from life_user_order luo
         left join store_info si on si.id = luo.store_id and si.delete_flag = 0
         left join order_coupon_middle ocm on ocm.order_id = luo.id and ocm.delete_flag = 0
-        left join total_coupon tc on tc.coupon_id = ocm.coupon_id and tc.coupon_type = luo.coupon_type
+        inner join total_coupon tc on tc.coupon_id = ocm.coupon_id and tc.coupon_type = luo.coupon_type
         left join life_discount_coupon_user ldcu on ldcu.id = luo.quan_id and ldcu.delete_flag = 0
         left join life_discount_coupon ldc on ldc.id = ldcu.coupon_id and ldc.delete_flag = 0
         left join life_user lu on lu.id = luo.user_id and lu.delete_flag = 0
         left join store_img simg on simg.id = tc.image_id and simg.delete_flag = 0
         left join store_business_info sbi on sbi.store_id = si.id and sbi.delete_flag = 0
-        where luo.status = 1
+        <where>
+            <!-- 引用 LambdaQueryWrapper 构建的条件 -->
+            ${ew.sqlSegment}
+        </where>
         order by luo.created_time desc
     </select>
 </mapper>

+ 33 - 2
alien-entity/src/main/resources/mapper/ManagementInfoMapper.xml

@@ -152,7 +152,7 @@
                 END AS type_name,
             coupon.`name`,
             "1" AS buy_count,
-            ROUND(userOrder.price / 100,2) AS buy_amount,
+            ROUND(userOrder.price ,2) AS buy_amount,
             userOrder.buy_time AS buy_time,
             userOrder.used_time AS used_time,
             userOrder.refund_time AS refund_time,
@@ -170,7 +170,8 @@
                 WHEN 4 THEN
                     "已退款"
                 END AS status_name,
-        userOrder.order_no
+        userOrder.order_no,
+        userOrder.coupon_type
         FROM
             life_user_order userOrder
                 LEFT JOIN life_coupon coupon ON coupon.id = userOrder.id
@@ -253,6 +254,36 @@
             AND store.store_name LIKE CONCAT('%', #{storeName}, '%')
         </if>
     </select>
+
+    <select id="getCashOutDetail" resultType="shop.alien.entity.store.vo.ManagementInfoVo">
+        SELECT
+        cash.id AS cash_id,
+        store.store_name AS store_name ,
+        storeUser.phone AS store_phone ,
+        store.id AS store_id,
+        cash.cash_out_type,
+        CASE
+        cash.cash_out_type
+        WHEN 0 THEN
+        "手动提现"
+        WHEN 1 THEN
+        "到期自动提现"
+        END AS cash_out_type_name,
+        ROUND(IFNULL(cash.money, 0) / 100,2) AS money,
+        cash.created_time,
+        cash.payment_date,
+        cash.approve_time,
+        cash.pay_date,
+        cash.fail_reason,
+        cash.payment_status,
+        cash.approve_fail_reason
+        FROM
+        store_cash_out_record cash
+        LEFT JOIN store_info store ON cash.store_id = store.id
+        LEFT JOIN store_user storeUser ON storeUser.store_id = store.id
+        WHERE cash.id = #{id}
+    </select>
+
     <select id="getPlatformNetProfit" resultType="shop.alien.entity.store.vo.ManagementInfoVo">
         select IFNULL(ROUND(sum(all_data.platform_profit),2), 0) AS profit from
         (SELECT

+ 5 - 0
alien-gateway/pom.xml

@@ -180,6 +180,11 @@
         </dependency>
 
         <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+        </dependency>
+
+        <dependency>
             <groupId>javax.xml.bind</groupId>
             <artifactId>jaxb-api</artifactId>
         </dependency>

+ 2 - 0
alien-gateway/src/main/java/shop/alien/gateway/AlienGatewayApplication.java

@@ -3,6 +3,7 @@ package shop.alien.gateway;
 import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.openfeign.EnableFeignClients;
 import org.springframework.context.annotation.ComponentScan;
 
 /**
@@ -14,6 +15,7 @@ import org.springframework.context.annotation.ComponentScan;
  */
 @ComponentScan({"shop.alien.gateway.*"})
 @MapperScan({"shop.alien.gateway.mapper"})
+@EnableFeignClients(basePackages = "shop.alien.gateway.feign")
 @SpringBootApplication
 public class AlienGatewayApplication {
 

+ 4 - 3
alien-gateway/src/main/java/shop/alien/gateway/controller/LifeUserController.java

@@ -25,9 +25,10 @@ public class LifeUserController {
     @ApiOperationSupport(order = 1)
     @ApiImplicitParams({@ApiImplicitParam(name = "phoneNum", value = "手机号", dataType = "String", paramType = "query", required = true)})
     @GetMapping("/userLogin")
-    public R<LifeUserVo> userLogin(@RequestParam("phoneNum") String phoneNum) {
-        log.info("LifeUserController.userLogin?phoneNum={}", phoneNum);
-        LifeUserVo userVo = service.userLogin(phoneNum);
+    public R<LifeUserVo> userLogin(@RequestParam("phoneNum") String phoneNum,
+                                    @RequestParam(value = "macIp",required = false) String macIp) {
+        log.info("LifeUserController.userLogin?phoneNum={},macIp={}", phoneNum, macIp);
+        LifeUserVo userVo = service.userLogin(phoneNum, macIp);
         if (null == userVo) {
             return R.fail("登录失败");
         }

+ 36 - 0
alien-gateway/src/main/java/shop/alien/gateway/feign/SecondServiceFeign.java

@@ -0,0 +1,36 @@
+package shop.alien.gateway.feign;
+
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@FeignClient(name = "alien-second", url = "${feign.alienSecond.url}")
+public interface SecondServiceFeign {
+    
+    /**
+     * 记录风控数据
+     *
+     * @param userId     用户ID
+     * @param ruleType   规则类型 1:洗钱嫌疑 2:账号异常 3:交易欺诈 4:异常发布
+     * @param ruleName   规则名称
+     * @param businessId 业务ID
+     * @param detailInfo 详细信息(JSON格式)
+     */
+    @PostMapping("/riskControl/record")
+    void recordRiskControlData(@RequestParam("userId") Integer userId,
+                               @RequestParam("ruleType") Integer ruleType,
+                               @RequestParam("ruleName") String ruleName,
+                               @RequestParam("businessId") String businessId,
+                               @RequestParam("detailInfo") String detailInfo);
+
+    /**
+     * 用户积分数据
+     *
+     * @param userId     用户ID
+     * @param initialPoints   用户积分
+     */
+    @PostMapping("/userPoints/create")
+    void createPointsRecord(@RequestParam("userId") Integer userId,
+                            @RequestParam("initialPoints") Integer initialPoints,
+                            @RequestParam("pointsType") Integer pointsType);
+}

+ 27 - 0
alien-gateway/src/main/java/shop/alien/gateway/mapper/LifeUserLogMapper.java

@@ -0,0 +1,27 @@
+package shop.alien.gateway.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import shop.alien.entity.second.LifeUserLog;
+
+import java.util.List;
+
+@Mapper
+public interface LifeUserLogMapper extends BaseMapper<LifeUserLog> {
+
+    /**
+     * 查询时间段内同一个macip地址的登录记录
+     *
+     * @param starDate 开始日期
+     * @param endDate 结束日期
+     * @return 同一个macip地址的登录记录
+     */
+    @Select("SELECT user_id, user_name, mac_ip FROM life_user_log " +
+            " WHERE created_time BETWEEN DATE_FORMAT(#{starDate}, '%Y-%m-%d %H:%i:%s') " +
+            " AND DATE_FORMAT(#{endDate}, '%Y-%m-%d %H:%i:%s') AND mac_ip = #{macIp} " +
+            " GROUP BY user_id, user_name, mac_ip ")
+    List<LifeUserLog> getLifeUserLogByDate(@Param("starDate") String starDate, @Param("endDate") String endDate, @Param("macIp") String macIp);
+
+}

+ 51 - 1
alien-gateway/src/main/java/shop/alien/gateway/service/LifeUserService.java

@@ -7,15 +7,22 @@ import lombok.RequiredArgsConstructor;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
+import shop.alien.entity.second.LifeUserLog;
 import shop.alien.entity.store.LifeUser;
 import shop.alien.entity.store.vo.LifeUserVo;
 import shop.alien.gateway.config.BaseRedisService;
+import shop.alien.gateway.feign.SecondServiceFeign;
+import shop.alien.gateway.mapper.LifeUserLogMapper;
 import shop.alien.gateway.mapper.LifeUserMapper;
 import shop.alien.util.common.JwtUtil;
 
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * 用户
@@ -26,12 +33,19 @@ public class LifeUserService extends ServiceImpl<LifeUserMapper, LifeUser> {
 
     private final LifeUserMapper lifeUserMapper;
 
+    private final LifeUserLogMapper lifeUserLogMapper;
+
     private final BaseRedisService baseRedisService;
 
+    private final SecondServiceFeign secondServiceFeign;
+
+    @Value("${risk-control.account-abnormal.reg-count24h:4}")
+    private Integer regCount24h;
+
     @Value("${jwt.expiration-time}")
     private String effectiveTime;
 
-    public LifeUserVo userLogin(String phoneNum) {
+    public LifeUserVo userLogin(String phoneNum, String macIp) {
         int effectiveTimeInt = Integer.parseInt(effectiveTime.substring(0, effectiveTime.length() - 1));
         String effectiveTimeUnit = effectiveTime.substring(effectiveTime.length() - 1);
         long effectiveTimeIntLong = 0L;
@@ -74,6 +88,8 @@ public class LifeUserService extends ServiceImpl<LifeUserMapper, LifeUser> {
                 userVo.setToken(JwtUtil.createJWT("user_" + phoneNum, lifeUser.getUserName(), JSONObject.toJSONString(tokenMap), effectiveTimeIntLong));
 //                userVo.setToken(JWTUtils.createToken(tokenMap));
                 baseRedisService.setString("user_" + phoneNum, userVo.getToken());
+                // 二手平台登录log,同一个macip登录多账号记录
+                addLifeUserLogInfo(user2, macIp);
                 return userVo;
             } else {
                 return null;
@@ -90,6 +106,8 @@ public class LifeUserService extends ServiceImpl<LifeUserMapper, LifeUser> {
             String token = JwtUtil.createJWT("user_" + phoneNum, user.getUserName(), JSONObject.toJSONString(tokenMap), effectiveTimeIntLong);
             userVo.setToken(token);
             baseRedisService.setString("user_" + phoneNum, token);
+            // 二手平台登录log,同一个macip登录多账号记录
+            addLifeUserLogInfo(user, macIp);
             return userVo;
         }
     }
@@ -100,4 +118,36 @@ public class LifeUserService extends ServiceImpl<LifeUserMapper, LifeUser> {
         return this.getOne(lambdaQueryWrapper);
     }
 
+
+    /**
+     * 用户登录log存放(加入mac地址)
+     */
+    public void addLifeUserLogInfo(LifeUser user, String macIp) {
+        try {
+            LifeUserLog lifeUserLog = new LifeUserLog();
+            lifeUserLog.setUserId(user.getId());
+            lifeUserLog.setUserName(user.getUserName());
+            lifeUserLog.setMacIp(macIp);
+            lifeUserLog.setCreatedTime(new Date());
+            lifeUserLogMapper.insert(lifeUserLog);
+
+            String startDate = LocalDateTime.now().minusHours(24L).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+            String endDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+            List<LifeUserLog> lsit = lifeUserLogMapper.getLifeUserLogByDate(startDate, endDate, macIp);
+
+            secondServiceFeign.recordRiskControlData(1, 2, "账号异常","1", "测试");
+
+            if (lsit.size() > regCount24h) {
+                String detailInfo = lsit.stream()
+                        .map(row -> row.getUserId().toString())
+                        .collect(Collectors.joining(","));
+                secondServiceFeign.recordRiskControlData(null, 2, "账号异常", "1", detailInfo);
+            }
+
+            secondServiceFeign.createPointsRecord(user.getId(), 300, 1);
+        } catch (Exception e) {
+            log.error("用户登录log存放异常:{}");
+        }
+
+    }
 }

+ 22 - 0
alien-gateway/src/main/resources/bootstrap-uat.yml

@@ -0,0 +1,22 @@
+spring:
+  application:
+    name: alien-gateway
+
+  cloud:
+    nacos:
+      #注册中心
+      discovery:
+        server-addr: localhost:8848
+        username: nacos
+        password: ngfriend198092
+        namespace: 79060c39-10ad-4098-9022-5e8a47796f8f
+
+      #配置中心
+      config:
+        enabled: true
+        server-addr: localhost:8848
+        username: nacos
+        password: ngfriend198092
+        group: DEFAULT_GROUP
+        file-extension: yml
+        namespace: 79060c39-10ad-4098-9022-5e8a47796f8f

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

@@ -50,7 +50,7 @@ public interface AlienStoreFeign {
      * @param refundReason 退款原因
      * @return
      */
-    @GetMapping("/processRefund")
+    @GetMapping("ali/processRefund")
     public String processRefund(@RequestParam(value = "outTradeNo") String outTradeNo,
                                    @RequestParam(value = "refundAmount") String refundAmount,
                                    @RequestParam(value = "refundReason") String refundReason,

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

@@ -15,8 +15,10 @@ import org.springframework.util.MultiValueMap;
 import org.springframework.web.client.RestTemplate;
 import shop.alien.entity.result.R;
 import shop.alien.entity.store.StoreCommentSummary;
+import shop.alien.entity.store.StoreCommentSummaryInterest;
 import shop.alien.entity.store.TagsMain;
 import shop.alien.entity.store.TagsSynonym;
+import shop.alien.mapper.StoreCommentSummaryInterestMapper;
 import shop.alien.mapper.StoreCommentSummaryMapper;
 import shop.alien.mapper.TagsMainMapper;
 import shop.alien.mapper.TagsSynonymMapper;
@@ -45,6 +47,8 @@ public class AiTagJob {
 
     private final StoreCommentSummaryMapper storeCommentSummaryMapper;
 
+    private final StoreCommentSummaryInterestMapper storeCommentSummaryInterestMapper;
+
     // 第三方接口地址 获取所有标签主表信息
     @Value("${third-party-tag.base-url}")
     private String tagMainUrl;
@@ -57,6 +61,10 @@ public class AiTagJob {
     @Value("${third-party-summary.base-url}")
     private String allSummaryUrl;
 
+    // 第三方接口地址 获取店铺趣味信息
+    @Value("${third-party-interest.base-url}")
+    private String allInterestUrl;
+
     // 第三方接口地址 登录接口URL
     @Value("${third-party-login.base-url}")
     private String loginUrl;
@@ -461,6 +469,104 @@ public class AiTagJob {
         return R.success("任务执行失败 状态码" + responseEntity.getStatusCodeValue());
     }
 
+    /**
+     * 拉取Ai服务获取趣味推荐信息表数据
+     */
+    @XxlJob("getStoreCommentSummaryInterestTask")
+    public R<String> getStoreCommentSummaryInterestTask() {
+        log.info("登录Ai服务获取token..." + loginUrl);
+        //构建请求参数
+        MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
+        formData.add("username", userName);    // 表单字段 1:用户名
+        formData.add("password", passWord);    // 表单字段 2:密码
+
+        //设置请求头
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers);
+        ResponseEntity<String> postForEntity = null;
+        try {
+            postForEntity = restTemplate.postForEntity(loginUrl, requestEntity, String.class);
+        } catch (Exception e) {
+            log.error("类:PostMethod 方法:post", e);
+        }
+
+        if (postForEntity != null) {
+            if (postForEntity.getStatusCodeValue() == 200) {
+                log.info("请求Ai服务登录成功 postForEntity.getBody()\t" + postForEntity.getBody());
+                String responseBody = postForEntity.getBody();
+                JSONObject jsonObject = JSONObject.parseObject(responseBody);
+                JSONObject dataJson = jsonObject.getJSONObject("data");
+                String accessToken = dataJson.getString("access_token");
+                //调用 获取AI服务 获取趣味推荐信息表 get请求
+                getStoreCommentSummaryInterestInfo(accessToken);
+                return R.success("任务执行成功");
+            } else {
+                log.error("请求AI服务 登录接口失败 http状态:" + postForEntity.getStatusCode());
+                return R.fail("请求AI服务 登录接口失败 http状态:" + postForEntity.getStatusCode());
+            }
+        }
+        XxlJobHelper.handleFail("登录任务执行失败 返回异常");
+        return R.fail("登录任务执行失败 返回异常");
+    }
+
+    public R<String> getStoreCommentSummaryInterestInfo(String token) {
+        log.info("开始从Ai服务获取数据 获取趣味推荐信息表...");
+        log.info("restTemplate:" + restTemplate + "url:" + allInterestUrl);
+        // 1. 构建请求头
+        HttpHeaders headers = new HttpHeaders();
+        headers.set("Authorization", "Bearer " + token); // Token 认证
+        headers.set("accept", "*/*");
+        headers.set("connection", "Keep-Alive");
+        headers.set("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+        // 2. 构建请求实体(仅包含头信息,GET 请求通常无请求体)
+        HttpEntity<?> requestEntity = new HttpEntity<>(headers);
+
+        // 发送 GET 请求,响应体为 String 类型
+        ResponseEntity<String> responseEntity = restTemplate.exchange(
+                allInterestUrl,
+                HttpMethod.GET,  // 指定请求方法为 GET
+                requestEntity,
+                String.class     // 响应体类型
+        );
+
+        // 解析响应
+        if (responseEntity.getStatusCodeValue() == 200) {
+            String responseBody = responseEntity.getBody();
+            JSONObject jsonObject = JSONObject.parseObject(responseBody);
+            Integer code = jsonObject.getInteger("code");
+            String message = jsonObject.getString("message");
+            JSONArray dataArray = jsonObject.getJSONArray("data");
+            List<StoreCommentSummaryInterest> storeCommentSummaryInterests = new ArrayList<>();
+            for (int i = 0; i < dataArray.size(); i++) {
+                JSONObject tagObj = dataArray.getJSONObject(i);
+                StoreCommentSummaryInterest summary = new StoreCommentSummaryInterest();
+                summary.setId(tagObj.getInteger("id"));
+                summary.setStoreId(tagObj.getInteger("store_id"));
+                summary.setStoreName(tagObj.getString("store_name"));
+                summary.setSummary(tagObj.getString("summary"));
+                summary.setTaskId(tagObj.getString("task_id"));
+                summary.setDeleteFlag(tagObj.getInteger("delete_flag"));
+                summary.setCreatedTime(tagObj.getDate("created_time"));
+                summary.setCreatedUserId(tagObj.getInteger("created_user_id"));
+                summary.setUpdatedTime(tagObj.getDate("updated_time"));
+                summary.setUpdatedUserId(tagObj.getInteger("updated_user_id"));
+                storeCommentSummaryInterests.add(summary);
+            }
+            if (!CollectionUtils.isEmpty(storeCommentSummaryInterests)) {
+                int num = storeCommentSummaryInterestMapper.insertBatchStoreCommentSummaryInterest(storeCommentSummaryInterests);
+                XxlJobHelper.handleSuccess("拉取子标签数据成功 执行" + num + "条");
+                return R.success("拉取子标签数据成功 执行" + num + "条");
+            } else {
+                XxlJobHelper.handleSuccess("获取回显数据为空" + "状态码:" + responseEntity.getStatusCodeValue());
+                return R.success("请求成功 获取回显数据为空" + "状态码:" + responseEntity.getStatusCodeValue());
+            }
+        }
+        log.info("AI服务 获取趣味推荐信息数据请求失败,状态码:" + responseEntity.getStatusCodeValue());
+        XxlJobHelper.handleFail("任务执行失败 状态码" + responseEntity.getStatusCodeValue());
+        return R.success("任务执行失败 状态码" + responseEntity.getStatusCodeValue());
+    }
+
     class AnalysisRequest {
         private String start_time;
         private String end_time;

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

@@ -160,11 +160,11 @@ public class LifeUserOrderJob {
         calendar.set(Calendar.SECOND, 0);
         calendar.set(Calendar.MILLISECOND, 0);
         now = calendar.getTime();
-        LambdaUpdateWrapper<LifeUserOrder> selectWrapper = new LambdaUpdateWrapper<>();
+        QueryWrapper<LifeUserOrder> selectWrapper = new QueryWrapper<>();
         // 查询状态为待使用的
         List<Integer> status = new ArrayList<>();
         status.add(OrderStatusEnum.WAIT_USE.getStatus());
-        selectWrapper.in(LifeUserOrder::getStatus, status);
+        selectWrapper.inSql("luo.id", "SELECT distinct order_id FROM order_coupon_middle WHERE status in ( "+String.join(",", status.stream().map(String::valueOf).collect(Collectors.toList()))+")");
         // 查询待使用的订单
         List<LifeUserOrderVo> orderList = lifeUserOrderMapper.selectRefundList(selectWrapper);
 

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

@@ -1,6 +1,7 @@
 package shop.alien.job.store;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.xxl.job.core.context.XxlJobHelper;
 import com.xxl.job.core.handler.annotation.XxlJob;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -129,7 +130,7 @@ public class StoreMembershipCardJob {
             if (null != storeUser.getLogoutTime()) {
                 // 获取申请注销时间
                 Date logoutTime = storeUser.getLogoutTime();
-                // 获取申请注销 8 天后的时间
+                // 获取申请注销 8(7+1) 天后的时间 防止实际时间不到7天被删除 所以实际删除时间为申请注销时间往后推8天
                 Calendar calendar = Calendar.getInstance();
                 calendar.setTime(logoutTime);
                 calendar.add(Calendar.DAY_OF_YEAR, 8);
@@ -150,7 +151,7 @@ public class StoreMembershipCardJob {
             if (null != storeInfo.getLogoutTime()) {
                 // 获取申请注销时间
                 Date logoutTime = storeInfo.getLogoutTime();
-                // 获取申请注销 8 天后的时间
+                // 获取申请注销 8(7+1) 天后的时间 防止实际时间不到7天被删除 所以实际删除时间为申请注销时间往后推8天
                 Calendar calendar = Calendar.getInstance();
                 calendar.setTime(logoutTime);
                 calendar.add(Calendar.DAY_OF_YEAR, 8);

+ 22 - 0
alien-job/src/main/resources/bootstrap-uat.yml

@@ -0,0 +1,22 @@
+spring:
+  application:
+    name: alien-job
+
+  cloud:
+    nacos:
+      #注册中心
+      discovery:
+        server-addr: localhost:8848
+        username: nacos
+        password: ngfriend198092
+        namespace: 79060c39-10ad-4098-9022-5e8a47796f8f
+
+      #配置中心
+      config:
+        enabled: true
+        server-addr: localhost:8848
+        username: nacos
+        password: ngfriend198092
+        group: DEFAULT_GROUP
+        file-extension: yml
+        namespace: 79060c39-10ad-4098-9022-5e8a47796f8f

+ 1 - 0
alien-second/src/main/java/shop/alien/second/AlienSecondApplication.java

@@ -16,6 +16,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
         "shop.alien.config.http",
         "shop.alien.config.databases",
         "shop.alien.config.feign",
+        "shop.alien.config.properties",
         "shop.alien.config.redis"})
 @MapperScan({
         "shop.alien.mapper",

+ 34 - 0
alien-second/src/main/java/shop/alien/second/controller/RiskControlController.java

@@ -0,0 +1,34 @@
+package shop.alien.second.controller;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import shop.alien.second.service.RiskControlService;
+
+@RestController
+@RequestMapping("/riskControl")
+@RequiredArgsConstructor
+public class RiskControlController {
+    
+    private final RiskControlService riskControlService;
+    
+    /**
+     * 记录风控数据
+     *
+     * @param userId     用户ID
+     * @param ruleType   规则类型 1:洗钱嫌疑 2:账号异常 3:交易欺诈 4:异常发布
+     * @param ruleName   规则名称
+     * @param businessId 业务ID
+     * @param detailInfo 详细信息(JSON格式)
+     */
+    @PostMapping("/record")
+    public void recordRiskControlData(@RequestParam("userId") Integer userId,
+                                      @RequestParam("ruleType") Integer ruleType,
+                                      @RequestParam("ruleName") String ruleName,
+                                      @RequestParam("businessId") String businessId,
+                                      @RequestParam("detailInfo") String detailInfo) {
+        riskControlService.recordRiskControlData(userId, ruleType, ruleName, businessId, detailInfo);
+    }
+}

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

@@ -101,6 +101,11 @@ public class SecondGoodsController {
     @NoRepeatSubmit(expireTime = 5, message = "请勿重复提交更新商品请求")
     public R<Void> updateSecondGoods(@ApiParam("二手商品信息") @RequestBody SecondGoodsVo secondGoods) throws Exception {
         log.info("SecondGoodsController.updateSecondGoods?secondGoods={}", secondGoods.toString());
+        JSONObject data = JwtUtil.getCurrentUserInfo();
+        if (null != data) {
+            int userId = data.getInteger("userId");
+            secondGoods.setUserId(userId);// 设置用户ID (发布者)
+        }
         // 添加商品 0 创建 1 更新
         if (!secondGoodsService.createBasicInfo(secondGoods,1)) {
             return R.fail("修改二手商品失败");

+ 81 - 0
alien-second/src/main/java/shop/alien/second/controller/SecondUserPointsController.java

@@ -0,0 +1,81 @@
+package shop.alien.second.controller;
+
+import io.swagger.annotations.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.entity.second.SecondUserCredit;
+import shop.alien.second.service.SecondUserCreditService;
+
+/**
+ * 二手平台用户积分控制器
+ */
+@Slf4j
+@Api(tags = {"二期-用户积分"})
+@CrossOrigin
+@RestController
+@RequestMapping("/userPoints")
+@RequiredArgsConstructor
+public class SecondUserPointsController {
+    
+    private final SecondUserCreditService secondUserCreditService;
+    
+    @ApiOperation("获取用户积分")
+    @ApiOperationSupport(order = 1)
+    @ApiImplicitParams({
+        @ApiImplicitParam(name = "userId", value = "用户ID", dataType = "Integer", paramType = "path", required = true)
+    })
+    @GetMapping("/{userId}")
+    public R<SecondUserCredit> getUserPoints(@PathVariable Integer userId) {
+        log.info("获取用户积分,userId={}", userId);
+        try {
+            SecondUserCredit userPoints = secondUserCreditService.getByUserId(userId);
+            return R.data(userPoints);
+        } catch (Exception e) {
+            log.error("获取用户积分失败,userId={}", userId, e);
+            return R.fail("获取用户积分失败");
+        }
+    }
+    
+    @ApiOperation("更新用户积分")
+    @ApiOperationSupport(order = 2)
+    @ApiImplicitParams({
+        @ApiImplicitParam(name = "userId", value = "用户ID", dataType = "Integer", paramType = "path", required = true),
+        @ApiImplicitParam(name = "points", value = "积分变动值", dataType = "Integer", paramType = "query", required = true)
+    })
+    @PostMapping("/{userId}/points")
+    public R<Boolean> updateUserPoints(@PathVariable Integer userId, @RequestParam Integer points) {
+        log.info("更新用户积分,userId={}, points={}", userId, points);
+        try {
+            boolean result = secondUserCreditService.updatePoints(userId, points);
+            if (result) {
+                return R.success("积分更新成功");
+            } else {
+                return R.fail("积分更新失败");
+            }
+        } catch (Exception e) {
+            log.error("更新用户积分失败,userId={}, points={}", userId, points, e);
+            return R.fail("积分更新失败");
+        }
+    }
+    
+    @ApiOperation("新建用户积分记录")
+    @ApiOperationSupport(order = 3)
+    @ApiImplicitParams({
+        @ApiImplicitParam(name = "userId", value = "用户ID", dataType = "Integer", paramType = "path", required = true),
+        @ApiImplicitParam(name = "initialPoints", value = "初始积分值", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "pointsType", value = "初始积分类型", dataType = "Integer", paramType = "query")
+    })
+    @PostMapping("/create")
+    public void createPointsRecord(@RequestParam("userId")  Integer userId,
+                                   @RequestParam("initialPoints")  Integer initialPoints,
+                                   @RequestParam("pointsType")  Integer pointsType) {
+        log.info("新建用户积分记录,userId={}, initialPoints={}", userId, initialPoints);
+        try {
+            secondUserCreditService.createPointsRecord(userId, initialPoints, pointsType);
+        } catch (Exception e) {
+            log.error("新建用户积分记录失败,userId={}, initialPoints={}", userId, initialPoints, e);
+        }
+    }
+}

+ 60 - 0
alien-second/src/main/java/shop/alien/second/controller/SecondUserPointsRecordController.java

@@ -0,0 +1,60 @@
+package shop.alien.second.controller;
+
+import io.swagger.annotations.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.entity.second.SecondUserCreditRecord;
+import shop.alien.second.service.SecondUserCreditRecordService;
+
+import java.util.List;
+
+/**
+ * 二手平台用户积分记录控制器
+ */
+@Slf4j
+@Api(tags = {"二期-用户积分记录"})
+@CrossOrigin
+@RestController
+@RequestMapping("/userPointsRecord")
+@RequiredArgsConstructor
+public class SecondUserPointsRecordController {
+    
+    private final SecondUserCreditRecordService secondUserPointsRecordService;
+    
+    @ApiOperation("获取用户积分记录列表")
+    @ApiOperationSupport(order = 1)
+    @ApiImplicitParams({
+        @ApiImplicitParam(name = "userId", value = "用户ID", dataType = "Integer", paramType = "path", required = true)
+    })
+    @GetMapping("/user/{userId}")
+    public R<List<SecondUserCreditRecord>> getUserPointsRecords(@PathVariable Integer userId) {
+        log.info("获取用户积分记录列表,userId={}", userId);
+        try {
+            List<SecondUserCreditRecord> records = secondUserPointsRecordService.getRecordsByUserId(userId);
+            return R.data(records);
+        } catch (Exception e) {
+            log.error("获取用户积分记录列表失败,userId={}", userId, e);
+            return R.fail("获取用户积分记录列表失败");
+        }
+    }
+    
+    @ApiOperation("创建积分记录")
+    @ApiOperationSupport(order = 2)
+    @PostMapping("/create")
+    public R<Boolean> createPointsRecord(@RequestBody SecondUserCreditRecord record) {
+        log.info("创建积分记录,userId={}, points={}", record.getUserId(), record.getPoints());
+        try {
+            boolean result = secondUserPointsRecordService.createRecord(record);
+            if (result) {
+                return R.success("积分记录创建成功");
+            } else {
+                return R.fail("积分记录创建失败");
+            }
+        } catch (Exception e) {
+            log.error("创建积分记录失败,record={}", record, e);
+            return R.fail("积分记录创建失败");
+        }
+    }
+}

+ 39 - 0
alien-second/src/main/java/shop/alien/second/platform/PlatformSecondUserFreezeController.java

@@ -0,0 +1,39 @@
+package shop.alien.second.platform;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiOperationSupport;
+import io.swagger.annotations.ApiSort;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.entity.second.vo.SecondTradeRecordVo;
+import shop.alien.second.service.PlatformSecondTradeService;
+
+import java.util.List;
+
+@Slf4j
+@Api(tags = {"平台-账号冻结"})
+@ApiSort(1)
+@CrossOrigin
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/userFreeze")
+public class PlatformSecondUserFreezeController {
+
+    private final PlatformSecondTradeService secondTradeRecordService;
+
+    @ApiOperation("交易列表(分页)")
+    @ApiOperationSupport(order = 1)
+    @PostMapping("/getTradeRecordPage")
+    public R<IPage<SecondTradeRecordVo>> getTradeRecordPage(@RequestBody SecondTradeRecordVo vo) throws Exception {
+        log.info("PlatformSecondTradeController.getTradeRecordPage?vo={}", vo.toString());
+        return R.data(secondTradeRecordService.getTradeRecordPage(vo));
+    }
+
+
+
+}

+ 36 - 0
alien-second/src/main/java/shop/alien/second/service/RiskControlService.java

@@ -0,0 +1,36 @@
+package shop.alien.second.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import shop.alien.entity.second.SecondRiskControlRecord;
+
+import java.util.List;
+
+/**
+ * 风控服务接口
+ */
+public interface RiskControlService extends IService<SecondRiskControlRecord> {
+    
+    /**
+     * 记录风控数据
+     *
+     * @param userId     用户ID
+     * @param ruleType   规则类型 1:洗钱嫌疑 2:账号异常 3:交易欺诈 4:异常发布
+     * @param ruleName   规则名称
+     * @param businessId 业务ID
+     * @param detailInfo 详细信息(JSON格式)
+     */
+    void recordRiskControlData(Integer userId,
+                               Integer ruleType,
+                               String ruleName,
+                               String businessId,
+                               String detailInfo);
+
+    /**
+     * 获取相同类型的风控数据
+     *
+     * @param ruleType   规则类型
+     * @param businessId 业务ID
+     * @return 相同类型的风控数据列表
+     */
+    List<SecondRiskControlRecord> getSameTypeRiskControlRecords(Integer ruleType, String businessId);
+}

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

@@ -6,6 +6,7 @@ import org.springframework.transaction.annotation.Transactional;
 import shop.alien.entity.SecondVideoTask;
 import shop.alien.entity.second.SecondGoods;
 import shop.alien.entity.second.SecondGoodsRecord;
+import shop.alien.entity.second.SecondRiskControlRecord;
 import shop.alien.entity.second.vo.SecondGoodsVo;
 import shop.alien.entity.second.vo.SecondGoodsAdminQueryDTO;
 import shop.alien.entity.second.vo.SecondGoodsDetailVo;
@@ -208,4 +209,12 @@ public interface SecondGoodsService extends IService<SecondGoods> {
      * @return 处理后的商品详情信息
      */
     SecondGoodsVo dealSecondGoodsRecordInfo(Integer goodsId);
+
+    /**
+     * 批量处理商品信息(管理后台使用)( ruleType = 4 异常发布场景)
+     * @param ruleType 风险类型
+     * @param businessId 业务ID
+     * @return 是否处理成功
+     */
+    boolean batchShelveGoodsByRiskControlRecord(Integer ruleType, String businessId);
 }

+ 24 - 0
alien-second/src/main/java/shop/alien/second/service/SecondUserCreditRecordService.java

@@ -0,0 +1,24 @@
+package shop.alien.second.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import shop.alien.entity.second.SecondUserCreditRecord;
+
+/**
+ * 二手平台用户积分记录服务接口
+ */
+public interface SecondUserCreditRecordService extends IService<SecondUserCreditRecord> {
+    
+    /**
+     * 根据用户ID获取积分记录列表
+     * @param userId 用户ID
+     * @return 积分记录列表
+     */
+    java.util.List<SecondUserCreditRecord> getRecordsByUserId(Integer userId);
+    
+    /**
+     * 创建积分记录
+     * @param record 积分记录信息
+     * @return 是否创建成功
+     */
+    boolean createRecord(SecondUserCreditRecord record);
+}

+ 33 - 0
alien-second/src/main/java/shop/alien/second/service/SecondUserCreditService.java

@@ -0,0 +1,33 @@
+package shop.alien.second.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import shop.alien.entity.second.SecondUserCredit;
+
+/**
+ * 二手平台用户积分服务接口
+ */
+public interface SecondUserCreditService extends IService<SecondUserCredit> {
+    
+    /**
+     * 根据用户ID获取用户积分信息
+     * @param userId 用户ID
+     * @return 用户积分信息
+     */
+    SecondUserCredit getByUserId(Integer userId);
+    
+    /**
+     * 更新用户积分
+     * @param userId 用户ID
+     * @param points 积分变动值(可为负数)
+     * @return 是否更新成功
+     */
+    boolean updatePoints(Integer userId, Integer points);
+    
+    /**
+     * 新建用户积分记录
+     * @param userId 用户ID
+     * @param initialPoints 初始积分值
+     * @return 是否创建成功
+     */
+    boolean createPointsRecord(Integer userId, Integer initialPoints, Integer pointsType);
+}

+ 75 - 0
alien-second/src/main/java/shop/alien/second/service/impl/RiskControlServiceImpl.java

@@ -0,0 +1,75 @@
+package shop.alien.second.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import shop.alien.entity.second.SecondRiskControlRecord;
+import shop.alien.mapper.second.SecondRiskControlRecordMapper;
+import shop.alien.second.service.RiskControlService;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 风控服务实现类
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class RiskControlServiceImpl extends ServiceImpl<SecondRiskControlRecordMapper, SecondRiskControlRecord> implements RiskControlService {
+
+    private final SecondRiskControlRecordMapper secondRiskControlRecordMapper;
+
+    /**
+     * 记录风控数据
+     *
+     * @param userId     用户ID
+     * @param ruleType   规则类型 1:洗钱嫌疑 2:账号异常 3:交易欺诈 4:异常发布
+     * @param ruleName   规则名称
+     * @param businessId 业务ID
+     * @param detailInfo 详细信息(JSON格式)
+     */
+    @Override
+    public void recordRiskControlData(Integer userId,
+                                       Integer ruleType,
+                                       String ruleName,
+                                      String businessId,
+                                       String detailInfo) {
+        try {
+            SecondRiskControlRecord record = new SecondRiskControlRecord();
+            record.setUserId(userId);
+            record.setRuleType(ruleType);
+            record.setRuleName(ruleName);
+            record.setBusinessId(businessId);
+            record.setDetailInfo(detailInfo);
+            record.setCreatedTime(new Date());
+            record.setUpdatedTime(new Date());
+            record.setDeleteFlag(0);
+            record.setCreatedUserId(userId);
+            record.setUpdatedUserId(userId);
+
+            secondRiskControlRecordMapper.insert(record);
+        } catch (Exception e) {
+            log.error("记录风控数据时发生异常: 用户ID={}, 规则类型={},业务id={}", userId, ruleType, businessId, e);
+        }
+    }
+
+    /**
+     * 获取相同类型的风控数据
+     *
+     * @param ruleType   规则类型 1:洗钱嫌疑 2:账号异常 3:交易欺诈 4:异常发布
+     * @param businessId 业务ID
+     * @return 相同类型的风控数据列表
+     */
+    @Override
+    public List<SecondRiskControlRecord> getSameTypeRiskControlRecords(Integer ruleType, String businessId) {
+        log.info("获取相同类型的风控数据: 规则类型={},业务id={}", ruleType, businessId);
+        QueryWrapper<SecondRiskControlRecord> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("rule_type", ruleType);
+        queryWrapper.eq("business_id", businessId);
+        log.info("查询条件: {}", queryWrapper.getSqlSegment());
+        return secondRiskControlRecordMapper.selectList(queryWrapper);
+    }
+}

+ 174 - 16
alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsServiceImpl.java

@@ -16,40 +16,30 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
+import shop.alien.config.properties.RiskControlProperties;
 import shop.alien.entity.SecondVideoTask;
 import shop.alien.entity.second.*;
-import shop.alien.entity.second.SecondTradeRecord;
+import shop.alien.entity.second.enums.RiskControlRuleTypeEnum;
+import shop.alien.entity.second.enums.SecondGoodsStatusEnum;
 import shop.alien.entity.second.vo.*;
-import shop.alien.entity.second.vo.SecondGoodsDetailVo;
 import shop.alien.entity.store.*;
 import shop.alien.entity.store.vo.LifeUserVo;
 import shop.alien.entity.store.vo.WebSocketVo;
 import shop.alien.mapper.*;
-import shop.alien.mapper.second.SecondGoodsAuditMapper;
-import shop.alien.mapper.second.SecondGoodsMapper;
-import shop.alien.mapper.second.SecondGoodsRecordMapper;
-import shop.alien.mapper.second.SecondTradeRecordMapper;
+import shop.alien.mapper.second.*;
 import shop.alien.second.feign.AlienStoreFeign;
 import shop.alien.second.service.PlatformSecondTradeService;
+import shop.alien.second.service.RiskControlService;
 import shop.alien.second.service.SecondGoodsService;
 import shop.alien.second.service.VideoModerationService;
 import shop.alien.util.common.Constants;
-import shop.alien.entity.second.enums.SecondGoodsStatusEnum;
 import shop.alien.util.common.VideoUtils;
 import shop.alien.util.common.safe.*;
 
 import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -151,6 +141,14 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
      */
     private final PlatformSecondTradeService platformSecondTradeService;
 
+    @Autowired
+    private RiskControlProperties riskControlProperties;
+    
+    /**
+     * 风控服务
+     */
+    private final RiskControlService riskControlService;
+
     @Override
     public SecondGoodsRecordDetailVo getAdminGoodsRecordDetail(Integer recordId) {
         // 1. 获取商品操作记录基本信息
@@ -571,6 +569,16 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
                 return false; // 如果获取不到ID,视为操作失败
             }
 
+            // 检查用户是否在24小时内发布同类商品超过阈值
+            if (!checkUserPublishSameCategoryLimit(goods)) {
+                log.warn("用户 {} 在24小时内发布同类商品次数超过限制", goodsDTO.getUserId());
+            }
+
+            // 检查用户是否在24小时内发布商品超过阈值
+            if (!checkUserPublishLimit(goods)) {
+                log.warn("用户 {} 在24小时内发布商品次数超过限制", goodsDTO.getUserId());
+
+            }
             // 保存商品图片信息
             if (!saveStoreImages(savedGoodsId, goodsDTO )) {
                 return false;
@@ -587,6 +595,88 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
         }
     }
 
+
+    /**
+     * 检查用户在24小时内 频繁修改发布商品的数量是否超过限制
+     * @param goods  用户ID,商品ID
+     * @return 是否未超过限制
+     */
+    private boolean checkUserPublishLimit(SecondGoods goods) {
+        // 获取配置的阈值
+        int publishLimit = riskControlProperties.getTradeFraud().getPublishCount24h();
+        // 时间窗口(小时)
+        int timeWindowHours = riskControlProperties.getTradeFraud().getTimeWindowHours();
+
+        // 计算时间窗口前的时间
+        Date timeWindowStart = new Date(System.currentTimeMillis() - timeWindowHours * 60 * 60 * 1000L);
+
+        // 查询用户在24小时内发布的商品数量
+        LambdaQueryWrapper<SecondGoodsRecord> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(SecondGoodsRecord::getUserId, goods.getUserId())
+                .eq(SecondGoodsRecord::getGoodsId, goods.getId())
+                .ge(SecondGoodsRecord::getReleaseTime, timeWindowStart)
+                .in(SecondGoodsRecord::getGoodsStatus,
+                        SecondGoodsStatusEnum.LISTED.getCode(),
+                        SecondGoodsStatusEnum.SOLD.getCode());
+        // 获取发布
+        List<SecondGoodsRecord> secondGoodsRecordList = secondGoodsRecordMapper.selectList(queryWrapper);
+        // 提取商品id集合
+        List<Integer> secondGoodsRecordIdList = secondGoodsRecordList.stream().map(SecondGoodsRecord::getId).collect(Collectors.toList());
+        // 转成json
+        String json = JSON.toJSONString(secondGoodsRecordIdList);
+        // 获取实际发布数量
+        int sameCategoryCount = secondGoodsRecordList.size();
+        // 如果发布数量超过限制,记录风控数据
+        if (sameCategoryCount >= publishLimit) {
+            // "异常发布-同类商品发布频率"
+            riskControlService.recordRiskControlData(goods.getUserId(), RiskControlRuleTypeEnum.TRANSACTION_FRAUD.getRuleType(), RiskControlRuleTypeEnum.TRANSACTION_FRAUD.getDescription(), goods.getId().toString(),json);
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 检查用户在指定时间窗口内发布同类商品的数量是否超过限制
+     * @param goods 商品信息
+     * @return 是否未超过限制
+     */
+    private boolean checkUserPublishSameCategoryLimit(SecondGoods goods) {
+        // 获取配置的阈值
+        int sameCategoryLimit = riskControlProperties.getAbnormalPublish().getSameCategoryCount24h();
+        int timeWindowHours = riskControlProperties.getAbnormalPublish().getTimeWindowHours();
+        
+        // 计算时间窗口前的时间
+        Date timeWindowStart = new Date(System.currentTimeMillis() - timeWindowHours * 60 * 60 * 1000L);
+        
+        // 查询用户在时间窗口内发布同类商品的数量
+        LambdaQueryWrapper<SecondGoods> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(SecondGoods::getUserId, goods.getUserId())
+                .eq(SecondGoods::getCategoryOneId, goods.getCategoryOneId())
+                .eq(SecondGoods::getCategoryTwoId, goods.getCategoryTwoId())
+                .ge(SecondGoods::getReleaseTime, timeWindowStart)
+                .in(SecondGoods::getGoodsStatus,
+                        SecondGoodsStatusEnum.LISTED.getCode(),
+                        SecondGoodsStatusEnum.SOLD.getCode());
+
+        // 获取发布
+        List<SecondGoods> secondGoodsList = list(queryWrapper);
+        // 提取商品id集合
+        List<Integer> secondGoodsIds = secondGoodsList.stream().map(SecondGoods::getId).collect(Collectors.toList());
+        // 转成json
+        String json = JSON.toJSONString(secondGoodsIds);
+        // 获取实际发布数量
+        int sameCategoryCount = secondGoodsList.size();
+        // 如果发布数量超过限制,记录风控数据
+        if (sameCategoryCount >= sameCategoryLimit) {
+            // "异常发布-同类商品发布频率"
+            riskControlService.recordRiskControlData(goods.getUserId(), RiskControlRuleTypeEnum.ABNORMAL_PUBLISH.getRuleType(), RiskControlRuleTypeEnum.ABNORMAL_PUBLISH.getDescription(), goods.getId().toString(),json);
+            return false;
+        }
+        return true;
+    }
+
+
+
     /**
      * 执行内容审核
      * @param goodsDTO 商品信息
@@ -1781,6 +1871,74 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
     }
 
     /**
+     * 根据风控记录中的JSON数据批量下架商品
+     * @param goodsIds 商品ID集合
+     * @return 是否下架成功
+     */
+    public boolean batchShelveGoodsByIds(List<Integer> goodsIds) {
+        if (goodsIds == null || goodsIds.isEmpty()) {
+            return true;
+        }
+        
+        // 批量更新商品状态为下架状态
+        LambdaUpdateWrapper<SecondGoods> updateWrapper = new LambdaUpdateWrapper<>();
+        updateWrapper.in(SecondGoods::getId, goodsIds)
+                .set(SecondGoods::getGoodsStatus, SecondGoodsStatusEnum.DELISTED.getCode());
+        
+        boolean updateResult = update(updateWrapper);
+        
+        if (updateResult) {
+            // 批量查询更新后的商品信息
+            Collection<SecondGoods> updatedGoodsList = listByIds(goodsIds);
+            
+            // 为每个商品记录操作历史并发送通知
+            for (SecondGoods goods : updatedGoodsList) {
+                recordGoodsOperation(goods, "风控下架");
+                sendShelveMessage(goods);
+            }
+        }
+        
+        return updateResult;
+    }
+
+    /**
+     * 根据风控记录中的JSON数据批量下架商品( ruleType = 4 异常发布场景)
+     * @param ruleType 风控规则类型
+     * @param businessId 业务ID
+     * @return 是否下架成功
+     */
+    @Override
+    public boolean batchShelveGoodsByRiskControlRecord(Integer ruleType, String businessId) {
+        try {
+            // 获取相同类型的风控数据
+            List<SecondRiskControlRecord> riskControlRecordList = riskControlService.getSameTypeRiskControlRecords(ruleType, businessId);
+            // 获取风控数据详情
+            List<String> detailInfoList = riskControlRecordList.stream()
+                    .map(SecondRiskControlRecord::getDetailInfo)
+                    .collect(Collectors.toList());
+
+            // 声明所有被风控的商品ID
+            List<Integer> goodsIdList = Lists.newArrayList();
+
+            // 循环情信息json 转换为集合
+            for (String detailInfo : detailInfoList){
+                // 解析JSON获取商品ID列表
+                List<Integer> goodsIds = JSON.parseArray(detailInfo, Integer.class);
+                goodsIdList.addAll(goodsIds);
+            }
+
+            // goodsIdList 去重
+            goodsIdList = goodsIdList.stream().distinct().collect(Collectors.toList());
+
+            // 调用批量下架方法
+            return batchShelveGoodsByIds(goodsIdList);
+        } catch (Exception e) {
+            log.error("根据风控记录批量下架商品失败,详情: {}", ruleType, e);
+            return false;
+        }
+    }
+
+    /**
      * 下架商品
      * @param secondGoods 商品信息
      * @return 是否下架成功

+ 59 - 0
alien-second/src/main/java/shop/alien/second/service/impl/SecondUserCreditRecordServiceImpl.java

@@ -0,0 +1,59 @@
+package shop.alien.second.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import shop.alien.entity.second.SecondUserCreditRecord;
+import shop.alien.mapper.second.SecondUserCreditRecordMapper;
+import shop.alien.second.service.SecondUserCreditRecordService;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 二手平台用户积分记录服务实现类
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class SecondUserCreditRecordServiceImpl extends ServiceImpl<SecondUserCreditRecordMapper, SecondUserCreditRecord> implements SecondUserCreditRecordService {
+    
+    private final SecondUserCreditRecordMapper secondUserCreditRecordMapper;
+    
+    /**
+     * 根据用户ID获取积分记录列表
+     * @param userId 用户ID
+     * @return 积分记录列表
+     */
+    @Override
+    public List<SecondUserCreditRecord> getRecordsByUserId(Integer userId) {
+        log.info("查询用户积分记录,userId={}", userId);
+        LambdaQueryWrapper<SecondUserCreditRecord> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(SecondUserCreditRecord::getUserId, userId)
+                .eq(SecondUserCreditRecord::getDeleteFlag, 0)
+                .orderByDesc(SecondUserCreditRecord::getCreatedTime);
+        return secondUserCreditRecordMapper.selectList(queryWrapper);
+    }
+    
+    /**
+     * 创建积分记录
+     * @param record 积分记录信息
+     * @return 是否创建成功
+     */
+    @Override
+    public boolean createRecord(SecondUserCreditRecord record) {
+        try {
+            log.info("创建积分记录,userId={}, points={}", record.getUserId(), record.getPoints());
+            record.setDeleteFlag(0);
+            record.setCreatedTime(new Date());
+            record.setUpdatedTime(new Date());
+            int result = secondUserCreditRecordMapper.insert(record);
+            return result > 0;
+        } catch (Exception e) {
+            log.error("创建积分记录失败,userId={}, points={}", record.getUserId(), record.getPoints(), e);
+            return false;
+        }
+    }
+}

+ 124 - 0
alien-second/src/main/java/shop/alien/second/service/impl/SecondUserCreditServiceImpl.java

@@ -0,0 +1,124 @@
+package shop.alien.second.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import shop.alien.entity.second.SecondUserCredit;
+import shop.alien.entity.second.SecondUserCreditRecord;
+import shop.alien.mapper.second.SecondUserCreditMapper;
+import shop.alien.second.service.SecondUserCreditService;
+
+import java.util.Date;
+
+/**
+ * 二手平台用户积分服务实现类
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class SecondUserCreditServiceImpl extends ServiceImpl<SecondUserCreditMapper, SecondUserCredit> implements SecondUserCreditService {
+    
+    private final SecondUserCreditMapper secondUserCreditMapper;
+
+    private final SecondUserCreditRecordServiceImpl serviceImpl;
+
+    /**
+     * 根据用户ID获取用户积分信息
+     * @param userId 用户ID
+     * @return 用户积分信息
+     */
+    @Override
+    public SecondUserCredit getByUserId(Integer userId) {
+        LambdaQueryWrapper<SecondUserCredit> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(SecondUserCredit::getUserId, userId)
+                .eq(SecondUserCredit::getDeleteFlag, 0);
+        return secondUserCreditMapper.selectOne(queryWrapper);
+    }
+    
+    /**
+     * 更新用户积分
+     * @param userId 用户ID
+     * @param points 积分变动值(可为负数)
+     * @return 是否更新成功
+     */
+    @Override
+    public boolean updatePoints(Integer userId, Integer points) {
+        try {
+            // 查询用户积分记录
+            SecondUserCredit userPoints = getByUserId(userId);
+            
+            if (userPoints == null) {
+                // 如果用户没有积分记录,则创建新记录
+                userPoints = new SecondUserCredit();
+                userPoints.setUserId(userId);
+                userPoints.setUserPoints(points > 0 ? points : 0);
+                userPoints.setDeleteFlag(0);
+                userPoints.setCreatedTime(new Date());
+                userPoints.setUpdatedTime(new Date());
+                secondUserCreditMapper.insert(userPoints);
+            } else {
+                // 更新积分
+                int newPoints = userPoints.getUserPoints() + points;
+                userPoints.setUserPoints(newPoints > 0 ? newPoints : 0);
+                userPoints.setUpdatedTime(new Date());
+                secondUserCreditMapper.updateById(userPoints);
+            }
+            return true;
+        } catch (Exception e) {
+            log.error("更新用户积分失败,userId={}, points={}", userId, points, e);
+            return false;
+        }
+    }
+    
+    /**
+     * 新建用户积分记录
+     * @param userId 用户ID
+     * @param initialPoints 初始积分值
+     * @return 是否创建成功
+     */
+    @Override
+    public boolean createPointsRecord(Integer userId, Integer initialPoints, Integer pointsType) {
+        try {
+            // 检查是否已存在记录
+            SecondUserCredit existingPoints = getByUserId(userId);
+            if (existingPoints != null) {
+                log.warn("用户积分记录已存在,userId={}", userId);
+                return false;
+            }
+            return addPointsRecord(userId, initialPoints, pointsType);
+        } catch (Exception e) {
+            log.error("创建用户积分记录失败,userId={}, initialPoints={}", userId, initialPoints, e);
+            return false;
+        }
+    }
+
+    public boolean addPointsRecord(Integer userId, Integer points, Integer pointsType) {
+        try {
+            // 创建新的积分记录
+            SecondUserCredit userPoints = new SecondUserCredit();
+            userPoints.setUserId(userId);
+            userPoints.setUserPoints(points != null ? points : 0);
+            userPoints.setDeleteFlag(0);
+            userPoints.setCreatedTime(new Date());
+            userPoints.setUpdatedTime(new Date());
+
+            int result = secondUserCreditMapper.insert(userPoints);
+
+            // 创建积分记录
+            SecondUserCreditRecord record = new SecondUserCreditRecord();
+            record.setUserId(userId);
+            record.setPoints(points);
+            record.setPointsType(pointsType);
+            serviceImpl.createRecord(record);
+
+            return result > 0;
+        } catch (Exception e) {
+            log.error("删除用户积分记录失败,userId={}", userId, e);
+            return false;
+        }
+    }
+
+
+}

+ 22 - 0
alien-second/src/main/resources/bootstrap-uat.yml

@@ -0,0 +1,22 @@
+spring:
+  application:
+    name: alien-second
+
+  cloud:
+    nacos:
+      #注册中心
+      discovery:
+        server-addr: localhost:8848
+        username: nacos
+        password: ngfriend198092
+        namespace: 79060c39-10ad-4098-9022-5e8a47796f8f
+
+      #配置中心
+      config:
+        enabled: true
+        server-addr: localhost:8848
+        username: nacos
+        password: ngfriend198092
+        group: DEFAULT_GROUP
+        file-extension: yml
+        namespace: 79060c39-10ad-4098-9022-5e8a47796f8f

+ 5 - 0
alien-store/pom.xml

@@ -153,6 +153,11 @@
         </dependency>
         <!-- mybatis-plus代码生成器 End -->
 
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+        </dependency>
+
         <!--Swagger Start-->
         <dependency>
             <groupId>io.springfox</groupId>

+ 2 - 0
alien-store/src/main/java/shop/alien/store/AlienStoreApplication.java

@@ -4,6 +4,7 @@ import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrap
 import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.openfeign.EnableFeignClients;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.scheduling.annotation.EnableScheduling;
 
@@ -11,6 +12,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
 @EnableSwaggerBootstrapUI
 @MapperScan({"shop.alien.mapper"})
 @SpringBootApplication
+@EnableFeignClients(basePackages = "shop.alien.store.feign")
 @EnableScheduling
 public class AlienStoreApplication {
 

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

@@ -216,7 +216,8 @@ public class AliController {
     @ApiImplicitParams({
             @ApiImplicitParam(name = "outTradeNo", value = "订单号", dataType = "String", paramType = "query", required = true),
             @ApiImplicitParam(name = "refundAmount", value = "退款金额", dataType = "String", paramType = "query", required = true),
-            @ApiImplicitParam(name = "refundReason", value = "退款原因", dataType = "String", paramType = "query", required = true)
+            @ApiImplicitParam(name = "refundReason", value = "退款原因", dataType = "String", paramType = "query", required = true),
+            @ApiImplicitParam(name = "partialRefundCode", value = "部分退款编码", dataType = "String", paramType = "query", required = false)
     })
     @GetMapping("/processRefund")
     public String processRefund(@RequestParam(value = "outTradeNo") String outTradeNo,

+ 8 - 4
alien-store/src/main/java/shop/alien/store/controller/LifePromotionPackageController.java

@@ -1,5 +1,6 @@
 package shop.alien.store.controller;
 
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import io.swagger.annotations.*;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -29,11 +30,14 @@ public class LifePromotionPackageController {
 
     @ApiOperation("获取推广套餐")
     @ApiOperationSupport(order = 1)
-    @ApiImplicitParams({@ApiImplicitParam(name = "expert_id", value = "达人id", dataType = "Long", paramType = "query", required = true)})
+    @ApiImplicitParams({@ApiImplicitParam(name = "expert_id", value = "达人id", dataType = "Long", paramType = "query", required = true),
+            @ApiImplicitParam(name = "page", value = "页数", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "size", value = "大小", dataType = "Integer", paramType = "query", required = true)}
+    )
     @GetMapping("/getByExpertId")
-    public R<List<LifePromotionPackageVo>> getByExpertId(Long expertId) {
-        log.info("LifePromotionPackageController.getByExpertId?id={}", expertId);
-        return R.data(promotionPackageService.getByExpertId(expertId));
+    public R<IPage<LifePromotionPackageVo>> getByExpertId(@RequestParam("expertId") Long expertId,@RequestParam(defaultValue = "1") int page, @RequestParam(defaultValue = "10") int size) {
+        log.info("LifePromotionPackageController.getByExpertId?id={},page={},size={}", expertId,page,size);
+        return R.data(promotionPackageService.getByExpertId(expertId, page, size));
     }
 
     @ApiOperation("新增或修改推广套餐")

+ 35 - 0
alien-store/src/main/java/shop/alien/store/controller/LifeUserController.java

@@ -1,5 +1,6 @@
 package shop.alien.store.controller;
 
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import io.swagger.annotations.*;
 import lombok.RequiredArgsConstructor;
@@ -192,4 +193,38 @@ public class LifeUserController {
         log.info("LifeUserController.getUserByPhone?phone={}", phone);
         return R.data(service.getUserByPhone(phone));
     }
+
+    /**
+     * 支付设置增加支付宝账户
+     */
+    @ApiOperation("支付设置增加支付宝账户")
+    @PostMapping("/addAlipayAccount")
+    public R<Integer> addAlipayAccount(@RequestBody LifeUserVo lifeUserVo) {
+        log.info("LifeUserController.addAlipayAccount?storeUserVo={}", lifeUserVo);
+        LambdaUpdateWrapper<LifeUser> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
+        lambdaUpdateWrapper.set(LifeUser :: getAlipayAccount, lifeUserVo.getAlipayAccount());
+        lambdaUpdateWrapper.eq(LifeUser :: getId, lifeUserVo.getId());
+        return R.data(lifeUserMapper.update(null,lambdaUpdateWrapper));
+    }
+
+    /**
+     * 根据id判断是否有支付密码
+     */
+    @ApiOperation("是否有支付密码")
+    @GetMapping("/havePayPassword")
+    public R<Boolean> havePayPassword(@RequestParam String userId,@RequestParam(required = false) String password){
+        log.info("LifeUserController.havePayPassword?userId={},password={}",userId,password);
+        return lifeUserService.havePayPassword(userId,password);
+    }
+
+    @ApiOperation("修改支付密码")
+    @ApiOperationSupport(order = 5)
+    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "主键", dataType = "String", paramType = "query", required = true), @ApiImplicitParam(name = "payPassword", value = "支付密码", dataType = "String", paramType = "query", required = true)})
+    @GetMapping("/setPayPassword")
+    public R<Boolean> setPayPassword(Integer id, String payPassword) {
+        if (lifeUserService.setPayPassword(id, payPassword)) {
+            return R.success("修改成功");
+        }
+        return R.fail("修改失败");
+    }
 }

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

@@ -10,6 +10,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 import shop.alien.entity.result.R;
+import shop.alien.entity.store.LifeBrowseRecord;
 import shop.alien.entity.store.LifeUserDynamics;
 import shop.alien.entity.store.vo.LifePinglunVo;
 import shop.alien.entity.store.vo.LifeUserDynamicsVo;
@@ -153,7 +154,7 @@ public class LifeUserDynamicsController {
     }
 
     @PostMapping("addLiulanShu")
-    public R dianzan(String id) {
+    public R addLiulanCount(String id) {
         log.info("LifeUserDynamicsController.addLiulanShu?id={}", id);
         if (lifeUserDynamicsService.addLiulanCount(id) == 0){
             return R.fail("操作失败");
@@ -236,4 +237,35 @@ public class LifeUserDynamicsController {
         LifeUserDynamicsVo lifeUserDynamicsVo = lifeUserDynamicsService.getDynamicsDetail(id);
         return R.data(lifeUserDynamicsVo);
     }
+
+    @ApiOperation("达人发布动态详情")
+    @ApiOperationSupport(order = 6)
+    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "动态ID", dataType = "Integer", paramType = "query", required = true),})
+    @GetMapping("/getExpertDynamicsDetail")
+    public R<LifeUserDynamicsVo> getExpertDynamicsDetail(@RequestParam() Integer id) {
+        log.info("LifeUserDynamicsController.getDynamicsDetail?id={}", id);
+        LifeUserDynamicsVo lifeUserDynamicsVo = lifeUserDynamicsService.getExpertDynamicsDetail(id);
+        return R.data(lifeUserDynamicsVo);
+    }
+
+
+    @ApiOperation("GVM推荐用户完成支付")
+    @ApiOperationSupport(order = 7)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "dynamicsId", value = "达人动态Id", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "finalPrice", value = "最终付款金额", dataType = "String", paramType = "query", required = true)})
+    @GetMapping("/getOrderGmvUser")
+    public R getOrderGmvUser(@RequestParam() Integer dynamicsId, @RequestParam() String finalPrice) {
+        log.info("LifeUserDynamicsController.getOrderGmvUser?dynamicsId={}&finalPrice={}", dynamicsId, finalPrice);
+        return R.data(lifeUserDynamicsService.countGvm(dynamicsId, finalPrice));
+    }
+
+    @ApiOperation("用户通过达人推广进入店铺浏览数")
+    @ApiOperationSupport(order = 8)
+    @PostMapping("/addUserStoreBrowseNumber")
+    public R addUserStoreBrowseNumber(@RequestBody LifeBrowseRecord lifeBrowseRecord) {
+        log.info("LifeUserDynamicsController.addUserStoreBrowseNumber?lifeBrowseRecord={}",lifeBrowseRecord.toString());
+        return R.data(lifeUserDynamicsService.addUserStoreBrowseNumber(lifeBrowseRecord));
+    }
+
 }

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

@@ -2,6 +2,7 @@ package shop.alien.store.controller;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import io.swagger.annotations.*;
+import lombok.Data;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.CrossOrigin;
@@ -14,7 +15,9 @@ import shop.alien.entity.store.vo.LifeUserExpertOrderVo;
 import shop.alien.entity.store.vo.LifeUserExpertVo;
 import shop.alien.store.service.LifeUserExpertService;
 
+import java.math.BigDecimal;
 import java.util.List;
+import java.util.Map;
 
 @Api(tags = {"平台-达人管理"})
 @Slf4j
@@ -53,14 +56,19 @@ public class LifeUserExpertController {
         return R.data(lifeUserExpertService.getExpertOrderList(page, size, expertId, orderNo, storeName, storeId));
     }
 
-    @ApiOperation("成为达人")
+    @ApiOperation("成为达人,以及状态审核或驳回")
     @ApiOperationSupport(order = 3)
-    @ApiImplicitParams({@ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer", paramType = "query", required = true),
-            @ApiImplicitParam(name = "expertType", value = "达人类型", dataType = "String", paramType = "query", required = true)})
+    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "用户id", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "userPhone", value = "用户电话", dataType = "String", paramType = "query", required = true),
+            @ApiImplicitParam(name = "comment", value = "拒绝原因", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "commissionRate", value = "佣金比例", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "advanceRate", value = "预付款比例", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "expertStatus", value = "审核状态 通过0 审核中1 拒绝2", dataType = "Integer", paramType = "query", required = true)})
+//    @ApiImplicitParam(name = "expertType", value = "达人类型", dataType = "String", paramType = "query", required = true)})
     @GetMapping("/becomeExpert")
-    public R<Boolean> becomeExpert(Integer userId, String expertType) {
-        log.info("LifeUserExpertController.becomeExpert?id={},expertType={}", userId, expertType);
-        return R.data(lifeUserExpertService.becomeExpert(userId, expertType));
+    public R<Boolean> becomeExpert(Integer id,  String userPhone, String comment, Integer expertStatus ,Integer commissionRate, Integer advanceRate) {
+        log.info("LifeUserExpertController.becomeExpert?id={},userPhone={},comment={},expertStatus={}", id, userPhone,comment,expertStatus);
+        return R.data(lifeUserExpertService.becomeExpert(id, userPhone,comment,expertStatus,commissionRate, advanceRate));
     }
 
     @ApiOperation("取消达人")
@@ -103,4 +111,111 @@ public class LifeUserExpertController {
         log.info("LifeUserExpertController.greatGoodsType?expertId={}", expertId);
         return R.data(lifeUserExpertService.greatGoodsType(expertId));
     }
+
+    @ApiOperation("申请中达人列表")
+    @ApiOperationSupport(order = 9)
+    @ApiImplicitParams({@ApiImplicitParam(name = "page", value = "分页页数", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "size", value = "分页条数", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "userName", value = "用户昵称", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "realName", value = "真实姓名", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "userPhone", value = "联系电话", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "expertStatus", value = "审核状态", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "createdTime", value = "开始时间", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "endTime", value = "结束时间", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "userId", value = "用户id", dataType = "String", paramType = "query")})
+    @GetMapping("/getApplicationExpertList")
+    public R<IPage<LifeUserExpertVo>> getApplicationExpertList(Integer page, Integer size, String userName, String realName, String userPhone, Integer expertStatus, String createdTime, String endTime , Integer userId) {
+        log.info("LifeUserExpertController.getApplicationExpertList?page={},size={},userName={},realName={},userPhone={},expertStatus={},createdTime={},endTime={},userId={}", page, size, userName,realName,userPhone,expertStatus,createdTime,endTime,userId);
+        return R.data(lifeUserExpertService.getApplicationExpertList(page, size, userName, realName, userPhone, expertStatus, createdTime, endTime, userId));
+    }
+
+    @ApiOperation("达人申请查看详情")
+    @ApiOperationSupport(order = 10)
+    @ApiImplicitParams({@ApiImplicitParam(name = "userId", value = "用户id", dataType = "String", paramType = "query")})
+    @GetMapping("/getViewDetails")
+    public R<LifeUserExpertVo> getViewDetails( Integer userId) {
+        log.info("LifeUserExpertController.getViewDetails?userId={}",userId);
+        return R.data(lifeUserExpertService.getViewDetails(userId));
+    }
+
+    @ApiOperation("达人预付款列表")
+    @ApiOperationSupport(order = 11)
+    @ApiImplicitParams({@ApiImplicitParam(name = "page", value = "分页页数", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "size", value = "分页条数", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "realName", value = "真实姓名", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "userPhone", value = "联系电话", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "advancePaymentStatus", value = "预付款审核状态", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "orderCreatedTime", value = "下单开始时间", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "orderEndTime", value = "下单结束时间", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "name", value = "套餐名称", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "orderNo", value = "订单编号", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "storeName", value = "商家昵称", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "userId", value = "用户id", dataType = "String", paramType = "query")
+    })
+    @GetMapping("/getAdvancePaymentList")
+    public R<IPage<LifeUserExpertOrderVo>> getAdvancePaymentList( Integer page, Integer size,String realName, String userPhone, String advancePaymentStatus, String orderCreatedTime, String orderEndTime ,String name, Integer userId) {
+        log.info("LifeUserExpertController.getViewDetails?userId={}",userId);
+        return R.data(lifeUserExpertService.getAdvancePaymentList(page, size, realName, userPhone, advancePaymentStatus, orderCreatedTime, orderEndTime, name, userId));
+    }
+
+
+    @ApiOperation("预付款审核接口")
+    @ApiOperationSupport(order = 12)
+    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "达人订单表id", dataType = "Integer", paramType = "query",required = true),
+                        @ApiImplicitParam(name = "reasonRefusal", value = "拒绝原因", dataType = "String", paramType = "query"),
+                        @ApiImplicitParam(name = "userPhone", value = "用户手机号", dataType = "String", paramType = "query"),
+                        @ApiImplicitParam(name = "name", value = "套餐名称", dataType = "String", paramType = "query"),
+                        @ApiImplicitParam(name = "storeTel", value = "门店电话", dataType = "String", paramType = "query"),
+                        @ApiImplicitParam(name = "orderNo", value = "订单号", dataType = "String", paramType = "query"),
+                        @ApiImplicitParam(name = "orderMoney", value = "订单金额", dataType = "String", paramType = "query"),
+                        @ApiImplicitParam(name = "advancePaymentStatus", value = "预付款审核状态", dataType = "String", paramType = "query")
+    })
+    @GetMapping("/getAdvancePaymentReview")
+    public R <Map<String,String>> getAdvancePaymentReview(Integer id, String reasonRefusal, String userPhone, String name, String storeTel, String orderNo, String orderMoney, String advancePaymentStatus) {
+        log.info("LifeUserExpertController.getViewDetails?Id={},reasonRefusal{},userPhone{},name{},orderNo{},orderMoney{},advancePaymentStatus{}",id,reasonRefusal,userPhone,name,orderNo,orderMoney,advancePaymentStatus);
+        return R.data(lifeUserExpertService.getAdvancePaymentReview(id, reasonRefusal, userPhone, name,storeTel,orderNo,orderMoney,advancePaymentStatus));
+    }
+
+    @ApiOperation("达人尾款列表")
+    @ApiOperationSupport(order = 13)
+    @ApiImplicitParams({@ApiImplicitParam(name = "page", value = "分页页数", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "size", value = "分页条数", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "realName", value = "真实姓名", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "userPhone", value = "联系电话", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "endFundsButton", value = "申请尾款按钮状态(审核状态)", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "orderCreatedTime", value = "下单开始时间", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "orderEndTime", value = "下单结束时间", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "orderCreatedTime", value = "支付开始时间", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "orderEndTime", value = "支付结束时间", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "firstCompleteTime", value = "开始完成时间", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "endCompleteTime", value = "结束完成时间", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "createdEndPaymentTime", value = "开始申请时间", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "endEndPaymentTime", value = "结束申请时间", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "name", value = "套餐名称", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "orderNo", value = "订单编号", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "storeName", value = "商家昵称", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "userId", value = "用户id", dataType = "String", paramType = "query")
+    })
+    @GetMapping("/getFinalPaymentList")
+    public R<IPage<LifeUserExpertOrderVo>> getFinalPaymentList( Integer page, Integer size,String realName, String userPhone, String advancePaymentStatus, String orderCreatedTime, String orderEndTime ,String firstCompleteTime,String endCompleteTime,String createdEndPaymentTime,String endEndPaymentTime,String name, Integer userId) {
+        log.info("LifeUserExpertController.getViewDetails?userId={}",userId);
+        return R.data(lifeUserExpertService.getFinalPaymentList(page, size, realName, userPhone, advancePaymentStatus, orderCreatedTime, orderEndTime, firstCompleteTime,endCompleteTime,createdEndPaymentTime,endEndPaymentTime,name, userId));
+    }
+
+    @ApiOperation("达人尾款审核接口")
+    @ApiOperationSupport(order = 14)
+    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "达人订单表id", dataType = "Integer", paramType = "query",required = true),
+            @ApiImplicitParam(name = "endPaymentRefusal", value = "尾款拒绝原因", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "userPhone", value = "用户手机号", dataType = "String", paramType = "query",readOnly = true),
+            @ApiImplicitParam(name = "name", value = "套餐名称", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "storeTel", value = "门店电话", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "orderNo", value = "订单号", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "orderMoney", value = "订单金额", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "endFundsButton", value = "申请尾款状态", dataType = "String", paramType = "query", required = true)
+    })
+    @GetMapping("/getFinalPaymentReview")
+    public R <Map<String,String>> getFinalPaymentReview(Integer id, String endPaymentRefusal, String userPhone, String name, String storeTel, String orderNo, String orderMoney, String endFundsButton) {
+        log.info("LifeUserExpertController.getViewDetails?Id={},endPaymentRefusal{},userPhone{},name{},orderNo{},orderMoney{},endFundsButton{}",id,endPaymentRefusal,userPhone,name,orderNo,orderMoney,endFundsButton);
+        return R.data(lifeUserExpertService.getFinalPaymentReview(id, endPaymentRefusal, userPhone, name,storeTel,orderNo,orderMoney,endFundsButton));
+    }
 }

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

@@ -1,5 +1,6 @@
 package shop.alien.store.controller;
 
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiOperationSupport;
@@ -42,9 +43,9 @@ public class LifeUserExpertOrderController {
     @ApiOperation("推广订单信息列表")
     @ApiOperationSupport(order = 2)
     @GetMapping("/getPromotionOrderInfoList")
-    public R<List<LifeUserExpertOrderVo>> getPromotionOrderInfoList(@RequestParam("expertId") Long expertId) {
-        log.info("StoreUserExpertOrderController.getPromotionOrderInfoList?id={}", expertId);
-        return R.data(lifeUserExpertOrderService.getPromotionOrderInfoList(expertId));
+    public R<IPage<LifeUserExpertOrderVo>> getPromotionOrderInfoList(@RequestParam("expertId") Long expertId,@RequestParam(defaultValue = "1") int page, @RequestParam(defaultValue = "10") int size){
+        log.info("StoreUserExpertOrderController.getPromotionOrderInfoList?id={},page={},size={}", expertId, page, size);
+        return R.data(lifeUserExpertOrderService.getPromotionOrderInfoList(expertId,page, size));
     }
 
     @ApiOperation("达人订单详情")
@@ -54,4 +55,15 @@ public class LifeUserExpertOrderController {
         log.info("LifeUserExpertController.fetchExpertOrderInfo?expertId={},orderId={}", expertId, orderId);
         return R.data(lifeUserExpertOrderService.fetchExpertOrderInfo(expertId, orderId));
     }
+
+    @ApiOperation("申请款项按钮")
+    @ApiOperationSupport(order = 4)
+    @GetMapping("/getApplicationFunds")
+    public R<Map<String, Object>> getApplicationFunds( @RequestParam("buttonType") String buttonType,@RequestParam("buttonStatus") String buttonStatus,@RequestParam("orderNo") String orderNo,@RequestParam("userPhone") String userPhone) {
+        log.info("LifeUserExpertController.getApplicationFunds?buttonType={},buttonStatus={},orderNo={},userPhone={}", buttonType, buttonStatus,orderNo, userPhone);
+        return R.data(lifeUserExpertOrderService.getApplicationFunds(buttonType, buttonStatus, orderNo,userPhone));
+    }
+
+
+
 }

+ 0 - 23
alien-store/src/main/java/shop/alien/store/controller/LifeUserOrderController.java

@@ -4,7 +4,6 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import io.swagger.annotations.*;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.collections4.map.HashedMap;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.format.annotation.DateTimeFormat;
 import org.springframework.web.bind.annotation.*;
@@ -13,8 +12,6 @@ import shop.alien.entity.store.LifeRefundOrder;
 import shop.alien.entity.store.dto.LifeUserOrderDto;
 import shop.alien.entity.store.vo.LifeUserOrderVo;
 import shop.alien.store.service.LifeUserOrderService;
-import shop.alien.util.common.AlipayTradeAppPay;
-import shop.alien.util.common.UniqueRandomNumGenerator;
 
 import java.util.Map;
 
@@ -28,26 +25,6 @@ public class LifeUserOrderController {
 
     private final LifeUserOrderService lifeUserOrderService;
 
-    @ApiOperation("获取支付信息")
-    @ApiOperationSupport(order = 1)
-    @ApiImplicitParams({@ApiImplicitParam(name = "payPrice", value = "payPrice", dataType = "String", paramType = "query"),
-            @ApiImplicitParam(name = "quanName", value = "quanName", dataType = "String", paramType = "query")})
-    @GetMapping("/getOrderStrForPay")
-    public R<Map<String, Object>> getOrderStrForPay(@RequestParam("payPrice") String payPrice,
-                                                    @RequestParam("quanName") String quanName) {
-        log.info("LifeUserStoreController.getOrderStrForPay?payPrice={},quanName={}", payPrice, quanName);
-        String orderNo = UniqueRandomNumGenerator.generateUniqueCode(19);
-        String orderStr = AlipayTradeAppPay.executeAlipayPayment(orderNo, payPrice, quanName);
-        if (!orderStr.equals("调用失败") && !orderStr.isEmpty()) {
-            Map<String, Object> returnMap = new HashedMap<>();
-            returnMap.put("orderStr", orderStr);
-            returnMap.put("orderNo", orderNo);
-            return R.data(returnMap);
-        } else {
-            return R.fail("支付失败");
-        }
-    }
-
 
     @ApiOperation("创建订单")
     @ApiOperationSupport(order = 2)

+ 10 - 0
alien-store/src/main/java/shop/alien/store/controller/ManagementInfoController.java

@@ -91,6 +91,16 @@ public class ManagementInfoController {
         return R.data(managementInfoService.getApplicationForWithdrawal(page, size, storeId, storeName));
     }
 
+    @ApiOperation("提现申请详情")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "提现申请id", dataType = "Integer", paramType = "query")
+    })
+    @GetMapping("/getCashOutDetail")
+    public R<ManagementInfoVo> getCashOutDetail(
+            @RequestParam(value = "id") Integer id) {
+        return R.data(managementInfoService.getCashOutDetail(id));
+    }
+
     @ApiOperation("生成结算回执单")
     @ApiImplicitParams({
             @ApiImplicitParam(name = "cashId", value = "提现记录id", dataType = "String", paramType = "query"),

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

@@ -6,13 +6,13 @@ import io.swagger.annotations.*;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.http.ResponseEntity;
-import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartRequest;
 import shop.alien.entity.result.R;
 import shop.alien.entity.store.*;
 import shop.alien.entity.store.dto.StoreInfoDto;
 import shop.alien.entity.store.vo.*;
+import shop.alien.mapper.StoreCommentSummaryInterestMapper;
 import shop.alien.mapper.StoreImgMapper;
 import shop.alien.mapper.TagsMainMapper;
 import shop.alien.mapper.WebAuditMapper;
@@ -46,6 +46,8 @@ public class StoreInfoController {
 
     private final WebAuditMapper webAuditMapper;
 
+    private final StoreCommentSummaryInterestMapper storeCommentSummaryInterestMapper;
+
     @ApiOperation("获取所有门店")
     @ApiOperationSupport(order = 1)
     @GetMapping("/getAll")
@@ -741,4 +743,15 @@ public class StoreInfoController {
         return R.data(voList);
     }
 
+    @ApiOperation(value = "AI服务-门店趣味信息")
+    @GetMapping("/getStoreInterestInfo")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店id", dataType = "int", paramType = "query")
+    })
+    public R<List<StoreCommentSummaryInterest>> getStoreInterestInfo(int storeId) {
+        log.info("StoreInfoController.getStoreInterestInfo?storeId={}", storeId);
+        List<StoreCommentSummaryInterest> list = storeCommentSummaryInterestMapper.selectList(new LambdaQueryWrapper<StoreCommentSummaryInterest>().eq(StoreCommentSummaryInterest :: getStoreId, storeId));
+        return R.data(list);
+    }
+
 }

+ 16 - 0
alien-store/src/main/java/shop/alien/store/controller/StoreUserExpertController.java

@@ -7,6 +7,8 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.*;
 import shop.alien.entity.result.R;
+import shop.alien.entity.store.ExpertImg;
+import shop.alien.entity.store.vo.ExpertImgVo;
 import shop.alien.entity.store.vo.LifeUserExpertVo;
 import shop.alien.store.service.StoreUserExpertService;
 
@@ -50,4 +52,18 @@ public class StoreUserExpertController {
         log.info("StoreUserExpertController.getExpertDetails?expertId={}", expertId);
         return R.data(storeUserExpertService.getExpertDetails(expertId));
     }
+
+@ApiOperation("申请达人,上传图片以及补充说明")
+@ApiOperationSupport(order = 4)
+@PostMapping("/applyExpert")
+public R<Map<String, String>> applyExpert(@RequestBody ExpertImgVo expertImgs) {
+    log.info("StoreUserExpertController.applyExpert?expertImgs={}", expertImgs);
+    if (null == expertImgs) {
+        return R.fail("参数错误");
+    }
+    return R.data(storeUserExpertService.getapplyExpert(expertImgs));
+}
+
+
+
 }

+ 36 - 0
alien-store/src/main/java/shop/alien/store/feign/SecondServiceFeign.java

@@ -0,0 +1,36 @@
+package shop.alien.store.feign;
+
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@FeignClient(name = "alien-second", url = "${feign.alienSecond.url}")
+public interface SecondServiceFeign {
+    
+    /**
+     * 记录风控数据
+     *
+     * @param userId     用户ID
+     * @param ruleType   规则类型 1:洗钱嫌疑 2:账号异常 3:交易欺诈 4:异常发布
+     * @param ruleName   规则名称
+     * @param businessId 业务ID
+     * @param detailInfo 详细信息(JSON格式)
+     */
+    @PostMapping("/riskControl/record")
+    void recordRiskControlData(@RequestParam("userId") Integer userId,
+                               @RequestParam("ruleType") Integer ruleType,
+                               @RequestParam("ruleName") String ruleName,
+                               @RequestParam("businessId") String businessId,
+                               @RequestParam("detailInfo") String detailInfo);
+
+    /**
+     * 用户积分数据
+     *
+     * @param userId     用户ID
+     * @param initialPoints   用户积分
+     */
+    @PostMapping("/userPoints/create")
+    void createPointsRecord(@RequestParam("userId") Integer userId,
+                            @RequestParam("initialPoints") Integer initialPoints,
+                            @RequestParam("pointsType") Integer pointsType);
+}

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

@@ -31,6 +31,7 @@ public class LifeDictService {
         QueryWrapper<StoreDictionary> queryWrapper = new QueryWrapper<>();
         queryWrapper.eq(StringUtils.isNotEmpty(typeName), "type_name", typeName);
         queryWrapper.lambda().isNull(StoreDictionary::getParentId);
+        queryWrapper.orderByAsc("dict_id");
         List<StoreDictionary> storeDictionaries = StoreDictionaryMapper.selectList(queryWrapper);
         //转Vo,并且查询子集数据
         for (StoreDictionary storeDictionary : storeDictionaries) {

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

@@ -1,5 +1,6 @@
 package shop.alien.store.service;
 
+import cn.hutool.core.date.DateTime;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@@ -13,12 +14,20 @@ import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
+import shop.alien.entity.result.R;
 import shop.alien.entity.store.*;
 import shop.alien.entity.store.vo.LifePinglunVo;
 import shop.alien.entity.store.vo.LifeUserDynamicsVo;
+import shop.alien.entity.store.vo.LifeUserOrderVo;
 import shop.alien.entity.store.vo.StoreCommentVo;
 import shop.alien.mapper.*;
 
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -53,6 +62,16 @@ public class LifeUserDynamicsService extends ServiceImpl<LifeUserDynamicsMapper,
 
     private final StoreInfoMapper storeInfoMapper;
 
+    private final LifeUserExpertOrderMapper lifeUserExpertOrderMapper;
+
+    private final PromotionPackageService promotionPackageService;
+
+    private final LifeBrowseRecordMapper lifeBrowseRecordMapper;
+
+    @Resource
+    LifeBrowseRecordService lifeBrowseRecordService;
+
+
     public int addLiulanCount(String id) {
         LambdaUpdateWrapper<LifeUserDynamics> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
         lambdaUpdateWrapper.eq(LifeUserDynamics::getId, id);
@@ -60,14 +79,15 @@ public class LifeUserDynamicsService extends ServiceImpl<LifeUserDynamicsMapper,
         return lifeUserDynamicsMapper.update(null, lambdaUpdateWrapper);
     }
 
+
     public int setTopStatus(LifeUserDynamicsVo lifeUserDynamicsVo) {
-        if(!StringUtils.isEmpty(lifeUserDynamicsVo.getId()) && !StringUtils.isEmpty(lifeUserDynamicsVo.getTopStatus())){
+        if (!StringUtils.isEmpty(lifeUserDynamicsVo.getId()) && !StringUtils.isEmpty(lifeUserDynamicsVo.getTopStatus())) {
             LambdaUpdateWrapper<LifeUserDynamics> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
             lambdaUpdateWrapper.eq(LifeUserDynamics::getId, lifeUserDynamicsVo.getId());
             lambdaUpdateWrapper.set(LifeUserDynamics::getTopStatus, lifeUserDynamicsVo.getTopStatus());
-            if(lifeUserDynamicsVo.getTopStatus() == 0){
+            if (lifeUserDynamicsVo.getTopStatus() == 0) {
                 lambdaUpdateWrapper.set(LifeUserDynamics::getTopTime, null);
-            } else{
+            } else {
                 lambdaUpdateWrapper.set(LifeUserDynamics::getTopTime, new Date());
 
             }
@@ -78,7 +98,7 @@ public class LifeUserDynamicsService extends ServiceImpl<LifeUserDynamicsMapper,
     }
 
     public int enableStatus(LifeUserDynamicsVo lifeUserDynamicsVo) {
-        if(!StringUtils.isEmpty(lifeUserDynamicsVo.getId()) && !StringUtils.isEmpty(lifeUserDynamicsVo.getEnableStatus())) {
+        if (!StringUtils.isEmpty(lifeUserDynamicsVo.getId()) && !StringUtils.isEmpty(lifeUserDynamicsVo.getEnableStatus())) {
             LambdaUpdateWrapper<LifeUserDynamics> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
             lambdaUpdateWrapper.eq(LifeUserDynamics::getId, lifeUserDynamicsVo.getId());
             lambdaUpdateWrapper.set(LifeUserDynamics::getEnableStatus, lifeUserDynamicsVo.getEnableStatus());
@@ -97,7 +117,7 @@ public class LifeUserDynamicsService extends ServiceImpl<LifeUserDynamicsMapper,
             //如果发布,则将创建时间修改为当前时间
             LifeUserDynamics lifeUserDynamics = lifeUserDynamicsMapper.selectById(store.getId());
             int draft = lifeUserDynamics.getDraft();
-            if(draft == 1 && store.getDraft() == 0){
+            if (draft == 1 && store.getDraft() == 0) {
                 store.setCreatedTime(new Date());
             }
             return lifeUserDynamicsMapper.updateById(store);
@@ -486,11 +506,11 @@ public class LifeUserDynamicsService extends ServiceImpl<LifeUserDynamicsMapper,
 
     public List<LifeUserDynamicsVo> getDianZanList(String phoneId) {
         List<LifeUserDynamicsVo> lifeUserDynamicsVos = lifeUserDynamicsMapper.selectDianZanList(phoneId);
-        if (!CollectionUtils.isEmpty(lifeUserDynamicsVos)){
+        if (!CollectionUtils.isEmpty(lifeUserDynamicsVos)) {
             for (LifeUserDynamicsVo lifeUserDynamicsVo : lifeUserDynamicsVos) {
-                if (lifeUserDynamicsVo.getType().equals("2")){
+                if (lifeUserDynamicsVo.getType().equals("2")) {
                     String phoneIdNew = lifeUserDynamicsVo.getPhoneId().substring(6);
-                     StoreInfo storeInfo=storeInfoMapper.getStoreNameByPhone(phoneIdNew);
+                    StoreInfo storeInfo = storeInfoMapper.getStoreNameByPhone(phoneIdNew);
                     lifeUserDynamicsVo.setStoreName(storeInfo.getStoreName());
                 } else if (lifeUserDynamicsVo.getType().equals("1")) {
                     String phoneIdNew = lifeUserDynamicsVo.getPhoneId().substring(5);
@@ -500,7 +520,7 @@ public class LifeUserDynamicsService extends ServiceImpl<LifeUserDynamicsMapper,
                 }
             }
         }
-        return  lifeUserDynamicsVos;
+        return lifeUserDynamicsVos;
     }
 
     public List<LifeUserDynamicsVo> getDynamicsList(Integer page, Integer size, String nickName, String userType, Integer dynamicsType, String releaseStartTime, String releaseEndTime) {
@@ -512,14 +532,83 @@ public class LifeUserDynamicsService extends ServiceImpl<LifeUserDynamicsMapper,
         // 查询动态数据并按类型过滤
         LifeUserDynamicsVo lifeUserDynamicsVo = new LifeUserDynamicsVo();
         List<LifeUserDynamicsVo> lifeUserDynamicsVoList = lifeUserDynamicsMapper.getDynamicsDetail(id);
-        if(!CollectionUtils.isEmpty(lifeUserDynamicsVoList)){
+        if (!CollectionUtils.isEmpty(lifeUserDynamicsVoList)) {
+            lifeUserDynamicsVo = lifeUserDynamicsVoList.get(0);
+            String imagePath = lifeUserDynamicsVo.getImagePath();
+            if (!StringUtils.isEmpty(imagePath)) {
+                List<String> imagePathList = Arrays.asList(imagePath.split(","));
+                lifeUserDynamicsVo.setImagePathList(imagePathList);
+            }
+        }
+        return lifeUserDynamicsVo;
+    }
+
+    public LifeUserDynamicsVo getExpertDynamicsDetail(Integer id) {
+        // 查询动态数据并按类型过滤
+        LifeUserDynamicsVo lifeUserDynamicsVo = new LifeUserDynamicsVo();
+        List<LifeUserDynamicsVo> lifeUserDynamicsVoList = lifeUserDynamicsMapper.getExpertDynamicsDetail(id);
+        if (!CollectionUtils.isEmpty(lifeUserDynamicsVoList)) {
             lifeUserDynamicsVo = lifeUserDynamicsVoList.get(0);
             String imagePath = lifeUserDynamicsVo.getImagePath();
-            if(!StringUtils.isEmpty(imagePath)){
+            if (!StringUtils.isEmpty(imagePath)) {
                 List<String> imagePathList = Arrays.asList(imagePath.split(","));
                 lifeUserDynamicsVo.setImagePathList(imagePathList);
             }
+            //查询动态表中的 gvm和评论数是否满足当前达人订单规定值 都满足修改订单状态为已完成
+            LifeUserExpertOrder lifeUserExpertOrder = lifeUserExpertOrderMapper.selectOne(new LambdaQueryWrapper<LifeUserExpertOrder>().eq(LifeUserExpertOrder::getId, lifeUserDynamicsVo.getBusinessId()));
+            if (lifeUserExpertOrder != null && lifeUserExpertOrder.getStatus() != 2) {
+                  int liulanNum = lifeBrowseRecordMapper.selectCount(new LambdaQueryWrapper<LifeBrowseRecord>().eq(LifeBrowseRecord :: getDynamicsId, id).eq(LifeBrowseRecord :: getOrderId, lifeUserDynamicsVo.getBusinessId()));
+                if (lifeUserDynamicsVo.getOrderGmv().compareTo(lifeUserExpertOrder.getOrderGmv()) >= 0 && liulanNum >= lifeUserExpertOrder.getOrderPlayCount()) {
+                    lifeUserExpertOrder.setStatus(2);
+                    lifeUserExpertOrderMapper.updateById(lifeUserExpertOrder);
+                }
+            }
+
         }
         return lifeUserDynamicsVo;
     }
+
+    public R countGvm(Integer dynamicsId, String finalPrice) {
+        LifeUserDynamics lifeUserDynamics = lifeUserDynamicsMapper.selectOne(new LambdaQueryWrapper<LifeUserDynamics>().eq(LifeUserDynamics::getId, dynamicsId));
+        if (lifeUserDynamics != null) {
+            BigDecimal price = new BigDecimal(finalPrice);
+            lifeUserDynamics.setOrderGmv(lifeUserDynamics.getOrderGmv().add(price));
+            lifeUserDynamicsMapper.updateById(lifeUserDynamics);
+        }
+        LifeUserExpertOrder lifeUserExpertOrder = lifeUserExpertOrderMapper.selectOne(new LambdaQueryWrapper<LifeUserExpertOrder>().eq(LifeUserExpertOrder::getId, lifeUserDynamics.getBusinessId()));
+        if (lifeUserExpertOrder != null && lifeUserExpertOrder.getStatus() != 2) {
+            LifeUserDynamics lifeUserDynamics1 = lifeUserDynamicsMapper.selectOne(new LambdaQueryWrapper<LifeUserDynamics>().eq(LifeUserDynamics::getId, dynamicsId));
+            int liulanNum = lifeBrowseRecordMapper.selectCount(new LambdaQueryWrapper<LifeBrowseRecord>().eq(LifeBrowseRecord :: getDynamicsId, dynamicsId).eq(LifeBrowseRecord :: getOrderId, lifeUserDynamics1.getBusinessId()));
+            if (lifeUserDynamics1.getOrderGmv().compareTo(lifeUserExpertOrder.getOrderGmv()) >= 0 && liulanNum >= lifeUserExpertOrder.getOrderPlayCount()) {
+                lifeUserExpertOrder.setStatus(2);
+                lifeUserExpertOrderMapper.updateById(lifeUserExpertOrder);
+            }
+        }
+        return R.success("请求成功");
+    }
+
+    public boolean addUserStoreBrowseNumber(LifeBrowseRecord lifeBrowseRecord) {
+        // 获取当天开始时间(00:00:00)
+        LocalDateTime todayStart = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
+        // 获取当天结束时间(23:59:59.999)
+        LocalDateTime todayEnd = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
+        LifeBrowseRecord selectOne = lifeBrowseRecordMapper.selectOne(new LambdaQueryWrapper<LifeBrowseRecord>().eq(LifeBrowseRecord::getUserId, lifeBrowseRecord.getUserId())
+                .between(LifeBrowseRecord::getLiulanTime, todayStart, todayEnd).in(LifeBrowseRecord::getDeleteFlag, 0, 1).eq(LifeBrowseRecord::getDynamicsId, lifeBrowseRecord.getDynamicsId())
+                .eq(LifeBrowseRecord::getOrderId, lifeBrowseRecord.getOrderId()));
+        if (selectOne == null) {
+            lifeBrowseRecord.setCreatedTime(new DateTime());
+            lifeBrowseRecord.setLiulanTime(new DateTime());
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+            lifeBrowseRecord.setLiulanDate(sdf.format(new Date()));
+            lifeBrowseRecordMapper.insert(lifeBrowseRecord);
+            //查询当前动态浏记录数
+            int liulanNum = lifeBrowseRecordMapper.selectCount(new LambdaQueryWrapper<LifeBrowseRecord>().eq(LifeBrowseRecord :: getDynamicsId, lifeBrowseRecord.getDynamicsId())
+                    .eq(LifeBrowseRecord :: getOrderId, lifeBrowseRecord.getOrderId()).in(LifeBrowseRecord :: getDeleteFlag, 0, 1));
+            LambdaUpdateWrapper<LifeUserDynamics> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
+            lambdaUpdateWrapper.eq(LifeUserDynamics :: getId, lifeBrowseRecord.getDynamicsId());
+            lambdaUpdateWrapper.set(LifeUserDynamics :: getStoreCount, liulanNum);
+            lifeUserDynamicsMapper.update(null,lambdaUpdateWrapper);
+        }
+        return true;
+    }
 }

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

@@ -22,9 +22,11 @@ public interface LifeUserExpertOrderService extends IService<LifeUserExpertOrder
 
     List<LifeUserExpertOrderVo> getExpertOrderDetails(Long expertId);
 
-    List<LifeUserExpertOrderVo> getPromotionOrderInfoList(Long expertId);
+    IPage<LifeUserExpertOrderVo> getPromotionOrderInfoList(Long expertId, int page, int size);
 
     List<Map<String, Object>> fetchExpertOrderInfo(Long expertId, String orderId);
 
     List<LifeUserExpertOrderVo> getTalentPromotionOrder(String orderId, String expertId);
+
+    Map<String, Object> getApplicationFunds(String buttonType, String buttonStatus ,String orderNo,String userPhone);
 }

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

@@ -2,12 +2,15 @@ package shop.alien.store.service;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
+import lombok.Data;
+import shop.alien.entity.result.R;
 import shop.alien.entity.store.LifeUserExpert;
 import shop.alien.entity.store.vo.ExpertGoodsTypeVo;
 import shop.alien.entity.store.vo.LifeUserExpertOrderVo;
 import shop.alien.entity.store.vo.LifeUserExpertVo;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * <p>
@@ -23,7 +26,7 @@ public interface LifeUserExpertService extends IService<LifeUserExpert> {
 
     IPage<LifeUserExpertOrderVo> getExpertOrderList(int page, int size, Integer expertId, String orderNo, String storeName, Integer storeId);
 
-    boolean becomeExpert(Integer userId, String expertType);
+    boolean becomeExpert(Integer id,  String userPhone, String comment, Integer expertStatus ,Integer commissionRate, Integer advanceRate);
 
     boolean cancelExpert(Integer id);
 
@@ -40,4 +43,16 @@ public interface LifeUserExpertService extends IService<LifeUserExpert> {
      * @return List<Map < String, Object>>
      */
     List<ExpertGoodsTypeVo> greatGoodsType(Integer expertId);
+
+    IPage<LifeUserExpertVo> getApplicationExpertList(Integer page, Integer size, String userName, String realName, String userPhone, Integer expertStatus, String createdTime, String endTime , Integer userId);
+
+    LifeUserExpertVo getViewDetails(Integer expertId);
+
+    IPage<LifeUserExpertOrderVo> getAdvancePaymentList(Integer page, Integer size,String realName, String userPhone, String advancePaymentStatus, String orderCreatedTime, String orderEndTime ,String name, Integer userId);
+
+    Map<String,String> getAdvancePaymentReview(Integer id,String reasonRefusal, String userPhone,String name,String storeTel,String orderNo, String orderMoney,String advancePaymentStatus);
+
+    IPage<LifeUserExpertOrderVo> getFinalPaymentList(Integer page, Integer size,String realName, String userPhone, String advancePaymentStatus, String orderCreatedTime, String orderEndTime ,String firstCompleteTime,String endCompleteTime,String createdEndPaymentTime,String endEndPaymentTime,String name, Integer userId);
+
+    Map<String,String> getFinalPaymentReview(Integer id, String endPaymentRefusal, String userPhone, String name, String storeTel, String orderNo, String orderMoney, String endFundsButton);
 }

+ 34 - 14
alien-store/src/main/java/shop/alien/store/service/LifeUserOrderService.java

@@ -14,7 +14,6 @@ import lombok.RequiredArgsConstructor;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
-import shop.alien.entity.result.BusinessException;
 import shop.alien.entity.result.R;
 import shop.alien.entity.store.*;
 import shop.alien.entity.store.dto.LifeUserOrderDto;
@@ -457,7 +456,7 @@ public class LifeUserOrderService extends ServiceImpl<LifeUserOrderMapper, LifeU
 
         // 更新的中间表id
         List<Integer> updateIds = orderCouponMiddles1.stream().limit(refundCouponAmount).map(x -> x.getId()).collect(Collectors.toList());
-        if (result.equals("调用失败")) {
+        if (!result.equals("调用成功")) {
             refundMessage = "编号为"+order.getOrderNo()+"的订单退款失败,请重新发起申请。";
             // TODO 退款失败目前不做处理
             /*orderCouponMiddleMapper.update(null,new UpdateWrapper<OrderCouponMiddle>().in("id",updateIds)
@@ -552,6 +551,16 @@ public class LifeUserOrderService extends ServiceImpl<LifeUserOrderMapper, LifeU
                 lifeCouponMapper.update(null, new LambdaUpdateWrapper<LifeCoupon>()
                         .setSql("single_qty=single_qty+" + refundCouponAmount)
                         .eq(LifeCoupon::getId, couponId));
+
+                //判断当前时间在开始时间start_date和结束时间end_date之间,并且库存single_qty大于0,则修改状态status为5
+                lifeCouponMapper.update(null, new LambdaUpdateWrapper<LifeCoupon>()
+                        .set(LifeCoupon::getStatus, 5)
+                        .eq(LifeCoupon::getId, couponId)
+                        .le(LifeCoupon::getStartDate, LocalDateTime.now())
+                        .ge(LifeCoupon::getEndDate, LocalDateTime.now())
+                        .gt(LifeCoupon::getSingleQty, 0));
+
+
             } else {
                 // 团购信息
                 lifeGroupBuyMainMapper.update(null, new LambdaUpdateWrapper<LifeGroupBuyMain>()
@@ -767,20 +776,31 @@ public class LifeUserOrderService extends ServiceImpl<LifeUserOrderMapper, LifeU
             orderCouponMiddleService.save(orderCouponMiddle);
         }
         //4. 代金券/团购库存扣除 coupon_type 1 代金券 2团购
-        int successful = 0;
-        if(lifeUserOrderDto.getCouponType() == 2){
-            // 团购库存扣除
-            successful = lifeGroupBuyMainMapper.update(null, new UpdateWrapper<LifeGroupBuyMain>()
-                    .eq("id", lifeUserOrderDto.getCouponId()).ge("inventory_num",lifeUserOrderDto.getCount()).setSql("inventory_num = inventory_num - " + lifeUserOrderDto.getCount()));
+        Map<String, Object> returnMap = new HashMap<>();
+        int soldOutStatus = CouponStatusEnum.SOLD_OUT.getCode();
+        int updateRows = 0;
+
+        if (lifeUserOrderDto.getCouponType() == 2) {
+            // 团购库存:原子扣减
+            updateRows = lifeGroupBuyMainMapper.deductInventoryAtomically(
+                    lifeUserOrderDto.getCouponId(),
+                    buyCount,
+                    soldOutStatus
+            );
         } else {
-            successful = lifeCouponMapper.update(null, new UpdateWrapper<LifeCoupon>()
-                    .eq("id", lifeUserOrderDto.getCouponId()).ge("single_qty",lifeUserOrderDto.getCount()).setSql("single_qty = single_qty - " + lifeUserOrderDto.getCount()));
+            // 代金券库存:原子扣减
+            updateRows = lifeCouponMapper.deductInventoryAtomically(
+                    lifeUserOrderDto.getCouponId(),
+                    buyCount,
+                    soldOutStatus
+            );
         }
-        if(successful == 0){
-            log.error("库存不足");
-            throw new BusinessException("库存不足");
+// 判断库存扣减结果
+        if (updateRows == 0) {
+            log.error("couponid:"+lifeUserOrderDto.getCouponId()+" 库存不足,当前购买数量:"+ buyCount);
+            // 手动抛出异常,触发事务回滚(回滚之前创建的订单和优惠券状态变更)
+            throw new RuntimeException("库存不足,下单失败");
         }
-        Map<String, Object> returnMap = new HashMap<>();
         returnMap.put("success", "下单成功");
         returnMap.put("orderNo", lifeUserOrderDto.getOrderNo());
         returnMap.put("lifeUserOrder", lifeUserOrder);
@@ -1031,7 +1051,7 @@ public class LifeUserOrderService extends ServiceImpl<LifeUserOrderMapper, LifeU
 //            lifeUserOrderQueryWrapper.inSql("luo.id", sql);
             lifeUserOrderQueryWrapper.eq("ocm.status",orderStatus);
         }
-        lifeUserOrderQueryWrapper.groupBy("tc.coupon_type","tc.coupon_id");
+        lifeUserOrderQueryWrapper.groupBy("luo.id");
         IPage<LifeUserOrderVo> lifeUserOrderVoIPage = lifeUserOrderMapper.queryUserOrderList(brandedPage, lifeUserOrderQueryWrapper);
 
         if (!"-1".equals(orderStatus)) {

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

@@ -15,17 +15,18 @@ import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
+import shop.alien.entity.result.R;
 import shop.alien.entity.store.LifeFans;
 import shop.alien.entity.store.LifeNotice;
 import shop.alien.entity.store.LifeUser;
 import shop.alien.entity.store.vo.LifeMessageVo;
 import shop.alien.entity.store.vo.LifeUserVo;
 import shop.alien.entity.store.vo.WebSocketVo;
-import shop.alien.store.config.BaseRedisService;
 import shop.alien.mapper.LifeFansMapper;
 import shop.alien.mapper.LifeMessageMapper;
 import shop.alien.mapper.LifeNoticeMapper;
 import shop.alien.mapper.LifeUserMapper;
+import shop.alien.store.config.BaseRedisService;
 import shop.alien.store.config.WebSocketProcess;
 import shop.alien.store.util.FunctionMagic;
 import shop.alien.util.common.JwtUtil;
@@ -301,4 +302,43 @@ public class LifeUserService extends ServiceImpl<LifeUserMapper, LifeUser> {
             log.error("LifeUserService webSocketProcess Stack={}", e);
         }
     }
+
+    public R havePayPassword(String userId, String password) {
+        LifeUser lifeUser = lifeUserMapper.selectById(userId);
+        HashMap<Object, Object> returnMap = new HashMap<>();
+        returnMap.put("code",200);
+        if (null == lifeUser) {
+            returnMap.put("message","未查询到用户");
+            returnMap.put("data","false");
+            return R.data(returnMap);
+        }
+        if( null == lifeUser.getPayPassword()){
+            returnMap.put("message","用户未设置支付密码");
+            returnMap.put("data","false");
+            return R.data(returnMap);
+        } else if(null != password){
+            if( !password.equals(lifeUser.getPayPassword())){
+                returnMap.put("message","密码错误");
+                returnMap.put("data","false");
+                return R.data(returnMap);
+            }
+        }
+        returnMap.put("data","true");
+        returnMap.put("message","用户已设置支付密码");
+        return R.data(returnMap);
+    }
+
+    /**
+     * 修改支付密码
+     *
+     * @param id          主键
+     * @param payPassword 支付密码
+     * @return boolean
+     */
+    public boolean setPayPassword(Integer id, String payPassword) {
+        LifeUser lifeUser = new LifeUser();
+        lifeUser.setId(id);
+        lifeUser.setPayPassword(payPassword);
+        return this.updateById(lifeUser);
+    }
 }

+ 57 - 12
alien-store/src/main/java/shop/alien/store/service/LifeUserStoreService.java

@@ -51,6 +51,8 @@ public class LifeUserStoreService {
 
     private final StoreClockInService storeClockInService;
 
+    private final StoreBusinessInfoMapper storeBusinessInfoMapper;
+
     /**
      * 门店列表
      *
@@ -80,7 +82,7 @@ public class LifeUserStoreService {
             // 过滤掉永久关门的店铺
             wrapper.ne("a.business_status", 99);
             // 根据构建的条件查询门店信息
-            List<StoreInfoVo> storeInfoVoList = storeInfoMapper.getStoreInfoVoList(wrapper);
+            List<StoreInfoVo> storeInfoVoList = storeInfoMapper.getStoreInfoVoListNew(wrapper,jingdu + "," + weidu);
             // 如果查询结果为空,则直接返回空列表
             if (storeInfoVoList.isEmpty()) {
                 return returnMaps;
@@ -105,9 +107,13 @@ public class LifeUserStoreService {
             List<Map<Integer, Integer>> storeClockInCountList = storeClockInService.getStoreClockInCount();
             // 遍历所有门店信息,构造返回结果
             for (StoreInfoVo store : storeInfoVoList) {
+
+                //门店营业时间信息
+                StoreBusinessInfo storeBusinessInfo = storeBusinessInfoMapper.selectOne(new QueryWrapper<StoreBusinessInfo>().eq("store_id", store.getId()).eq("delete_flag", 0).last("limit 1"));
+
                 Map<String, Object> storeMap = new HashMap<>();
                 // 如果用户提供了经纬度信息,则计算并添加门店到用户的距离
-                if ((jingdu != null && !jingdu.isEmpty()) && (weidu != null && !weidu.isEmpty())) {
+                /*if ((jingdu != null && !jingdu.isEmpty()) && (weidu != null && !weidu.isEmpty())) {
                     double storeJing = Double.parseDouble(store.getStorePosition().split(",")[0]);
                     double storeWei = Double.parseDouble(store.getStorePosition().split(",")[1]);
                     double storeDistance = DistanceUtil.haversineCalculateDistance(Double.parseDouble(jingdu), Double.parseDouble(weidu), storeJing, storeWei);
@@ -115,10 +121,15 @@ public class LifeUserStoreService {
                 } else {
                     // 否则,返回提示信息
                     storeMap.put("distance", "没有位置信息");
-                }
+                }*/
+                storeMap.put("distance", store.getDist());
                 // 添加门店的业务状态及其描述
                 storeMap.put("businessStatus", store.getBusinessStatus());
                 storeMap.put("businessStatusStr", store.getBusinessStatusStr());
+
+                //474bug
+                storeMap.put("businessTypesName", store.getBusinessTypesName());
+                storeMap.put("storeBusinessInfo", storeBusinessInfo);
                 // 添加门店ID
                 storeMap.put("storeId", store.getId());
                 // 如果存在评分数据,则添加评分、平均消费及评价总数
@@ -198,16 +209,37 @@ public class LifeUserStoreService {
             // 如果用户提供了距离阈值,则根据距离过滤结果,并按距离升序排序
             if (distance != null) {
                 double maxDistance = distance;
-                returnMaps = returnMaps.stream()
-                        .filter(storeMap -> {
-                            Object distanceObj = storeMap.get("distance");
-                            if (distanceObj instanceof String) {
-                                return false;
-                            }
-                            double distanceValue = (double) distanceObj;
-                            return distanceValue < maxDistance;
+                returnMaps = returnMaps.stream().filter(storeMap -> {
+                    Object distanceObj = storeMap.get("distance");
+                    if (distanceObj == null) {
+                        return false; // 排除 null
+                    }
+                    double distanceValue;
+                    try {
+                        // 先尝试直接转换为数值类型(如果本身是 Double/Integer 等)
+                        if (distanceObj instanceof Number) {
+                            distanceValue = ((Number) distanceObj).doubleValue();
+                        }
+                        // 再处理字符串类型(如 "100.5")
+                        else if (distanceObj instanceof String) {
+                            // 将字符串解析为 double(注意处理非数字格式的字符串)
+                            distanceValue = Double.parseDouble((String) distanceObj);
+                        }
+                        // 其他类型视为无效
+                        else {
+                            return false;
+                        }
+                    } catch (NumberFormatException e) {
+                        // 字符串无法解析为数字(如 "abc"),视为无效
+                        return false;
+                    }
+                    return distanceValue < maxDistance;
+                })
+                        .sorted((map1, map2) -> {
+                            double d1 = getDistanceValue(map1.get("distance"));
+                            double d2 = getDistanceValue(map2.get("distance"));
+                            return Double.compare(d1, d2);
                         })
-                        .sorted(Comparator.comparingDouble(storeMap -> (double) storeMap.get("distance")))
                         .collect(Collectors.toList());
             }
 
@@ -221,6 +253,19 @@ public class LifeUserStoreService {
             throw new RuntimeException(e);
         }
     }
+    // 提取一个工具方法,统一处理距离值的转换
+    private double getDistanceValue(Object distanceObj) {
+        if (distanceObj instanceof Number) {
+            return ((Number) distanceObj).doubleValue();
+        } else if (distanceObj instanceof String) {
+            try {
+                return Double.parseDouble((String) distanceObj);
+            } catch (NumberFormatException e) {
+                return Double.MAX_VALUE; // 无效值排序时放最后
+            }
+        }
+        return Double.MAX_VALUE;
+    }
 
     public Map<String, Object> getStoreDetailById(String storeId, String userId, String jingdu, String weidu) {
         Map<String, Object> returnMap = new HashMap<>();

+ 2 - 0
alien-store/src/main/java/shop/alien/store/service/ManagementInfoService.java

@@ -29,6 +29,8 @@ public interface ManagementInfoService {
      */
     IPage<ManagementInfoVo> getApplicationForWithdrawal(int pageNo, int pageSize, Integer storeId, String storeName);
 
+    ManagementInfoVo getCashOutDetail(Integer id);
+
     /**
      * 店铺明细账单统计
      */

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

@@ -1,5 +1,6 @@
 package shop.alien.store.service;
 
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
 import shop.alien.entity.store.LifePromotionPackage;
 import shop.alien.entity.store.vo.LifePromotionPackageVo;
@@ -9,7 +10,7 @@ import java.util.Map;
 
 public interface PromotionPackageService extends IService<LifePromotionPackage> {
 
-    List<LifePromotionPackageVo> getByExpertId(Long expertId);
+    IPage<LifePromotionPackageVo> getByExpertId(Long expertId, Integer page, Integer size);
 
     Map<String, Object> buyPromotion(LifePromotionPackageVo lifePromotionPackageVo);
 }

+ 15 - 0
alien-store/src/main/java/shop/alien/store/service/StoreAliPayErrorLogService.java

@@ -0,0 +1,15 @@
+package shop.alien.store.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import shop.alien.entity.store.StoreAliPayErrorLog;
+
+/**
+ * <p>
+ * 支付宝转账错误记录表 服务类
+ * </p>
+ *
+ * @author qxy
+ * @since 2025-10-27
+ */
+public interface StoreAliPayErrorLogService extends IService<StoreAliPayErrorLog> {
+}

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

@@ -1,7 +1,10 @@
 package shop.alien.store.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import shop.alien.entity.result.R;
+import shop.alien.entity.store.ExpertImg;
 import shop.alien.entity.store.LifeUserExpert;
+import shop.alien.entity.store.vo.ExpertImgVo;
 import shop.alien.entity.store.vo.LifeUserExpertVo;
 
 import java.util.List;
@@ -14,4 +17,7 @@ public interface StoreUserExpertService extends IService<LifeUserExpert> {
     List<Map<String, LifeUserExpertVo>> getExpertDetails(Integer expertId);
 
     List<LifeUserExpertVo> ifExpert(String id);
+
+
+    Map<String, String> getapplyExpert(ExpertImgVo expertImgs);
 }

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

@@ -132,12 +132,16 @@ public class LifeGroupBuyServiceImpl extends ServiceImpl<LifeGroupBuyMainMapper,
     @Override
     public IPage<LifeGroupBuyThaliVo> getThaliList(int page, int size, String storeId, String status, String groupName, String groupType) {
         QueryWrapper<LifeGroupBuyThaliVo> queryWrapper = new QueryWrapper<>();
-        queryWrapper.eq(StringUtils.isNotEmpty(storeId), "store_id", storeId)
-                .eq(StringUtils.isNotEmpty(status), "status", status)
-                .eq(StringUtils.isNotEmpty(groupType), "group_type", groupType)
-                .like(StringUtils.isNotEmpty(groupName), "group_name", groupName)
-                .eq("delete_flag", 0)
-                .orderByDesc("created_time");
+        queryWrapper.eq(StringUtils.isNotEmpty(storeId), "store_id", storeId);
+        if(status.equals("8")){
+            queryWrapper.in(StringUtils.isNotEmpty(status), "status", 2, 6);
+        }else{
+            queryWrapper.eq(StringUtils.isNotEmpty(status), "status", status);
+        }
+        queryWrapper.eq(StringUtils.isNotEmpty(groupType), "group_type", groupType);
+        queryWrapper.like(StringUtils.isNotEmpty(groupName), "group_name", groupName);
+        queryWrapper.eq("delete_flag", 0);
+        queryWrapper.orderByDesc("created_time");
         IPage<LifeGroupBuyThaliVo> lifeGroupBuyThaliVoIPage = new Page<>(page, size);
         IPage<LifeGroupBuyThaliVo> voIPage = lifeGroupBuyMainMapper.selectPageByThaliVo(lifeGroupBuyThaliVoIPage, queryWrapper);
         voIPage.getRecords().forEach(this::getMainImgAndDisableDate);
@@ -237,7 +241,15 @@ public class LifeGroupBuyServiceImpl extends ServiceImpl<LifeGroupBuyMainMapper,
                     List<EssentialHolidayComparison> essentialHolidayComparisons = essentialHolidayComparisonMapper.selectList(new LambdaQueryWrapper<EssentialHolidayComparison>().in(EssentialHolidayComparison::getId, list));
                     holiday = essentialHolidayComparisons.stream().map(EssentialHolidayComparison::getFestivalName).collect(Collectors.joining(","));
                 }
-                record.setDisableDateValueStr(valueList.get(0) + ";" + holiday);
+                if (StringUtils.isNotEmpty(valueList.get(0)) && StringUtils.isNotEmpty(holiday)) {
+                    record.setDisableDateValueStr(valueList.get(0) + ";" + holiday);
+                }
+                if (StringUtils.isEmpty(valueList.get(0))) {
+                    record.setDisableDateValueStr(holiday);
+                }
+                if (StringUtils.isEmpty(holiday)) {
+                    record.setDisableDateValueStr(valueList.get(0));
+                }
             }
         }
     }

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