From 991b53649b2c2f015118f6583429eee8f340ef4d Mon Sep 17 00:00:00 2001 From: owen Date: Sun, 3 Sep 2023 21:19:42 +0800 Subject: [PATCH 01/50] =?UTF-8?q?member:=20=E5=88=86=E9=94=80=E9=85=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../brokerage/BrokerageBindModeEnum.java | 44 +++++++++++++ .../BrokerageEnabledConditionEnum.java | 44 +++++++++++++ .../brokerage/BrokerageRecordBizTypeEnum.java | 46 ++++++++++++++ .../brokerage/BrokerageRecordStatusEnum.java | 39 ++++++++++++ .../BrokerageWithdrawStatusEnum.java | 41 ++++++++++++ .../brokerage/BrokerageWithdrawTypeEnum.java | 40 ++++++++++++ .../vo/config/MemberPointConfigBaseVO.java | 57 +++++++++++++++++ .../dataobject/point/MemberPointConfigDO.java | 62 ++++++++++++++++++- 8 files changed, 371 insertions(+), 2 deletions(-) create mode 100644 yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageBindModeEnum.java create mode 100644 yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageEnabledConditionEnum.java create mode 100644 yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageRecordBizTypeEnum.java create mode 100644 yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageRecordStatusEnum.java create mode 100644 yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageWithdrawStatusEnum.java create mode 100644 yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageWithdrawTypeEnum.java diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageBindModeEnum.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageBindModeEnum.java new file mode 100644 index 000000000..2ee7e891f --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageBindModeEnum.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.member.enums.brokerage; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 分销关系绑定模式枚举 + * + * @author owen + */ +@AllArgsConstructor +@Getter +public enum BrokerageBindModeEnum implements IntArrayValuable { + + /** + * 只要用户没有推广人,随时都可以绑定分销关系 + */ + ANYTIME(0, "没有推广人"), + /** + * 仅新用户注册时才能绑定推广关系 + */ + REGISTER(1, "新用户"), + ; + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageBindModeEnum::getMode).toArray(); + + /** + * 模式 + */ + private final Integer mode; + /** + * 名字 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageEnabledConditionEnum.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageEnabledConditionEnum.java new file mode 100644 index 000000000..5422b98b7 --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageEnabledConditionEnum.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.member.enums.brokerage; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 分佣模式枚举 + * + * @author owen + */ +@AllArgsConstructor +@Getter +public enum BrokerageEnabledConditionEnum implements IntArrayValuable { + + /** + * 所有用户都可以分销 + */ + ALL(0, "人人分销"), + /** + * 仅可后台手动设置推广员 + */ + ADMIN(1, "指定分销"), + ; + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageEnabledConditionEnum::getCondition).toArray(); + + /** + * 模式 + */ + private final Integer condition; + /** + * 名字 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageRecordBizTypeEnum.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageRecordBizTypeEnum.java new file mode 100644 index 000000000..d30758a88 --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageRecordBizTypeEnum.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.member.enums.brokerage; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 佣金记录业务类型枚举 + * + * @author owen + */ +@AllArgsConstructor +@Getter +public enum BrokerageRecordBizTypeEnum implements IntArrayValuable { + + ORDER(0, "获得推广佣金", "获得推广佣金 {}", true), + WITHDRAW(1, "提现申请", "提现申请扣除佣金 {}", false), + ; + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageRecordBizTypeEnum::getType).toArray(); + + /** + * 类型 + */ + private final Integer type; + /** + * 标题 + */ + private final String title; + /** + * 描述 + */ + private final String description; + /** + * 是否为增加佣金 + */ + private final boolean add; + + @Override + public int[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageRecordStatusEnum.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageRecordStatusEnum.java new file mode 100644 index 000000000..75ddc9e0a --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageRecordStatusEnum.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.member.enums.brokerage; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 佣金记录状态枚举 + * + * @author owen + */ +@AllArgsConstructor +@Getter +public enum BrokerageRecordStatusEnum implements IntArrayValuable { + + WAIT_SETTLEMENT(0, "待结算"), + SETTLEMENT(1, "已结算"), + CANCEL(2, "已取消"), + ; + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageRecordStatusEnum::getStatus).toArray(); + + /** + * 状态 + */ + private final Integer status; + /** + * 名字 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageWithdrawStatusEnum.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageWithdrawStatusEnum.java new file mode 100644 index 000000000..6d0232deb --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageWithdrawStatusEnum.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.member.enums.brokerage; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 佣金提现状态枚举 + * + * @author owen + */ +@AllArgsConstructor +@Getter +public enum BrokerageWithdrawStatusEnum implements IntArrayValuable { + + AUDITING(0, "审核中"), + AUDIT_SUCCESS(10, "审核通过"), + WITHDRAW_SUCCESS(11, "提现成功"), + AUDIT_FAIL(20, "审核不通过"), + WITHDRAW_FAIL(21, "提现失败"), + ; + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageWithdrawStatusEnum::getStatus).toArray(); + + /** + * 状态 + */ + private final Integer status; + /** + * 名字 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageWithdrawTypeEnum.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageWithdrawTypeEnum.java new file mode 100644 index 000000000..21d0712b9 --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageWithdrawTypeEnum.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.member.enums.brokerage; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 佣金提现类型枚举 + * + * @author owen + */ +@AllArgsConstructor +@Getter +public enum BrokerageWithdrawTypeEnum implements IntArrayValuable { + + WALLET(1, "钱包"), + BANK(2, "银行卡"), + WECHAT(3, "微信"), + ALIPAY(4, "支付宝"), + ; + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageWithdrawTypeEnum::getType).toArray(); + + /** + * 类型 + */ + private final Integer type; + /** + * 名字 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/vo/config/MemberPointConfigBaseVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/vo/config/MemberPointConfigBaseVO.java index f946e4a27..acdadb6bc 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/vo/config/MemberPointConfigBaseVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/vo/config/MemberPointConfigBaseVO.java @@ -1,9 +1,17 @@ package cn.iocoder.yudao.module.member.controller.admin.point.vo.config; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageBindModeEnum; +import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageEnabledConditionEnum; +import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageWithdrawTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.hibernate.validator.constraints.Range; +import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; +import javax.validation.constraints.PositiveOrZero; +import java.util.List; /** * 会员积分配置 Base VO,提供给添加、修改、详细的子 VO 使用 @@ -28,4 +36,53 @@ public class MemberPointConfigBaseVO { @NotNull(message = "1 元赠送积分不能为空") private Integer tradeGivePoint; + // ========== 分销相关 ========== + + @Schema(description = "是否启用分佣", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "是否启用分佣不能为空") + private Boolean brokerageEnabled; + + @Schema(description = "分佣模式", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "分佣模式不能为空") + @InEnum(value = BrokerageEnabledConditionEnum.class, message = "分佣模式必须是 {value}") + private Integer brokerageEnabledCondition; + + @Schema(description = "分销关系绑定模式", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "分销关系绑定模式不能为空") + @InEnum(value = BrokerageBindModeEnum.class, message = "分销关系绑定模式必须是 {value}") + private Integer brokerageBindMode; + + @Schema(description = "分销海报图地址数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/yudao.jpg]") + private List brokeragePostUrls; + + @Schema(description = "一级返佣比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") + @NotNull(message = "一级返佣比例不能为空") + @Range(min = 0, max = 100, message = "一级返佣比例必须在 0 - 100 之间") + private Integer brokerageFirstPercent; + + @Schema(description = "二级返佣比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") + @NotNull(message = "二级返佣比例不能为空") + @Range(min = 0, max = 100, message = "二级返佣比例必须在 0 - 100 之间") + private Integer brokerageSecondPercent; + + @Schema(description = "用户提现最低金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") + @NotNull(message = "用户提现最低金额不能为空") + @PositiveOrZero(message = "用户提现最低金额不能是负数") + private Integer brokerageWithdrawMinPrice; + + @Schema(description = "提现银行", requiredMode = Schema.RequiredMode.REQUIRED, example = "[0, 1]") + @NotEmpty(message = "提现银行不能为空") + private List brokerageBankNames; + + @Schema(description = "佣金冻结时间(天)", requiredMode = Schema.RequiredMode.REQUIRED, example = "7") + @NotNull(message = "佣金冻结时间(天)不能为空") + @PositiveOrZero(message = "佣金冻结时间不能是负数") + private Integer brokerageFrozenDays; + + @Schema(description = "提现方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "[0, 1]") + @NotNull(message = "提现方式不能为空") + @InEnum(value = BrokerageWithdrawTypeEnum.class, message = "提现方式必须是 {value}") + private List brokerageWithdrawType; + + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/point/MemberPointConfigDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/point/MemberPointConfigDO.java index 94fed9c53..8f44bd948 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/point/MemberPointConfigDO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/point/MemberPointConfigDO.java @@ -1,19 +1,25 @@ package cn.iocoder.yudao.module.member.dal.dataobject.point; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.framework.mybatis.core.type.IntegerListTypeHandler; +import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageBindModeEnum; +import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageEnabledConditionEnum; +import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageWithdrawTypeEnum; import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import lombok.*; -import java.math.BigDecimal; +import java.util.List; /** * 会员积分配置 DO * * @author QingX */ -@TableName("member_point_config") +@TableName(value = "member_point_config", autoResultMap = true) @KeySequence("member_point_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 @Data @EqualsAndHashCode(callSuper = true) @@ -47,4 +53,56 @@ public class MemberPointConfigDO extends BaseDO { */ private Integer tradeGivePoint; + // ========== 分销相关 ========== + + /** + * 是否启用分佣 + */ + private Boolean brokerageEnabled; + /** + * 分佣模式 + * + * 枚举 {@link BrokerageEnabledConditionEnum 对应的类} + */ + private Integer brokerageEnabledCondition; + /** + * 分销关系绑定模式 + * + * 枚举 {@link BrokerageBindModeEnum 对应的类} + */ + private Integer brokerageBindMode; + /** + * 分销海报图地址数组 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List brokeragePostUrls; + /** + * 一级返佣比例 + */ + private Integer brokerageFirstPercent; + /** + * 二级返佣比例 + */ + private Integer brokerageSecondPercent; + /** + * 用户提现最低金额 + */ + private Integer brokerageWithdrawMinPrice; + /** + * 提现银行 + */ + @TableField(typeHandler = IntegerListTypeHandler.class) + private List brokerageBankNames; + /** + * 佣金冻结时间(天) + */ + private Integer brokerageFrozenDays; + /** + * 提现方式 + * + * 枚举 {@link BrokerageWithdrawTypeEnum 对应的类} + */ + @TableField(typeHandler = IntegerListTypeHandler.class) + private List brokerageWithdrawType; + } From 6a819da0b6cdd4b9f3eb8c67c519e2a6eb8498c6 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 3 Sep 2023 21:21:33 +0800 Subject: [PATCH 02/50] =?UTF-8?q?=E5=88=86=E4=BD=A3=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E7=94=A8=E6=88=B7=E5=88=86=E9=94=80=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=20API=20mock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 6 +-- .../AppCombinationRecordController.java | 10 ++--- .../brokerage/AppBrokerageUserController.java | 36 +++++++++++++++ .../vo/AppBrokerageUserSummaryRespVO.java | 22 ++++++++++ .../app/user/AppMemberUserController.java | 4 +- .../app/user/vo/AppMemberUserInfoRespVO.java | 3 ++ yudao-server/pom.xml | 44 +++++++++---------- 7 files changed, 94 insertions(+), 31 deletions(-) create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageUserController.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/AppBrokerageUserSummaryRespVO.java diff --git a/pom.xml b/pom.xml index d892b1a13..b50fb8586 100644 --- a/pom.xml +++ b/pom.xml @@ -16,11 +16,11 @@ yudao-module-member yudao-module-system yudao-module-infra - - + - + yudao-module-pay + yudao-module-mall yudao-example diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationRecordController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationRecordController.java index 7496e2e0e..ef0e7ff99 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationRecordController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationRecordController.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.promotion.controller.app.combination; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.util.date.DateUtils; +import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.AppCombinationRecordDetailRespVO; import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.AppCombinationRecordRespVO; import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.AppCombinationRecordSummaryRespVO; @@ -16,8 +16,8 @@ import org.springframework.web.bind.annotation.RestController; import javax.validation.constraints.Max; import java.time.Duration; +import java.time.LocalDateTime; import java.util.ArrayList; -import java.util.Date; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -58,7 +58,7 @@ public class AppCombinationRecordController { record.setId((long) i); record.setNickname("用户" + i); record.setAvatar("头像" + i); - record.setExpireTime(new Date()); + record.setExpireTime(LocalDateTime.now()); record.setUserSize(10); record.setUserCount(i); record.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); @@ -79,7 +79,7 @@ public class AppCombinationRecordController { headRecord.setId(1L); headRecord.setNickname("用户" + 1); headRecord.setAvatar("头像" + 1); - headRecord.setExpireTime(DateUtils.addTime(Duration.ofDays(1))); + headRecord.setExpireTime(LocalDateTimeUtils.addTime(Duration.ofDays(1))); headRecord.setUserSize(10); headRecord.setUserCount(3); headRecord.setStatus(1); @@ -94,7 +94,7 @@ public class AppCombinationRecordController { record.setId((long) i); record.setNickname("用户" + i); record.setAvatar("头像" + i); - record.setExpireTime(new Date()); + record.setExpireTime(LocalDateTime.now()); record.setUserSize(10); record.setUserCount(i); record.setStatus(1); diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageUserController.java new file mode 100644 index 000000000..6af65775e --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageUserController.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.member.controller.app.brokerage; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; +import cn.iocoder.yudao.module.member.controller.app.brokerage.vo.AppBrokerageUserSummaryRespVO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "用户 APP - 分销用户") +@RestController +@RequestMapping("/member/brokerage-user") +@Validated +@Slf4j +public class AppBrokerageUserController { + + // TODO 芋艿:临时 mock => + @GetMapping("/get-summary") + @Operation(summary = "获得个人分销统计") + @PreAuthenticated + public CommonResult getBrokerageUserSummary() { + AppBrokerageUserSummaryRespVO respVO = new AppBrokerageUserSummaryRespVO() + .setYesterdayBrokeragePrice(1) + .setBrokeragePrice(2) + .setFrozenBrokeragePrice(3) + .setWithdrawBrokeragePrice(4); + return success(respVO); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/AppBrokerageUserSummaryRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/AppBrokerageUserSummaryRespVO.java new file mode 100644 index 000000000..ff1bea584 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/AppBrokerageUserSummaryRespVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.member.controller.app.brokerage.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "用户 App - 个人分销统计 Response VO") +@Data +public class AppBrokerageUserSummaryRespVO { + + @Schema(description = "昨天的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Integer yesterdayBrokeragePrice; + + @Schema(description = "提现的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Integer withdrawBrokeragePrice; + + @Schema(description = "可用的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2408") + private Integer brokeragePrice; + + @Schema(description = "冻结的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "234") + private Integer frozenBrokeragePrice; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java index c957ceedc..4d15aad1f 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java @@ -39,7 +39,9 @@ public class AppMemberUserController { public CommonResult getUserInfo() { MemberUserDO user = userService.getUser(getLoginUserId()); MemberLevelDO level = levelService.getLevel(user.getLevelId()); - return success(MemberUserConvert.INSTANCE.convert(user, level)); + return success(MemberUserConvert.INSTANCE.convert(user, level) + .setBrokerageEnabled(true) // TODO @疯狂:这里我先写死,后面改成 db 返回; + ); } @PutMapping("/update") diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java index fc3f427ca..25cceedc2 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java @@ -29,6 +29,9 @@ public class AppMemberUserInfoRespVO { @Schema(description = "用户等级") private Level level; + @Schema(description = "是否成为推广员", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean brokerageEnabled; + @Schema(description = "用户 App - 会员等级") @Data public static class Level { diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index cc383236c..69f912096 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -41,24 +41,24 @@ yudao-spring-boot-starter-biz-error-code - + - + - - - - - + + cn.iocoder.boot + yudao-module-pay-biz + ${revision} + @@ -68,21 +68,21 @@ - - - - - - - - - - - - - - - + + cn.iocoder.boot + yudao-module-promotion-biz + ${revision} + + + cn.iocoder.boot + yudao-module-product-biz + ${revision} + + + cn.iocoder.boot + yudao-module-trade-biz + ${revision} + From 91b03e7c93c9f027a3bb4b5b5984b98243c77d6e Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Mon, 4 Sep 2023 12:18:56 +0800 Subject: [PATCH 03/50] =?UTF-8?q?=E9=92=B1=E5=8C=85=20review=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/order/PayOrderController.java | 12 ++- .../pay/dal/mysql/wallet/PayWalletMapper.java | 51 ++++++++++ .../framework/pay/wallet/WalletPayClient.java | 9 +- .../pay/service/wallet/PayWalletService.java | 35 ++++++- .../service/wallet/PayWalletServiceImpl.java | 98 +++++++++++-------- 5 files changed, 157 insertions(+), 48 deletions(-) diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java index 9a2afbe66..3350b5877 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java @@ -5,6 +5,8 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; +import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import cn.iocoder.yudao.module.pay.controller.admin.order.vo.*; import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert; import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; @@ -23,9 +25,7 @@ import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import java.util.*; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @@ -70,6 +70,12 @@ public class PayOrderController { @PostMapping("/submit") @Operation(summary = "提交支付订单") public CommonResult submitPayOrder(@RequestBody PayOrderSubmitReqVO reqVO) { + if (Objects.equals(reqVO.getChannelCode(), PayChannelEnum.WALLET.getCode())) { + Map channelExtras = reqVO.getChannelExtras() == null ? new HashMap<>(8) : reqVO.getChannelExtras(); + channelExtras.put("user_id", String.valueOf(WebFrameworkUtils.getLoginUserId())); + channelExtras.put("user_type", String.valueOf(WebFrameworkUtils.getLoginUserType())); + reqVO.setChannelExtras(channelExtras); + } PayOrderSubmitRespVO respVO = orderService.submitOrder(reqVO, getClientIP()); return success(respVO); } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java index a05b88fe5..ccacdd376 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java @@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.pay.dal.mysql.wallet; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; +import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; @Mapper @@ -12,6 +14,55 @@ public interface PayWalletMapper extends BaseMapperX { return selectOne(PayWalletDO::getUserId, userId, PayWalletDO::getUserType, userType); } + + /** + * 当余额减少时候更新 + * + * @param bizType 业务类型 + * @param balance 当前余额 + * @param totalRecharge 当前累计充值 + * @param totalExpense 当前累计支出 + * @param price 支出的金额 + * @param id 钱包 id + */ + default int updateWhenDecBalance(PayWalletBizTypeEnum bizType, Integer balance, Long totalRecharge, + Long totalExpense, Integer price, Long id) { + PayWalletDO updateDO = new PayWalletDO().setBalance(balance - price); + if(bizType == PayWalletBizTypeEnum.PAYMENT){ + updateDO.setTotalExpense(totalExpense + price); + } + if (bizType == PayWalletBizTypeEnum.RECHARGE_REFUND) { + updateDO.setTotalRecharge(totalRecharge - price); + } + return update(updateDO, + new LambdaQueryWrapper().eq(PayWalletDO::getId, id) + .eq(PayWalletDO::getBalance, balance) + .ge(PayWalletDO::getBalance, price)); + } + + /** + * 当余额增加时候更新 + * + * @param bizType 业务类型 + * @param balance 当前余额 + * @param totalRecharge 当前累计充值 + * @param totalExpense 当前累计支出 + * @param price 金额 + * @param id 钱包 id + */ + default int updateWhenIncBalance(PayWalletBizTypeEnum bizType, Integer balance, Long totalRecharge, + Long totalExpense, Integer price, Long id) { + PayWalletDO updateDO = new PayWalletDO().setBalance(balance + price); + if (bizType == PayWalletBizTypeEnum.PAYMENT_REFUND) { + updateDO.setTotalExpense(totalExpense - price); + } + if (bizType == PayWalletBizTypeEnum.RECHARGE) { + updateDO.setTotalExpense(totalRecharge + price); + } + return update(updateDO, + new LambdaQueryWrapper().eq(PayWalletDO::getId, id) + .eq(PayWalletDO::getBalance, balance)); + } } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java index 7e23f5cf7..68985965f 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.pay.framework.pay.wallet; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.map.MapUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; @@ -41,7 +43,12 @@ public class WalletPayClient extends AbstractPayClient { @Override protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) { try { - PayWalletTransactionDO transaction = wallService.pay(reqDTO.getOutTradeNo(), reqDTO.getPrice()); + String userId = MapUtil.getStr(reqDTO.getChannelExtras(), "user_id"); + String userType = MapUtil.getStr(reqDTO.getChannelExtras(), "user_type"); + Assert.notEmpty(userId, "用户 id 不能为空"); + Assert.notEmpty(userType, "用户类型不能为空"); + PayWalletTransactionDO transaction = wallService.pay(Long.valueOf(userId), Integer.valueOf(userType), + reqDTO.getOutTradeNo(), reqDTO.getPrice()); return PayOrderRespDTO.successOf(transaction.getNo(), transaction.getCreator(), transaction.getTransactionTime(), reqDTO.getOutTradeNo(), transaction); diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java index 2f57fc465..13cddaeeb 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.service.wallet; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; +import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; /** * 钱包 Service 接口 @@ -20,15 +21,43 @@ public interface PayWalletService { PayWalletDO getPayWallet(Long userId, Integer userType); /** - * 钱包支付 + * 钱包订单支付 * * @param outTradeNo 外部订单号 * @param price 金额 */ - PayWalletTransactionDO pay(String outTradeNo, Integer price); + PayWalletTransactionDO pay(Long userId, Integer userType, String outTradeNo, Integer price); + /** - * 钱包支付退款 + * 扣减钱包余额 + * + * @param userId 用户 id + * @param userType 用户类型 + * @param bizId 业务关联 id + * @param bizType 业务关联分类 + * @param price 扣减金额 + * @return 钱包流水 + */ + PayWalletTransactionDO reduceWalletBalance(Long userId, Integer userType, + Long bizId, PayWalletBizTypeEnum bizType, Integer price); + + + /** + * 增加钱包余额 + * + * @param userId 用户 id + * @param userType 用户类型 + * @param bizId 业务关联 id + * @param bizType 业务关联分类 + * @param price 增加金额 + * @return 钱包流水 + */ + PayWalletTransactionDO addWalletBalance(Long userId, Integer userType, + Long bizId, PayWalletBizTypeEnum bizType, Integer price); + + /** + * 钱包订单支付退款 * * @param outRefundNo 外部退款号 * @param refundPrice 退款金额 diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java index 6992d63f6..5ea1b4945 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java @@ -1,11 +1,13 @@ package cn.iocoder.yudao.module.pay.service.wallet; +import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletMapper; import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO; +import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; import cn.iocoder.yudao.module.pay.service.order.PayOrderService; import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; import lombok.extern.slf4j.Slf4j; @@ -16,9 +18,8 @@ import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.time.LocalDateTime; +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.TOO_MANY_REQUESTS; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId; -import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserType; import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum.PAYMENT; import static cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum.PAYMENT_REFUND; @@ -60,42 +61,70 @@ public class PayWalletServiceImpl implements PayWalletService { return payWalletMapper.selectByUserIdAndType(userId, userType); } - // TODO @jason:可以做的更抽象一点;pay(bizType, bizId, price);reduceWalletBalance; - // TODO @jason:最好是,明确传入哪个 userId 或者 walletId; + @Override @Transactional(rollbackFor = Exception.class) - public PayWalletTransactionDO pay(String outTradeNo, Integer price) { - // 1.1 判断支付交易拓展单是否存 + public PayWalletTransactionDO pay(Long userId, Integer userType, String outTradeNo, Integer price) { + // 判断支付交易拓展单是否存 PayOrderExtensionDO orderExtension = payOrderService.getOrderExtensionByNo(outTradeNo); if (orderExtension == null) { throw exception(ORDER_EXTENSION_NOT_FOUND); } + return reduceWalletBalance(userId, userType, orderExtension.getOrderId(), PAYMENT, price); + } + + @Override + public PayWalletTransactionDO reduceWalletBalance(Long userId, Integer userType, + Long bizId, PayWalletBizTypeEnum bizType, Integer price) { + // 1.1 判断钱包是否有效 + PayWalletDO payWallet = validatePayWallet(userId, userType); // 1.2 判断余额是否足够 - PayWalletDO payWallet = validatePayWallet(); int afterBalance = payWallet.getBalance() - price; if (afterBalance < 0) { throw exception(WALLET_BALANCE_NOT_ENOUGH); } // 2.1 扣除余额 - // TODO @jason:不要直接整个更新;而是 new 一个出来更新;然后要考虑并发,要 where 余额 > price,以及 - price - payWallet.setBalance(afterBalance); - payWallet.setTotalExpense(payWallet.getTotalExpense() + price); - payWalletMapper.updateById(payWallet); + int number = payWalletMapper.updateWhenDecBalance(bizType,payWallet.getBalance(), payWallet.getTotalRecharge(), + payWallet.getTotalExpense(), price, payWallet.getId()); + if (number == 0) { + throw exception(TOO_MANY_REQUESTS); + } - // 2.2 生成钱包流水 + // 2.2 生成钱包流水 TODO 根据 bizType 生成 NO String walletNo = noRedisDAO.generate(WALLET_PAY_NO_PREFIX); PayWalletTransactionDO walletTransaction = new PayWalletTransactionDO().setWalletId(payWallet.getId()) - .setNo(walletNo).setAmount(price * -1).setBalance(afterBalance).setTransactionTime(LocalDateTime.now()) - .setBizId(orderExtension.getOrderId()).setBizType(PAYMENT.getType()); + .setNo(walletNo).setAmount(-price).setBalance(afterBalance).setTransactionTime(LocalDateTime.now()) + .setBizId(bizId).setBizType(bizType.getType()).setDescription(bizType.getDescription()); payWalletTransactionService.createWalletTransaction(walletTransaction); return walletTransaction; } - // TODO @jason:不要在 service 里去使用用户上下文,这样和 request 就耦合了。 - private PayWalletDO validatePayWallet() { - Long userId = getLoginUserId(); - Integer userType = getLoginUserType(); + @Override + public PayWalletTransactionDO addWalletBalance(Long userId, Integer userType, Long bizId, + PayWalletBizTypeEnum bizType, Integer price) { + // 1.1 判断钱包是否有效 + PayWalletDO payWallet = validatePayWallet(userId, userType); + + // 2.1 增加余额 + int number = payWalletMapper.updateWhenIncBalance(bizType, payWallet.getBalance(), payWallet.getTotalRecharge(), + payWallet.getTotalExpense(), price, payWallet.getId()); + if (number == 0) { + throw exception(TOO_MANY_REQUESTS); + } + + // 2.2 生成钱包流水 TODO 根据 bizType 生成 NO + String walletNo = noRedisDAO.generate(WALLET_REFUND_NO_PREFIX); + PayWalletTransactionDO newWalletTransaction = new PayWalletTransactionDO().setWalletId(payWallet.getId()) + .setNo(walletNo).setAmount(price).setBalance(payWallet.getBalance()+price).setTransactionTime(LocalDateTime.now()) + .setBizId(bizId).setBizType(bizType.getType()) + .setDescription(bizType.getDescription()); + payWalletTransactionService.createWalletTransaction(newWalletTransaction); + return newWalletTransaction; + } + + + private PayWalletDO validatePayWallet(Long userId, Integer userType) { PayWalletDO payWallet = getPayWallet(userId, userType); if (payWallet == null) { log.error("[validatePayWallet] 用户 {} 钱包不存在", userId); @@ -104,7 +133,7 @@ public class PayWalletServiceImpl implements PayWalletService { return payWallet; } - // TODO @jason:可以做的更抽象一点;pay(bizType, bizId, price);addWalletBalance;这样,如果后续充值,应该也是能复用这个方法的; + @Override @Transactional(rollbackFor = Exception.class) public PayWalletTransactionDO refund(String outRefundNo, Integer refundPrice, String reason) { @@ -114,23 +143,11 @@ public class PayWalletServiceImpl implements PayWalletService { throw exception(REFUND_NOT_FOUND); } // 1.2 校验是否可以退款 - PayWalletDO payWallet = validatePayWallet(); - validateWalletCanRefund(payRefund.getId(), payRefund.getChannelOrderNo(), payWallet.getId(), refundPrice); + Long walletId = validateWalletCanRefund(payRefund.getId(), payRefund.getChannelOrderNo(), refundPrice); - // TODO @jason:不要直接整个更新;而是 new 一个出来更新;然后要考虑并发,要 where 余额 + 金额 - Integer afterBalance = payWallet.getBalance() + refundPrice; - payWallet.setBalance(afterBalance); - payWallet.setTotalExpense(payWallet.getTotalExpense() + refundPrice * -1L); - payWalletMapper.updateById(payWallet); - - // 2.2 生成钱包流水 - String walletNo = noRedisDAO.generate(WALLET_REFUND_NO_PREFIX); - PayWalletTransactionDO newWalletTransaction = new PayWalletTransactionDO().setWalletId(payWallet.getId()) - .setNo(walletNo).setAmount(refundPrice).setBalance(afterBalance).setTransactionTime(LocalDateTime.now()) - .setBizId(payRefund.getId()).setBizType(PAYMENT_REFUND.getType()) - .setDescription(reason); - payWalletTransactionService.createWalletTransaction(newWalletTransaction); - return newWalletTransaction; + PayWalletDO payWallet = payWalletMapper.selectById(walletId); + Assert.notNull(payWallet, "钱包 {} 不存在", walletId); + return addWalletBalance(payWallet.getUserId(), payWallet.getUserType(),payRefund.getId(), PAYMENT_REFUND, refundPrice); } /** @@ -138,24 +155,23 @@ public class PayWalletServiceImpl implements PayWalletService { * * @param refundId 支付退款单 id * @param walletPayNo 钱包支付 no - * @param walletId 钱包 id */ - // TODO @jason:不要使用基本类型; - private void validateWalletCanRefund(long refundId, String walletPayNo, long walletId, int refundPrice) { + private Long validateWalletCanRefund(Long refundId, String walletPayNo, Integer refundPrice) { // 查询钱包支付交易 PayWalletTransactionDO payWalletTransaction = payWalletTransactionService.getWalletTransactionByNo(walletPayNo); if (payWalletTransaction == null) { throw exception(WALLET_TRANSACTION_NOT_FOUND); } // 原来的支付金额 - int amount = payWalletTransaction.getAmount() * -1; // TODO @jason:直接 - payWalletTransaction.getAmount() 即可; + int amount = - payWalletTransaction.getAmount(); if (refundPrice != amount) { throw exception(WALLET_REFUND_AMOUNT_ERROR); } - PayWalletTransactionDO refundTransaction = payWalletTransactionService.getWalletTransaction(walletId, refundId, PAYMENT_REFUND); + PayWalletTransactionDO refundTransaction = payWalletTransactionService.getWalletTransaction( + payWalletTransaction.getWalletId(), refundId, PAYMENT_REFUND); if (refundTransaction != null) { throw exception(WALLET_REFUND_EXIST); } + return payWalletTransaction.getWalletId(); } - } From cc4c924717b862a85765f918a8205cdcfcc80f41 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Mon, 4 Sep 2023 14:54:38 +0800 Subject: [PATCH 04/50] =?UTF-8?q?=E9=92=B1=E5=8C=85=20review=20DO=20?= =?UTF-8?q?=E7=B1=BB=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/mysql/pay_wallet.sql | 37 ++++++----- .../app/wallet/AppPayWalletController.java | 2 +- .../AppPayWalletTransactionRespVO.java | 3 - .../wallet/PayWalletTransactionDO.java | 23 ++----- .../wallet/PayWalletTransactionMapper.java | 4 +- .../framework/pay/wallet/WalletPayClient.java | 4 +- .../pay/service/wallet/PayWalletService.java | 7 +- .../service/wallet/PayWalletServiceImpl.java | 64 +++++++++++-------- .../PayWalletTransactionServiceImpl.java | 9 +-- 9 files changed, 74 insertions(+), 79 deletions(-) diff --git a/sql/mysql/pay_wallet.sql b/sql/mysql/pay_wallet.sql index 1fda83769..bc2ad183e 100644 --- a/sql/mysql/pay_wallet.sql +++ b/sql/mysql/pay_wallet.sql @@ -1,5 +1,5 @@ -- ---------------------------- --- 支付-钱包表 +-- 会员钱包表 -- ---------------------------- DROP TABLE IF EXISTS `pay_wallet`; CREATE TABLE `pay_wallet` @@ -17,28 +17,27 @@ CREATE TABLE `pay_wallet` `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB COMMENT='支付钱包表'; +) ENGINE=InnoDB COMMENT='会员钱包表'; -- ---------------------------- --- 支付- 钱包余额明细表 +-- 会员钱包流水表 -- ---------------------------- DROP TABLE IF EXISTS `pay_wallet_transaction`; CREATE TABLE `pay_wallet_transaction` ( - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', - `wallet_id` bigint NOT NULL COMMENT '会员钱包 id', - `biz_type` tinyint NOT NULL COMMENT '关联类型', - `biz_id` bigint NOT NULL COMMENT '关联业务编号', - `no` varchar(64) NOT NULL COMMENT '流水号', - `description` varchar(255) COMMENT '操作说明', - `amount` int NOT NULL COMMENT '交易金额, 单位分', - `balance` int NOT NULL COMMENT '余额, 单位分', - `transaction_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '交易时间', - `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', - `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', - `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', - `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', + `wallet_id` bigint NOT NULL COMMENT '会员钱包 id', + `biz_type` tinyint NOT NULL COMMENT '关联类型', + `biz_id` varchar(64) NOT NULL COMMENT '关联业务编号', + `no` varchar(64) NOT NULL COMMENT '流水号', + `title` varchar(128) NOT NULL COMMENT '流水标题', + `price` int NOT NULL COMMENT '交易金额, 单位分', + `balance` int NOT NULL COMMENT '余额, 单位分', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB COMMENT='支付钱包余额明细表'; +) ENGINE=InnoDB COMMENT='会员钱包流水表'; diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletController.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletController.java index 23515ed33..2c5f2d5f4 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletController.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletController.java @@ -37,7 +37,7 @@ public class AppPayWalletController { @Operation(summary = "获取钱包") @PreAuthenticated public CommonResult getPayWallet() { - PayWalletDO wallet = payWalletService.getPayWallet(getLoginUserId(), UserTypeEnum.MEMBER.getValue()); + PayWalletDO wallet = payWalletService.getOrCreatePayWallet(getLoginUserId(), UserTypeEnum.MEMBER.getValue()); return success(PayWalletConvert.INSTANCE.convert(wallet)); } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/transaction/AppPayWalletTransactionRespVO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/transaction/AppPayWalletTransactionRespVO.java index b89628bc2..9d17c346e 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/transaction/AppPayWalletTransactionRespVO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/transaction/AppPayWalletTransactionRespVO.java @@ -15,9 +15,6 @@ public class AppPayWalletTransactionRespVO { @Schema(description = "业务分类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Integer bizType; - @Schema(description = "交易时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") - private LocalDateTime transactionTime; - @Schema(description = "交易金额,单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") private Long price; diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletTransactionDO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletTransactionDO.java index 677febb25..04a869f32 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletTransactionDO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletTransactionDO.java @@ -7,8 +7,6 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; -import java.time.LocalDateTime; - /** * 会员钱包流水 DO * @@ -24,6 +22,7 @@ public class PayWalletTransactionDO extends BaseDO { */ @TableId private Long id; + /** * 流水号 */ @@ -42,34 +41,26 @@ public class PayWalletTransactionDO extends BaseDO { * 枚举 {@link PayWalletBizTypeEnum#getType()} */ private Integer bizType; - // TODO @jason:使用 string;因为可能有业务是 string 接入哈。 + /** * 关联业务编号 */ - private Long bizId; + private String bizId; - // TODO @jason:想了下,改成 title;流水标题;因为账户明细那,会看到这个; /** - * 附加说明 + * 流水说明 */ - private String description; + private String title; - // TODO @jason:使用 price 哈。项目里,金额都是用这个为主; /** * 交易金额,单位分 * * 正值表示余额增加,负值表示余额减少 */ - private Integer amount; + private Integer price; + /** * 交易后余额,单位分 */ private Integer balance; - - // TODO @jason:使用 createTime 就够啦 - /** - * 交易时间 - */ - private LocalDateTime transactionTime; - } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletTransactionMapper.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletTransactionMapper.java index 9e08b2caa..3d329d118 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletTransactionMapper.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletTransactionMapper.java @@ -18,9 +18,9 @@ public interface PayWalletTransactionMapper extends BaseMapperX query = new LambdaQueryWrapperX() .eq(PayWalletTransactionDO::getWalletId, walletId); if (Objects.equals(pageReqVO.getType(), AppPayWalletTransactionPageReqVO.TYPE_INCOME)) { - query.gt(PayWalletTransactionDO::getAmount, 0); + query.gt(PayWalletTransactionDO::getPrice, 0); } else if (Objects.equals(pageReqVO.getType(), AppPayWalletTransactionPageReqVO.TYPE_EXPENSE)) { - query.lt(PayWalletTransactionDO::getAmount, 0); + query.lt(PayWalletTransactionDO::getPrice, 0); } query.orderByDesc(PayWalletTransactionDO::getId); return selectPage(pageReqVO, query); diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java index 68985965f..170fd6694 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java @@ -50,7 +50,7 @@ public class WalletPayClient extends AbstractPayClient { PayWalletTransactionDO transaction = wallService.pay(Long.valueOf(userId), Integer.valueOf(userType), reqDTO.getOutTradeNo(), reqDTO.getPrice()); return PayOrderRespDTO.successOf(transaction.getNo(), transaction.getCreator(), - transaction.getTransactionTime(), + transaction.getCreateTime(), reqDTO.getOutTradeNo(), transaction); } catch (Throwable ex) { log.error("[doUnifiedOrder] 失败", ex); @@ -81,7 +81,7 @@ public class WalletPayClient extends AbstractPayClient { try { PayWalletTransactionDO payWalletTransaction = wallService.refund(reqDTO.getOutRefundNo(), reqDTO.getRefundPrice(), reqDTO.getReason()); - return PayRefundRespDTO.successOf(payWalletTransaction.getNo(), payWalletTransaction.getTransactionTime(), + return PayRefundRespDTO.successOf(payWalletTransaction.getNo(), payWalletTransaction.getCreateTime(), reqDTO.getOutRefundNo(), payWalletTransaction); } catch (Throwable ex) { log.error("[doUnifiedRefund] 失败", ex); diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java index 13cddaeeb..370b776a7 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java @@ -11,18 +11,19 @@ import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; */ public interface PayWalletService { - // TODO @jason:改成 getOrCreateWallet;因为目前解耦,用户注册时,不会创建钱包;需要这里兜底处理; /** - * 获取钱包信息 + * 获取钱包信息,如果不存在创建钱包。由于用户注册时候不会创建钱包 * * @param userId 用户编号 * @param userType 用户类型 */ - PayWalletDO getPayWallet(Long userId, Integer userType); + PayWalletDO getOrCreatePayWallet(Long userId, Integer userType); /** * 钱包订单支付 * + * @param userId 用户 id + * @param userType 用户类型 * @param outTradeNo 外部订单号 * @param price 金额 */ diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java index 5ea1b4945..a3606323b 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java @@ -57,8 +57,19 @@ public class PayWalletServiceImpl implements PayWalletService { private PayRefundService payRefundService; @Override - public PayWalletDO getPayWallet(Long userId, Integer userType) { - return payWalletMapper.selectByUserIdAndType(userId, userType); + public PayWalletDO getOrCreatePayWallet(Long userId, Integer userType) { + PayWalletDO payWalletDO = payWalletMapper.selectByUserIdAndType(userId, userType); + if (payWalletDO == null) { + payWalletDO = new PayWalletDO(); + payWalletDO.setUserId(userId); + payWalletDO.setUserType(userType); + payWalletDO.setBalance(0); + payWalletDO.setTotalExpense(0L); + payWalletDO.setTotalRecharge(0L); + payWalletDO.setCreateTime(LocalDateTime.now()); + payWalletMapper.insert(payWalletDO); + } + return payWalletDO; } @@ -76,8 +87,8 @@ public class PayWalletServiceImpl implements PayWalletService { @Override public PayWalletTransactionDO reduceWalletBalance(Long userId, Integer userType, Long bizId, PayWalletBizTypeEnum bizType, Integer price) { - // 1.1 判断钱包是否有效 - PayWalletDO payWallet = validatePayWallet(userId, userType); + // 1.1 获取钱包 + PayWalletDO payWallet = getOrCreatePayWallet(userId, userType); // 1.2 判断余额是否足够 int afterBalance = payWallet.getBalance() - price; if (afterBalance < 0) { @@ -90,12 +101,11 @@ public class PayWalletServiceImpl implements PayWalletService { if (number == 0) { throw exception(TOO_MANY_REQUESTS); } - - // 2.2 生成钱包流水 TODO 根据 bizType 生成 NO - String walletNo = noRedisDAO.generate(WALLET_PAY_NO_PREFIX); + // 2.2 生成钱包流水 + String walletNo = generateWalletNo(bizType); PayWalletTransactionDO walletTransaction = new PayWalletTransactionDO().setWalletId(payWallet.getId()) - .setNo(walletNo).setAmount(-price).setBalance(afterBalance).setTransactionTime(LocalDateTime.now()) - .setBizId(bizId).setBizType(bizType.getType()).setDescription(bizType.getDescription()); + .setNo(walletNo).setPrice(-price).setBalance(afterBalance) + .setBizId(String.valueOf(bizId)).setBizType(bizType.getType()).setTitle(bizType.getDescription()); payWalletTransactionService.createWalletTransaction(walletTransaction); return walletTransaction; } @@ -103,8 +113,8 @@ public class PayWalletServiceImpl implements PayWalletService { @Override public PayWalletTransactionDO addWalletBalance(Long userId, Integer userType, Long bizId, PayWalletBizTypeEnum bizType, Integer price) { - // 1.1 判断钱包是否有效 - PayWalletDO payWallet = validatePayWallet(userId, userType); + // 1.1 获取钱包 + PayWalletDO payWallet = getOrCreatePayWallet(userId, userType); // 2.1 增加余额 int number = payWalletMapper.updateWhenIncBalance(bizType, payWallet.getBalance(), payWallet.getTotalRecharge(), @@ -113,27 +123,31 @@ public class PayWalletServiceImpl implements PayWalletService { throw exception(TOO_MANY_REQUESTS); } - // 2.2 生成钱包流水 TODO 根据 bizType 生成 NO - String walletNo = noRedisDAO.generate(WALLET_REFUND_NO_PREFIX); + // 2.2 生成钱包流水 + String walletNo = generateWalletNo(bizType); PayWalletTransactionDO newWalletTransaction = new PayWalletTransactionDO().setWalletId(payWallet.getId()) - .setNo(walletNo).setAmount(price).setBalance(payWallet.getBalance()+price).setTransactionTime(LocalDateTime.now()) - .setBizId(bizId).setBizType(bizType.getType()) - .setDescription(bizType.getDescription()); + .setNo(walletNo).setPrice(price).setBalance(payWallet.getBalance()+price) + .setBizId(String.valueOf(bizId)).setBizType(bizType.getType()) + .setTitle(bizType.getDescription()); payWalletTransactionService.createWalletTransaction(newWalletTransaction); return newWalletTransaction; } - - private PayWalletDO validatePayWallet(Long userId, Integer userType) { - PayWalletDO payWallet = getPayWallet(userId, userType); - if (payWallet == null) { - log.error("[validatePayWallet] 用户 {} 钱包不存在", userId); - throw exception(WALLET_NOT_FOUND); + private String generateWalletNo(PayWalletBizTypeEnum bizType) { + String no = ""; + switch(bizType){ + case PAYMENT : + no = noRedisDAO.generate(WALLET_PAY_NO_PREFIX); + break; + case PAYMENT_REFUND : + no = noRedisDAO.generate(WALLET_REFUND_NO_PREFIX); + break; + default : + // TODO 待增加 } - return payWallet; + return no; } - @Override @Transactional(rollbackFor = Exception.class) public PayWalletTransactionDO refund(String outRefundNo, Integer refundPrice, String reason) { @@ -163,7 +177,7 @@ public class PayWalletServiceImpl implements PayWalletService { throw exception(WALLET_TRANSACTION_NOT_FOUND); } // 原来的支付金额 - int amount = - payWalletTransaction.getAmount(); + int amount = - payWalletTransaction.getPrice(); if (refundPrice != amount) { throw exception(WALLET_REFUND_AMOUNT_ERROR); } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java index e2338219d..1b156576a 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java @@ -11,9 +11,6 @@ import org.springframework.stereotype.Service; import javax.annotation.Resource; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.WALLET_NOT_FOUND; - /** * 钱包流水 Service 实现类 * @@ -32,11 +29,7 @@ public class PayWalletTransactionServiceImpl implements PayWalletTransactionServ @Override public PageResult getWalletTransactionPage(Long userId, Integer userType, AppPayWalletTransactionPageReqVO pageVO) { - PayWalletDO wallet = payWalletService.getPayWallet(userId, userType); - if (wallet == null) { - log.error("[getWalletTransactionPage][用户({}/{}) 钱包不存在", userId, userType); - throw exception(WALLET_NOT_FOUND); - } + PayWalletDO wallet = payWalletService.getOrCreatePayWallet(userId, userType); return payWalletTransactionMapper.selectPage(wallet.getId(), pageVO); } From fc56a15f76815581191ba9e7afcb6411813c86b1 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 4 Sep 2023 21:00:03 +0800 Subject: [PATCH 05/50] =?UTF-8?q?=E5=88=86=E4=BD=A3=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E7=94=A8=E6=88=B7=E5=88=86=E9=94=80=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E3=80=81=E6=8F=90=E7=8E=B0=20API=20mock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AppBrokerageRecordController.java | 39 +++++++++++++++++++ .../brokerage/AppBrokerageUserController.java | 2 +- .../AppBrokerageWithdrawController.java | 39 +++++++++++++++++++ .../vo/record/AppBrokerageRecordRespVO.java | 24 ++++++++++++ .../AppBrokerageUserSummaryRespVO.java | 2 +- .../withdraw/AppBrokerageWithdrawRespVO.java | 27 +++++++++++++ 6 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageRecordController.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageWithdrawController.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/record/AppBrokerageRecordRespVO.java rename yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/{ => user}/AppBrokerageUserSummaryRespVO.java (99%) create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawRespVO.java diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageRecordController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageRecordController.java new file mode 100644 index 000000000..df46b561d --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageRecordController.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.member.controller.app.brokerage; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; +import cn.iocoder.yudao.module.member.controller.app.brokerage.vo.record.AppBrokerageRecordRespVO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static java.util.Arrays.asList; + +@Tag(name = "用户 APP - 分销用户") +@RestController +@RequestMapping("/member/brokerage-record") +@Validated +@Slf4j +public class AppBrokerageRecordController { + + // TODO 芋艿:临时 mock => + @GetMapping("/page") + @Operation(summary = "获得分销记录分页") + @PreAuthenticated + public CommonResult> getBrokerageRecordPage() { + AppBrokerageRecordRespVO vo1 = new AppBrokerageRecordRespVO() + .setId(1L).setPrice(10).setTitle("收到钱").setCreateTime(LocalDateTime.now()); + AppBrokerageRecordRespVO vo2 = new AppBrokerageRecordRespVO() + .setId(2L).setPrice(-20).setTitle("提现钱").setCreateTime(LocalDateTime.now()); + return success(new PageResult<>(asList(vo1, vo2), 10L)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageUserController.java index 6af65775e..0b31c07bd 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageUserController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageUserController.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.member.controller.app.brokerage; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; -import cn.iocoder.yudao.module.member.controller.app.brokerage.vo.AppBrokerageUserSummaryRespVO; +import cn.iocoder.yudao.module.member.controller.app.brokerage.vo.user.AppBrokerageUserSummaryRespVO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageWithdrawController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageWithdrawController.java new file mode 100644 index 000000000..dde0a8a03 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageWithdrawController.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.member.controller.app.brokerage; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; +import cn.iocoder.yudao.module.member.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawRespVO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static java.util.Arrays.asList; + +@Tag(name = "用户 APP - 分销提现") +@RestController +@RequestMapping("/member/brokerage-withdraw") +@Validated +@Slf4j +public class AppBrokerageWithdrawController { + + // TODO 芋艿:临时 mock => + @GetMapping("/page") + @Operation(summary = "获得分销提现分页") + @PreAuthenticated + public CommonResult> getBrokerageWithdrawPage() { + AppBrokerageWithdrawRespVO vo1 = new AppBrokerageWithdrawRespVO() + .setId(1L).setStatus(10).setPrice(10).setStatusName("审批通过").setCreateTime(LocalDateTime.now()); + AppBrokerageWithdrawRespVO vo2 = new AppBrokerageWithdrawRespVO() + .setId(2L).setStatus(0).setPrice(20).setStatusName("审批中").setCreateTime(LocalDateTime.now()); + return success(new PageResult<>(asList(vo1, vo2), 10L)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/record/AppBrokerageRecordRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/record/AppBrokerageRecordRespVO.java new file mode 100644 index 000000000..fc85695d0 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/record/AppBrokerageRecordRespVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.member.controller.app.brokerage.vo.record; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "用户 App - 分销记录 Response VO") +@Data +public class AppBrokerageRecordRespVO { + + @Schema(description = "记录编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Long id; + + @Schema(description = "分销标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "用户下单") + private String title; + + @Schema(description = "分销金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") + private Integer price; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/AppBrokerageUserSummaryRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/user/AppBrokerageUserSummaryRespVO.java similarity index 99% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/AppBrokerageUserSummaryRespVO.java rename to yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/user/AppBrokerageUserSummaryRespVO.java index ff1bea584..635705253 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/AppBrokerageUserSummaryRespVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/user/AppBrokerageUserSummaryRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.member.controller.app.brokerage.vo; +package cn.iocoder.yudao.module.member.controller.app.brokerage.vo.user; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawRespVO.java new file mode 100644 index 000000000..3a3670097 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawRespVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.member.controller.app.brokerage.vo.withdraw; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "用户 App - 分销提现 Response VO") +@Data +public class AppBrokerageWithdrawRespVO { + + @Schema(description = "提现编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Long id; + + @Schema(description = "提现状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Integer status; + + @Schema(description = "提现状态名", requiredMode = Schema.RequiredMode.REQUIRED, example = "审核中") + private String statusName; + + @Schema(description = "提现金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") + private Integer price; + + @Schema(description = "提现时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} From 7389e4fb650be0b51a8a6d38fca0b165b3754c26 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 4 Sep 2023 22:48:26 +0800 Subject: [PATCH 06/50] =?UTF-8?q?=E5=88=86=E4=BD=A3=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=8E=B7=E5=BE=97=E5=88=86=E9=94=80=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E5=88=86=E9=A1=B5=20API=20mock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AppBrokerageRecordController.java | 9 ++++++--- .../record/AppBrokerageRecordPageReqVO.java | 19 +++++++++++++++++++ .../vo/record/AppBrokerageRecordRespVO.java | 3 +++ 3 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageRecordController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageRecordController.java index df46b561d..de2460fee 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageRecordController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageRecordController.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.member.controller.app.brokerage; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; +import cn.iocoder.yudao.module.member.controller.app.brokerage.vo.record.AppBrokerageRecordPageReqVO; import cn.iocoder.yudao.module.member.controller.app.brokerage.vo.record.AppBrokerageRecordRespVO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -28,11 +29,13 @@ public class AppBrokerageRecordController { @GetMapping("/page") @Operation(summary = "获得分销记录分页") @PreAuthenticated - public CommonResult> getBrokerageRecordPage() { + public CommonResult> getBrokerageRecordPage(AppBrokerageRecordPageReqVO pageReqVO) { AppBrokerageRecordRespVO vo1 = new AppBrokerageRecordRespVO() - .setId(1L).setPrice(10).setTitle("收到钱").setCreateTime(LocalDateTime.now()); + .setId(1L).setPrice(10).setTitle("收到钱").setCreateTime(LocalDateTime.now()) + .setFinishTime(LocalDateTime.now()); AppBrokerageRecordRespVO vo2 = new AppBrokerageRecordRespVO() - .setId(2L).setPrice(-20).setTitle("提现钱").setCreateTime(LocalDateTime.now()); + .setId(2L).setPrice(-20).setTitle("提现钱").setCreateTime(LocalDateTime.now()) + .setFinishTime(LocalDateTime.now()); return success(new PageResult<>(asList(vo1, vo2), 10L)); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java new file mode 100644 index 000000000..c8bfabd5c --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.member.controller.app.brokerage.vo.record; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "应用 App - 分销记录分页 Request VO") +@Data +public class AppBrokerageRecordPageReqVO extends PageParam { + + // TODO @疯狂:要加下枚举校验 + + @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer bizType; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer status; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/record/AppBrokerageRecordRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/record/AppBrokerageRecordRespVO.java index fc85695d0..0459e15f9 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/record/AppBrokerageRecordRespVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/record/AppBrokerageRecordRespVO.java @@ -21,4 +21,7 @@ public class AppBrokerageRecordRespVO { @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; + @Schema(description = "完成时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime finishTime; + } From eae8218f0dda538d7117b63ef1ec558af3db242a Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 5 Sep 2023 00:11:41 +0800 Subject: [PATCH 07/50] =?UTF-8?q?=E5=88=86=E4=BD=A3=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=8E=B7=E5=BE=97=E5=88=86=E9=94=80=E6=8E=92=E8=A1=8C?= =?UTF-8?q?=E5=88=86=E9=A1=B5=20API=20mock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AppBrokerageRecordController.java | 3 ++- .../brokerage/AppBrokerageUserController.java | 23 +++++++++++++++++++ .../user/AppBrokerageUserRankPageReqVO.java | 22 ++++++++++++++++++ .../vo/user/AppBrokerageUserRankRespVO.java | 22 ++++++++++++++++++ 4 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/user/AppBrokerageUserRankPageReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/user/AppBrokerageUserRankRespVO.java diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageRecordController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageRecordController.java index de2460fee..8cf4d81e8 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageRecordController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageRecordController.java @@ -13,6 +13,7 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import javax.validation.Valid; import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -29,7 +30,7 @@ public class AppBrokerageRecordController { @GetMapping("/page") @Operation(summary = "获得分销记录分页") @PreAuthenticated - public CommonResult> getBrokerageRecordPage(AppBrokerageRecordPageReqVO pageReqVO) { + public CommonResult> getBrokerageRecordPage(@Valid AppBrokerageRecordPageReqVO pageReqVO) { AppBrokerageRecordRespVO vo1 = new AppBrokerageRecordRespVO() .setId(1L).setPrice(10).setTitle("收到钱").setCreateTime(LocalDateTime.now()) .setFinishTime(LocalDateTime.now()); diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageUserController.java index 0b31c07bd..1b5bc6184 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageUserController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageUserController.java @@ -1,7 +1,10 @@ package cn.iocoder.yudao.module.member.controller.app.brokerage; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; +import cn.iocoder.yudao.module.member.controller.app.brokerage.vo.user.AppBrokerageUserRankPageReqVO; +import cn.iocoder.yudao.module.member.controller.app.brokerage.vo.user.AppBrokerageUserRankRespVO; import cn.iocoder.yudao.module.member.controller.app.brokerage.vo.user.AppBrokerageUserSummaryRespVO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -12,6 +15,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static java.util.Arrays.asList; @Tag(name = "用户 APP - 分销用户") @RestController @@ -33,4 +37,23 @@ public class AppBrokerageUserController { return success(respVO); } + @GetMapping("/rank-page") + @Operation(summary = "获得分销用户排行分页") + @PreAuthenticated + public CommonResult> getBrokerageUserRankPage(AppBrokerageUserRankPageReqVO pageReqVO) { + AppBrokerageUserRankRespVO vo1 = new AppBrokerageUserRankRespVO() + .setUserId(1L).setNickname("芋1**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") + .setBrokerageUserCount(10); + AppBrokerageUserRankRespVO vo2 = new AppBrokerageUserRankRespVO() + .setUserId(2L).setNickname("芋2**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") + .setBrokerageUserCount(6); + AppBrokerageUserRankRespVO vo3 = new AppBrokerageUserRankRespVO() + .setUserId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") + .setBrokerageUserCount(4); + AppBrokerageUserRankRespVO vo4 = new AppBrokerageUserRankRespVO() + .setUserId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") + .setBrokerageUserCount(4); + return success(new PageResult<>(asList(vo1, vo2, vo3, vo4), 10L)); + } + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/user/AppBrokerageUserRankPageReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/user/AppBrokerageUserRankPageReqVO.java new file mode 100644 index 000000000..0ba1e9c75 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/user/AppBrokerageUserRankPageReqVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.member.controller.app.brokerage.vo.user; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotEmpty; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "应用 App - 分销用户排行 Request VO") +@Data +public class AppBrokerageUserRankPageReqVO extends PageParam { + + @Schema(description = "开始 + 结束时间", requiredMode = Schema.RequiredMode.REQUIRED) + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @NotEmpty(message = "时间不能为空") + private LocalDateTime[] times; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/user/AppBrokerageUserRankRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/user/AppBrokerageUserRankRespVO.java new file mode 100644 index 000000000..7835f5532 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/user/AppBrokerageUserRankRespVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.member.controller.app.brokerage.vo.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "用户 App - 分销排行用户 Response VO") +@Data +public class AppBrokerageUserRankRespVO { + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Long userId; + + @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小王") + private String nickname; + + @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://www.iocoder.cn/xxx.jpg") + private String avatar; + + @Schema(description = "邀请用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Integer brokerageUserCount; + +} From c7ef8519c83dc6f0339dd6600ec62ecc37ac4d85 Mon Sep 17 00:00:00 2001 From: owen Date: Tue, 5 Sep 2023 08:56:39 +0800 Subject: [PATCH 08/50] =?UTF-8?q?member:=20=E5=88=86=E9=94=80=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E4=BD=A3=E9=87=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/mysql/brokerage.sql | 189 ++++++++++++++++++ .../api/sku/dto/ProductSkuRespDTO.java | 9 + .../convert/order/TradeOrderConvert.java | 8 + .../order/TradeOrderUpdateServiceImpl.java | 15 ++ .../member/api/brokerage/BrokerageApi.java | 30 +++ .../api/brokerage/dto/BrokerageAddReqDTO.java | 35 ++++ .../api/brokerage/BrokerageApiImpl.java | 32 +++ .../MemberBrokerageRecordController.java | 51 +++++ .../vo/MemberBrokerageRecordBaseVO.java | 59 ++++++ .../vo/MemberBrokerageRecordPageReqVO.java | 33 +++ .../vo/MemberBrokerageRecordRespVO.java | 22 ++ .../record/MemberBrokerageRecordConvert.java | 46 +++++ .../record/MemberBrokerageRecordDO.java | 78 ++++++++ .../dal/dataobject/user/MemberUserDO.java | 27 +++ .../record/MemberBrokerageRecordMapper.java | 27 +++ .../dal/mysql/user/MemberUserMapper.java | 30 +++ .../record/MemberBrokerageRecordService.java | 40 ++++ .../MemberBrokerageRecordServiceImpl.java | 151 ++++++++++++++ .../service/user/MemberUserService.java | 24 +++ .../service/user/MemberUserServiceImpl.java | 22 ++ .../MemberBrokerageRecordServiceImplTest.java | 116 +++++++++++ .../src/test/resources/sql/clean.sql | 3 +- .../src/test/resources/sql/create_tables.sql | 23 ++- 23 files changed, 1068 insertions(+), 2 deletions(-) create mode 100644 sql/mysql/brokerage.sql create mode 100644 yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/BrokerageApi.java create mode 100644 yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/dto/BrokerageAddReqDTO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/BrokerageApiImpl.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/MemberBrokerageRecordController.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/vo/MemberBrokerageRecordBaseVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/vo/MemberBrokerageRecordPageReqVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/vo/MemberBrokerageRecordRespVO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/brokerage/record/MemberBrokerageRecordConvert.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/brokerage/record/MemberBrokerageRecordDO.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordService.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImpl.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImplTest.java diff --git a/sql/mysql/brokerage.sql b/sql/mysql/brokerage.sql new file mode 100644 index 000000000..187e07621 --- /dev/null +++ b/sql/mysql/brokerage.sql @@ -0,0 +1,189 @@ +-- 增加配置 +alter table member_point_config + add column brokerage_enabled bit default 1 not null comment '是否启用分佣'; +alter table member_point_config + add column brokerage_enabled_condition tinyint default 0 not null comment '分佣模式:0-人人分销 1-指定分销'; +alter table member_point_config + add column brokerage_bind_mode tinyint default 0 not null comment '分销关系绑定模式: 0-没有推广人,1-新用户'; +alter table member_point_config + add column brokerage_post_urls varchar(2000) null comment '分销海报图地址数组'; +alter table member_point_config + add column brokerage_first_percent int not null comment '一级返佣比例'; +alter table member_point_config + add column brokerage_second_percent int not null comment '二级返佣比例'; +alter table member_point_config + add column brokerage_withdraw_min_price int not null comment '用户提现最低金额'; +alter table member_point_config + add column brokerage_bank_names varchar(200) not null comment '提现银行(字典类型=brokerage_bank_name)'; +alter table member_point_config + add column brokerage_frozen_days int default 7 not null comment '佣金冻结时间(天)'; +alter table member_point_config + add column brokerage_withdraw_type varchar(32) default '1,2,3,4' not null comment '提现方式:1-钱包;2-银行卡;3-微信;4-支付宝'; + +-- 用户表增加分销相关字段 +alter table member_user + add column brokerage_user_id bigint not null comment '推广员编号'; +alter table member_user + add column brokerage_bind_time datetime null comment '推广员绑定时间'; +alter table member_user + add column brokerage_enabled bit default 1 not null comment '是否成为推广员'; +alter table member_user + add column brokerage_time datetime null comment '成为分销员时间'; +alter table member_user + add column brokerage_price int default 0 not null comment '可用佣金'; +alter table member_user + add column frozen_brokerage_price int default 0 not null comment '冻结佣金'; + +create index idx_invite_user_id on member_user (brokerage_user_id) comment '推广员编号'; +create index idx_agent on member_user (brokerage_enabled) comment '是否成为推广员'; + + +create table member_brokerage_record +( + id int auto_increment comment '编号' + primary key, + user_id bigint not null comment '用户编号', + biz_id varchar(64) default '' not null comment '业务编号', + biz_type tinyint default 0 not null comment '业务类型:0-订单,1-提现', + title varchar(64) default '' not null comment '标题', + price int default 0 not null comment '金额', + total_price int default 0 not null comment '当前总佣金', + description varchar(500) default '' not null comment '说明', + status tinyint default 0 not null comment '状态:0-待结算,1-已结算,2-已取消', + frozen_days int default 0 not null comment '冻结时间(天)', + unfreeze_time datetime null comment '解冻时间', + creator varchar(64) collate utf8mb4_general_ci default '' null comment '创建者', + create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间', + updater varchar(64) collate utf8mb4_general_ci default '' null comment '更新者', + update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间', + deleted bit default b'0' not null comment '是否删除', + tenant_id bigint default 0 not null comment '租户编号' +) + comment '佣金记录'; + +create index idx_user_id on member_brokerage_record (user_id) comment '用户编号'; +create index idx_biz on member_brokerage_record (biz_type, biz_id) comment '业务'; +create index idx_status on member_brokerage_record (status) comment '状态'; + + +create table member_brokerage_withdraw +( + id int auto_increment comment '编号' + primary key, + user_id bigint not null comment '用户编号', + price int default 0 not null comment '提现金额', + fee_price int default 0 not null comment '提现手续费', + total_price int default 0 not null comment '当前总佣金', + type tinyint default 0 not null comment '提现类型:1-钱包;2-银行卡;3-微信;4-支付宝', + name varchar(64) null comment '真实姓名', + account_no varchar(64) null comment '账号', + bank_name varchar(100) null comment '银行名称', + bank_address varchar(200) null comment '开户地址', + account_qr_code_url varchar(512) null comment '收款码', + status tinyint(2) default 0 not null comment '状态:0-审核中,10-审核通过 20-审核不通过;预留:11 - 提现成功;21-提现失败', + audit_reason varchar(128) null comment '审核驳回原因', + audit_time datetime null comment '审核时间', + remark varchar(500) null comment '备注', + creator varchar(64) collate utf8mb4_general_ci default '' null comment '创建者', + create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间', + updater varchar(64) collate utf8mb4_general_ci default '' null comment '更新者', + update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间', + deleted bit default b'0' not null comment '是否删除', + tenant_id bigint default 0 not null comment '租户编号' +) + comment '佣金提现'; + +create index idx_user_id on member_brokerage_withdraw (user_id) comment '用户编号'; +create index idx_audit_status on member_brokerage_withdraw (status) comment '状态'; + +-- 增加字典 +insert into system_dict_type(type, name) +values ('brokerage_enabled_condition', '分佣模式'); +insert into system_dict_data(dict_type, label, value, sort, remark) +values ('brokerage_enabled_condition', '人人分销', 0, 0, '所有用户都可以分销'), + ('brokerage_enabled_condition', '指定分销', 1, 1, '仅可后台手动设置推广员'); + +insert into system_dict_type(type, name) +values ('brokerage_bind_mode', '分销关系绑定模式'); +insert into system_dict_data(dict_type, label, value, sort, remark) +values ('brokerage_bind_mode', '没有推广人', 0, 0, '只要用户没有推广人,随时都可以绑定推广关系'), + ('brokerage_bind_mode', '新用户', 1, 1, '仅新用户注册时才能绑定推广关系'); + +insert into system_dict_type(type, name) +values ('brokerage_withdraw_type', '佣金提现类型'); +insert into system_dict_data(dict_type, label, value, sort) +values ('brokerage_withdraw_type', '钱包', 1, 1), + ('brokerage_withdraw_type', '银行卡', 2, 2), + ('brokerage_withdraw_type', '微信', 3, 3), + ('brokerage_withdraw_type', '支付宝', 4, 4); + +insert into system_dict_type(type, name) +values ('brokerage_record_biz_type', '佣金记录业务类型'); +insert into system_dict_data(dict_type, label, value, sort) +values ('brokerage_record_biz_type', '订单返佣', 0, 0), + ('brokerage_record_biz_type', '申请提现', 1, 1); + +insert into system_dict_type(type, name) +values ('brokerage_record_status', '佣金记录状态'); +insert into system_dict_data(dict_type, label, value, sort) +values ('brokerage_record_status', '待结算', 0, 0), + ('brokerage_record_status', '已结算', 1, 1), + ('brokerage_record_status', '已取消', 2, 2); + +insert into system_dict_type(type, name) +values ('brokerage_withdraw_status', '佣金提现状态'); +insert into system_dict_data(dict_type, label, value, sort) +values ('brokerage_withdraw_status', '审核中', 0, 0), + ('brokerage_withdraw_status', '审核通过', 10, 10), + ('brokerage_withdraw_status', '提现成功', 11, 11), + ('brokerage_withdraw_status', '审核不通过', 20, 20), + ('brokerage_withdraw_status', '提现失败', 21, 21); + +insert into system_dict_type(type, name) +values ('brokerage_bank_name', '佣金提现银行'); +insert into system_dict_data(dict_type, label, value, sort) +values ('brokerage_bank_name', '工商银行', 0, 0), + ('brokerage_bank_name', '建设银行', 1, 1), + ('brokerage_bank_name', '农业银行', 2, 2), + ('brokerage_bank_name', '中国银行', 3, 3), + ('brokerage_bank_name', '交通银行', 4, 4), + ('brokerage_bank_name', '招商银行', 5, 5); + +-- 增加菜单:分销员管理 +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name) +VALUES ('分销员', '', 2, 7, 2262, 'brokerage', 'user', 'member/brokerage/user/index', 0, 'MemberBrokerageUser'); +-- 按钮父菜单ID +SELECT @parentId := LAST_INSERT_ID(); +-- 按钮 SQL +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES ('分销员查询', 'member:brokerage-user:query', 3, 1, @parentId, '', '', '', 0); +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES ('分销员创建', 'member:brokerage-user:create', 3, 2, @parentId, '', '', '', 0); +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES ('分销员更新', 'member:brokerage-user:update', 3, 3, @parentId, '', '', '', 0); +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES ('分销员删除', 'member:brokerage-user:delete', 3, 4, @parentId, '', '', '', 0); + +-- 增加菜单:佣金记录 +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name) +VALUES ('佣金记录', '', 2, 8, 2262, 'brokerage-record', 'list', 'member/brokerage/record/index', 0, + 'MemberBrokerageRecord'); +-- 按钮父菜单ID +-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码 +SELECT @parentId := LAST_INSERT_ID(); +-- 按钮 SQL +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES ('佣金记录查询', 'member:member-brokerage-record:query', 3, 1, @parentId, '', 'table', '', 0); + +-- 增加菜单:佣金提现 +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name) +VALUES ('佣金提现', '', 2, 9, 2262, 'brokerage-withdraw', '', 'member/brokerage/withdraw/index', 0, + 'MemberBrokerageWithdraw'); + +-- 按钮父菜单ID +-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码 +SELECT @parentId := LAST_INSERT_ID(); + +-- 按钮 SQL +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES ('佣金提现查询', 'member:brokerage-withdraw:query', 3, 1, @parentId, '', '', '', 0); diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java index 20f84f87c..2899fc075 100644 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java +++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java @@ -60,4 +60,13 @@ public class ProductSkuRespDTO { */ private Double volume; + /** + * 一级分销的佣金,单位:分 + */ + private Integer subCommissionFirstPrice; + /** + * 二级分销的佣金,单位:分 + */ + private Integer subCommissionSecondPrice; + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java index df7b296f0..e46ce66b6 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java @@ -7,11 +7,13 @@ import cn.iocoder.yudao.framework.common.util.string.StrUtils; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; +import cn.iocoder.yudao.module.member.api.brokerage.dto.BrokerageAddReqDTO; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; import cn.iocoder.yudao.module.pay.enums.DictTypeConstants; import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO; @@ -273,4 +275,10 @@ public interface TradeOrderConvert { TradeOrderDO convert(TradeOrderRemarkReqVO reqVO); + default BrokerageAddReqDTO convert(TradeOrderItemDO item, ProductSkuRespDTO sku) { + return new BrokerageAddReqDTO().setBizId(String.valueOf(item.getId())) + .setPayPrice(item.getPayPrice()).setCount(item.getCount()) + .setSkuFirstBrokeragePrice(sku.getSubCommissionFirstPrice()) + .setSkuSecondBrokeragePrice(sku.getSubCommissionSecondPrice()); + } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index f887b71e8..afb125e08 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -12,6 +12,8 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.module.member.api.address.AddressApi; import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; +import cn.iocoder.yudao.module.member.api.brokerage.BrokerageApi; +import cn.iocoder.yudao.module.member.api.brokerage.dto.BrokerageAddReqDTO; import cn.iocoder.yudao.module.member.api.level.MemberLevelApi; import cn.iocoder.yudao.module.member.api.point.MemberPointApi; import cn.iocoder.yudao.module.member.api.user.MemberUserApi; @@ -118,6 +120,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @Resource private MemberPointApi memberPointApi; @Resource + private BrokerageApi brokerageApi; + @Resource private ProductCommentApi productCommentApi; @Resource @@ -365,6 +369,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { getSelf().addUserPointAsync(order.getUserId(), order.getPayPrice(), order.getId()); // 增加用户经验 getSelf().addUserExperienceAsync(order.getUserId(), order.getPayPrice(), order.getId()); + // 增加用户佣金 + getSelf().addBrokerageAsync(order.getUserId(), order.getId()); } /** @@ -742,6 +748,15 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { memberPointApi.addPoint(userId, -refundPrice, bizType, String.valueOf(afterSaleId)); } + + @Async + protected void addBrokerageAsync(Long userId, Long orderId) { + List orderItems = tradeOrderItemMapper.selectListByOrderId(orderId); + List list = convertList(orderItems, + item -> TradeOrderConvert.INSTANCE.convert(item, productSkuApi.getSku(item.getSkuId()))); + brokerageApi.addBrokerage(userId, list); + } + /** * 获得自身的代理对象,解决 AOP 生效问题 * diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/BrokerageApi.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/BrokerageApi.java new file mode 100644 index 000000000..d01ce5845 --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/BrokerageApi.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.member.api.brokerage; + +import cn.iocoder.yudao.module.member.api.brokerage.dto.BrokerageAddReqDTO; + +import java.util.List; + +/** + * 佣金 API 接口 + * + * @author owen + */ +public interface BrokerageApi { + + /** + * 增加佣金 + * + * @param userId 会员ID + * @param list 请求参数列表 + */ + void addBrokerage(Long userId, List list); + + /** + * 取消佣金 + * + * @param userId 会员ID + * @param bizId 业务编号 + */ + void cancelBrokerage(Long userId, String bizId); + +} diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/dto/BrokerageAddReqDTO.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/dto/BrokerageAddReqDTO.java new file mode 100644 index 000000000..c46645201 --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/dto/BrokerageAddReqDTO.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.member.api.brokerage.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 佣金 增加 Request DTO + * @author owen + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class BrokerageAddReqDTO { + /** + * 业务ID + */ + private String bizId; + /** + * 商品支付价格 + */ + private Integer payPrice; + /** + * SKU 一级佣金 + */ + private Integer skuFirstBrokeragePrice; + /** + * SKU 二级佣金 + */ + private Integer skuSecondBrokeragePrice; + /** + * 购买数量 + */ + private Integer count; +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/BrokerageApiImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/BrokerageApiImpl.java new file mode 100644 index 000000000..2891bdcc1 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/BrokerageApiImpl.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.member.api.brokerage; + +import cn.iocoder.yudao.module.member.api.brokerage.dto.BrokerageAddReqDTO; +import cn.iocoder.yudao.module.member.service.brokerage.record.MemberBrokerageRecordService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 佣金 API 实现类 + * + * @author owen + */ +@Service +@Validated +public class BrokerageApiImpl implements BrokerageApi { + + @Resource + private MemberBrokerageRecordService memberBrokerageRecordService; + + @Override + public void addBrokerage(Long userId, List list) { + memberBrokerageRecordService.addBrokerage(userId, list); + } + + @Override + public void cancelBrokerage(Long userId, String bizId) { + + } +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/MemberBrokerageRecordController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/MemberBrokerageRecordController.java new file mode 100644 index 000000000..92cb0ae1a --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/MemberBrokerageRecordController.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.member.controller.admin.brokerage.record; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; +import cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo.MemberBrokerageRecordRespVO; +import cn.iocoder.yudao.module.member.convert.brokerage.record.MemberBrokerageRecordConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; +import cn.iocoder.yudao.module.member.service.brokerage.record.MemberBrokerageRecordService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import javax.validation.Valid; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - 佣金记录") +@RestController +@RequestMapping("/member/member-brokerage-record") +@Validated +public class MemberBrokerageRecordController { + + @Resource + private MemberBrokerageRecordService memberBrokerageRecordService; + + @GetMapping("/get") + @Operation(summary = "获得佣金记录") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('member:member-brokerage-record:query')") + public CommonResult getMemberBrokerageRecord(@RequestParam("id") Integer id) { + MemberBrokerageRecordDO memberBrokerageRecord = memberBrokerageRecordService.getMemberBrokerageRecord(id); + return success(MemberBrokerageRecordConvert.INSTANCE.convert(memberBrokerageRecord)); + } + + @GetMapping("/page") + @Operation(summary = "获得佣金记录分页") + @PreAuthorize("@ss.hasPermission('member:member-brokerage-record:query')") + public CommonResult> getMemberBrokerageRecordPage(@Valid MemberBrokerageRecordPageReqVO pageVO) { + PageResult pageResult = memberBrokerageRecordService.getMemberBrokerageRecordPage(pageVO); + return success(MemberBrokerageRecordConvert.INSTANCE.convertPage(pageResult)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/vo/MemberBrokerageRecordBaseVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/vo/MemberBrokerageRecordBaseVO.java new file mode 100644 index 000000000..ef6762be1 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/vo/MemberBrokerageRecordBaseVO.java @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +/** + * 佣金记录 Base VO,提供给添加、修改、详细的子 VO 使用 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 + */ +@Data +public class MemberBrokerageRecordBaseVO { + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25973") + @NotNull(message = "用户编号不能为空") + private Long userId; + + @Schema(description = "业务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23353") + @NotNull(message = "业务编号不能为空") + private String bizId; + + @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "业务类型不能为空") + private Integer bizType; + + @Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "标题不能为空") + private String title; + + @Schema(description = "金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "28731") + @NotNull(message = "金额不能为空") + private Integer price; + + @Schema(description = "当前总佣金", requiredMode = Schema.RequiredMode.REQUIRED, example = "13226") + @NotNull(message = "当前总佣金不能为空") + private Integer totalPrice; + + @Schema(description = "说明", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对") + @NotNull(message = "说明不能为空") + private String description; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "状态不能为空") + private Integer status; + + @Schema(description = "冻结时间(天)", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "冻结时间(天)不能为空") + private Integer frozenDays; + + @Schema(description = "解冻时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime unfreezeTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/vo/MemberBrokerageRecordPageReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/vo/MemberBrokerageRecordPageReqVO.java new file mode 100644 index 000000000..04a9ed94c --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/vo/MemberBrokerageRecordPageReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 佣金记录分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberBrokerageRecordPageReqVO extends PageParam { + + @Schema(description = "用户编号", example = "25973") + private Long userId; + + @Schema(description = "业务类型", example = "1") + private Integer bizType; + + @Schema(description = "状态", example = "1") + private Integer status; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/vo/MemberBrokerageRecordRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/vo/MemberBrokerageRecordRespVO.java new file mode 100644 index 000000000..417b5320d --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/vo/MemberBrokerageRecordRespVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 佣金记录 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MemberBrokerageRecordRespVO extends MemberBrokerageRecordBaseVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28896") + private Integer id; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/brokerage/record/MemberBrokerageRecordConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/brokerage/record/MemberBrokerageRecordConvert.java new file mode 100644 index 000000000..d36ef1c03 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/brokerage/record/MemberBrokerageRecordConvert.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.member.convert.brokerage.record; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo.MemberBrokerageRecordRespVO; +import cn.iocoder.yudao.module.member.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageRecordBizTypeEnum; +import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageRecordStatusEnum; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 佣金记录 Convert + * + * @author owen + */ +@Mapper +public interface MemberBrokerageRecordConvert { + + MemberBrokerageRecordConvert INSTANCE = Mappers.getMapper(MemberBrokerageRecordConvert.class); + + MemberBrokerageRecordRespVO convert(MemberBrokerageRecordDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + default MemberBrokerageRecordDO convert(MemberUserDO user, String bizId, int brokerageFrozenDays, int brokerage, LocalDateTime unfreezeTime) { + return new MemberBrokerageRecordDO() + .setUserId(user.getId()) + .setBizType(BrokerageRecordBizTypeEnum.ORDER.getType()) + .setBizId(bizId) + .setPrice(brokerage) + .setTotalPrice(user.getBrokeragePrice()) + .setTitle(BrokerageRecordBizTypeEnum.ORDER.getTitle()) + .setDescription(StrUtil.format(BrokerageRecordBizTypeEnum.ORDER.getDescription(), String.valueOf(brokerage / 100.0))) + .setStatus(BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus()) + .setFrozenDays(brokerageFrozenDays) + .setUnfreezeTime(unfreezeTime); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/brokerage/record/MemberBrokerageRecordDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/brokerage/record/MemberBrokerageRecordDO.java new file mode 100644 index 000000000..88e6ba7d9 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/brokerage/record/MemberBrokerageRecordDO.java @@ -0,0 +1,78 @@ +package cn.iocoder.yudao.module.member.dal.dataobject.brokerage.record; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageRecordBizTypeEnum; +import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageRecordStatusEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.time.LocalDateTime; + +/** + * 佣金记录 DO + * + * @author owen + */ +@TableName("member_brokerage_record") +@KeySequence("member_brokerage_record_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MemberBrokerageRecordDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Integer id; + /** + * 用户编号 + */ + private Long userId; + /** + * 业务编号 + */ + private String bizId; + /** + * 业务类型 + *

+ * 枚举 {@link BrokerageRecordBizTypeEnum 对应的类} + */ + private Integer bizType; + /** + * 标题 + */ + private String title; + /** + * 金额 + */ + private Integer price; + /** + * 当前总佣金 + */ + private Integer totalPrice; + /** + * 说明 + */ + private String description; + /** + * 状态 + *

+ * 枚举 {@link BrokerageRecordStatusEnum 对应的类} + */ + private Integer status; + /** + * 冻结时间(天) + */ + private Integer frozenDays; + /** + * 解冻时间 + */ + private LocalDateTime unfreezeTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java index 520d5a7d1..8e6c99aac 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java @@ -136,4 +136,31 @@ public class MemberUserDO extends TenantBaseDO { */ private Long groupId; + // ========== 分销相关 ========== + + /** + * 推广员编号 + */ + private Long brokerageUserId; + /** + * 推广员绑定时间 + */ + private LocalDateTime brokerageBindTime; + /** + * 是否成为推广员 + */ + private Boolean brokerageEnabled; + /** + * 成为分销员时间 + */ + private LocalDateTime brokerageTime; + /** + * 可用佣金 + */ + private Integer brokeragePrice; + /** + * 冻结佣金 + */ + private Integer frozenBrokeragePrice; + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java new file mode 100644 index 000000000..52f85c1a1 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.member.dal.mysql.brokerage.record; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 佣金记录 Mapper + * + * @author owen + */ +@Mapper +public interface MemberBrokerageRecordMapper extends BaseMapperX { + + default PageResult selectPage(MemberBrokerageRecordPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MemberBrokerageRecordDO::getUserId, reqVO.getUserId()) + .eqIfPresent(MemberBrokerageRecordDO::getBizType, reqVO.getBizType()) + .eqIfPresent(MemberBrokerageRecordDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(MemberBrokerageRecordDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(MemberBrokerageRecordDO::getId)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java index 902057272..39a7307c1 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java @@ -1,12 +1,14 @@ package cn.iocoder.yudao.module.member.dal.mysql.user; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserPageReqVO; import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; import java.util.List; @@ -62,4 +64,32 @@ public interface MemberUserMapper extends BaseMapperX { .apply("FIND_IN_SET({0}, tag_ids)", tagId)); } + /** + * 更新用户可用佣金(增加) + * + * @param id 用户编号 + * @param incrCount 增加佣金(正数) + */ + default void updateBrokeragePriceIncr(Long id, int incrCount) { + Assert.isTrue(incrCount > 0); + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() + .setSql(" brokerage_price = brokerage_price + " + incrCount) + .eq(MemberUserDO::getId, id); + update(null, lambdaUpdateWrapper); + } + + /** + * 更新用户冻结佣金(增加) + * + * @param id 用户编号 + * @param incrCount 增加冻结佣金(正数) + */ + default void updateFrozenBrokeragePriceIncr(Long id, int incrCount) { + Assert.isTrue(incrCount > 0); + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() + .setSql(" frozen_brokerage_price = frozen_brokerage_price + " + incrCount) + .eq(MemberUserDO::getId, id); + update(null, lambdaUpdateWrapper); + } + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordService.java new file mode 100644 index 000000000..16b82f78f --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordService.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.member.service.brokerage.record; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.api.brokerage.dto.BrokerageAddReqDTO; +import cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; + +import java.util.List; + +/** + * 佣金记录 Service 接口 + * + * @author owen + */ +public interface MemberBrokerageRecordService { + + /** + * 获得佣金记录 + * + * @param id 编号 + * @return 佣金记录 + */ + MemberBrokerageRecordDO getMemberBrokerageRecord(Integer id); + + /** + * 获得佣金记录分页 + * + * @param pageReqVO 分页查询 + * @return 佣金记录分页 + */ + PageResult getMemberBrokerageRecordPage(MemberBrokerageRecordPageReqVO pageReqVO); + + /** + * 增加佣金 + * + * @param userId 会员ID + * @param list 请求参数列表 + */ + void addBrokerage(Long userId, List list); +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImpl.java new file mode 100644 index 000000000..80c753fb5 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImpl.java @@ -0,0 +1,151 @@ +package cn.iocoder.yudao.module.member.service.brokerage.record; + +import cn.hutool.core.util.BooleanUtil; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.api.brokerage.dto.BrokerageAddReqDTO; +import cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; +import cn.iocoder.yudao.module.member.convert.brokerage.record.MemberBrokerageRecordConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; +import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointConfigDO; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import cn.iocoder.yudao.module.member.dal.mysql.brokerage.record.MemberBrokerageRecordMapper; +import cn.iocoder.yudao.module.member.service.point.MemberPointConfigService; +import cn.iocoder.yudao.module.member.service.user.MemberUserService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.math.RoundingMode; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +/** + * 佣金记录 Service 实现类 + * + * @author owen + */ +@Slf4j +@Service +@Validated +public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordService { + + @Resource + private MemberBrokerageRecordMapper memberBrokerageRecordMapper; + @Resource + private MemberPointConfigService memberConfigService; + @Resource + private MemberUserService memberUserService; + + @Override + public MemberBrokerageRecordDO getMemberBrokerageRecord(Integer id) { + return memberBrokerageRecordMapper.selectById(id); + } + + @Override + public PageResult getMemberBrokerageRecordPage(MemberBrokerageRecordPageReqVO pageReqVO) { + return memberBrokerageRecordMapper.selectPage(pageReqVO); + } + + @Override + public void addBrokerage(Long buyerId, List list) { + MemberPointConfigDO memberConfig = memberConfigService.getPointConfig(); + // 0 未启用分销功能 + if (memberConfig == null || !BooleanUtil.isTrue(memberConfig.getBrokerageEnabled())) { + log.warn("[addBrokerage][增加佣金失败:brokerageEnabled 未配置,buyerId({})", buyerId); + return; + } + + // 1.1 获得一级推广人 + MemberUserDO firstUser = memberUserService.getBrokerageUser(buyerId); + if (firstUser == null || !BooleanUtil.isTrue(firstUser.getBrokerageEnabled())) { + return; + } + + // 1.2 计算一级分佣 + addBrokerage(firstUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageFirstPercent(), BrokerageAddReqDTO::getSkuFirstBrokeragePrice); + + + // 2.1 获得二级推广员 + MemberUserDO secondUser = memberUserService.getUser(firstUser.getBrokerageUserId()); + if (secondUser == null || !BooleanUtil.isTrue(secondUser.getBrokerageEnabled())) { + return; + } + + // 2.2 计算二级分佣 + addBrokerage(secondUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageSecondPercent(), BrokerageAddReqDTO::getSkuSecondBrokeragePrice); + } + + /** + * 计算佣金 + * + * @param payPrice 订单支付金额 + * @param percent 商品 SKU 设置的佣金 + * @param skuBrokeragePrice 商品的佣金 + * @return 佣金 + */ + int calculateBrokerage(Integer payPrice, Integer percent, Integer skuBrokeragePrice) { + // 1. 优先使用商品 SKU 设置的佣金 + if (skuBrokeragePrice != null && skuBrokeragePrice > 0) { + return ObjectUtil.defaultIfNull(skuBrokeragePrice, 0); + } + + // 2. 根据订单支付金额计算佣金 + if (payPrice != null && payPrice > 0 && percent != null && percent > 0) { + return NumberUtil.div(NumberUtil.mul(payPrice, percent), 100, 0, RoundingMode.DOWN).intValue(); + } + + return 0; + } + + /** + * 增加用户佣金 + * + * @param user 用户 + * @param list 佣金增加参数列表 + * @param brokerageFrozenDays 冻结天数 + * @param brokeragePercent 佣金比例 + * @param skuBrokeragePriceFun 商品 SKU 设置的佣金 + */ + private void addBrokerage(MemberUserDO user, List list, Integer brokerageFrozenDays, + Integer brokeragePercent, Function skuBrokeragePriceFun) { + // 处理冻结时间 + brokerageFrozenDays = ObjectUtil.defaultIfNull(brokerageFrozenDays, 0); + LocalDateTime unfreezeTime = null; + if (brokerageFrozenDays > 0) { + unfreezeTime = LocalDateTime.now().plusDays(brokerageFrozenDays); + } + + // 计算分佣 + int totalBrokerage = 0; + List records = new ArrayList<>(); + for (BrokerageAddReqDTO dto : list) { + int brokeragePerItem = calculateBrokerage(dto.getPayPrice(), brokeragePercent, skuBrokeragePriceFun.apply(dto)); + if (brokeragePerItem > 0) { + int brokerage = brokeragePerItem * dto.getCount(); + records.add(MemberBrokerageRecordConvert.INSTANCE.convert(user, dto.getBizId(), brokerageFrozenDays, brokerage, unfreezeTime)); + totalBrokerage += brokerage; + } + } + + if (records.isEmpty()) { + return; + } + + // 保存佣金记录 + memberBrokerageRecordMapper.insertBatch(records); + + if (brokerageFrozenDays > 0) { + // 更新用户冻结佣金 + memberUserService.updateUserFrozenBrokeragePrice(user.getId(), totalBrokerage); + } else { + // 更新用户可用佣金 + memberUserService.updateUserBrokeragePrice(user.getId(), totalBrokerage); + } + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java index f1a0a7265..206f9f1c7 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java @@ -166,4 +166,28 @@ public interface MemberUserService { * @param point 积分数量 */ void updateUserPoint(Long userId, Integer point); + + /** + * 获得用户的推广人 + * + * @param id 用户编号 + * @return 用户的推广人 + */ + MemberUserDO getBrokerageUser(Long id); + + /** + * 增加用户佣金 + * + * @param id 用户编号 + * @param brokeragePrice 用户可用佣金 + */ + void updateUserBrokeragePrice(Long id, int brokeragePrice); + + /** + * 增加用户佣金 + * + * @param id 用户编号 + * @param frozenBrokeragePrice 用户冻结佣金 + */ + void updateUserFrozenBrokeragePrice(Long id, int frozenBrokeragePrice); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java index c5b674cc8..db80661c6 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java @@ -30,6 +30,7 @@ import javax.validation.Valid; import java.time.LocalDateTime; import java.util.Collection; import java.util.List; +import java.util.Optional; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; @@ -259,4 +260,25 @@ public class MemberUserServiceImpl implements MemberUserService { memberUserMapper.updateById(new MemberUserDO().setId(userId).setPoint(point)); } + @Override + public MemberUserDO getBrokerageUser(Long id) { + return Optional.ofNullable(id) + .map(this::getUser) + .map(MemberUserDO::getBrokerageUserId) + .map(this::getUser) + .orElse(null); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateUserBrokeragePrice(Long id, int brokeragePrice) { + memberUserMapper.updateBrokeragePriceIncr(id, brokeragePrice); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateUserFrozenBrokeragePrice(Long id, int frozenBrokeragePrice) { + memberUserMapper.updateFrozenBrokeragePriceIncr(id, frozenBrokeragePrice); + } + } diff --git a/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImplTest.java b/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImplTest.java new file mode 100644 index 000000000..d5991b4e8 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImplTest.java @@ -0,0 +1,116 @@ +package cn.iocoder.yudao.module.member.service.brokerage.record; + +import cn.hutool.core.util.NumberUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; +import cn.iocoder.yudao.module.member.dal.mysql.brokerage.record.MemberBrokerageRecordMapper; +import cn.iocoder.yudao.module.member.service.point.MemberPointConfigService; +import cn.iocoder.yudao.module.member.service.user.MemberUserService; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.math.RoundingMode; + +import static cn.hutool.core.util.RandomUtil.randomEle; +import static cn.hutool.core.util.RandomUtil.randomInt; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomInteger; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * {@link MemberBrokerageRecordServiceImpl} 的单元测试类 + * + * @author owen + */ +@Import(MemberBrokerageRecordServiceImpl.class) +public class MemberBrokerageRecordServiceImplTest extends BaseDbUnitTest { + + @Resource + private MemberBrokerageRecordServiceImpl memberBrokerageRecordService; + @Resource + private MemberBrokerageRecordMapper memberBrokerageRecordMapper; + + @MockBean + private MemberPointConfigService memberPointConfigService; + @MockBean + private MemberUserService memberUserService; + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetMemberBrokerageRecordPage() { + // mock 数据 + MemberBrokerageRecordDO dbMemberBrokerageRecord = randomPojo(MemberBrokerageRecordDO.class, o -> { // 等会查询到 + o.setUserId(null); + o.setBizType(null); + o.setStatus(null); + o.setCreateTime(null); + }); + memberBrokerageRecordMapper.insert(dbMemberBrokerageRecord); + // 测试 userId 不匹配 + memberBrokerageRecordMapper.insert(cloneIgnoreId(dbMemberBrokerageRecord, o -> o.setUserId(null))); + // 测试 bizType 不匹配 + memberBrokerageRecordMapper.insert(cloneIgnoreId(dbMemberBrokerageRecord, o -> o.setBizType(null))); + // 测试 status 不匹配 + memberBrokerageRecordMapper.insert(cloneIgnoreId(dbMemberBrokerageRecord, o -> o.setStatus(null))); + // 测试 createTime 不匹配 + memberBrokerageRecordMapper.insert(cloneIgnoreId(dbMemberBrokerageRecord, o -> o.setCreateTime(null))); + // 准备参数 + MemberBrokerageRecordPageReqVO reqVO = new MemberBrokerageRecordPageReqVO(); + reqVO.setUserId(null); + reqVO.setBizType(null); + reqVO.setStatus(null); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + PageResult pageResult = memberBrokerageRecordService.getMemberBrokerageRecordPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbMemberBrokerageRecord, pageResult.getList().get(0)); + } + + @Test + public void testCalculateBrokerage_useSkuBrokeragePrice() { + // mock 数据 + Integer payPrice = randomInteger(); + Integer percent = randomInt(1, 101); + Integer skuBrokeragePrice = randomInt(); + // 调用 + int brokerage = memberBrokerageRecordService.calculateBrokerage(payPrice, percent, skuBrokeragePrice); + // 断言 + assertEquals(brokerage, skuBrokeragePrice); + } + + @Test + public void testCalculateBrokerage_usePercent() { + // mock 数据 + Integer payPrice = randomInteger(); + Integer percent = randomInt(1, 101); + Integer skuBrokeragePrice = randomEle(new Integer[]{0, null}); + System.out.println("skuBrokeragePrice=" + skuBrokeragePrice); + // 调用 + int brokerage = memberBrokerageRecordService.calculateBrokerage(payPrice, percent, skuBrokeragePrice); + // 断言 + assertEquals(brokerage, NumberUtil.div(NumberUtil.mul(payPrice, percent), 100, 0, RoundingMode.DOWN).intValue()); + } + + @Test + public void testCalculateBrokerage_equalsZero() { + // mock 数据 + Integer payPrice = null; + Integer percent = null; + Integer skuBrokeragePrice = null; + // 调用 + int brokerage = memberBrokerageRecordService.calculateBrokerage(payPrice, percent, skuBrokeragePrice); + // 断言 + assertEquals(brokerage, 0); + } +} diff --git a/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/clean.sql b/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/clean.sql index f972e048d..6981982c4 100644 --- a/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/clean.sql +++ b/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/clean.sql @@ -2,4 +2,5 @@ DELETE FROM "member_user"; DELETE FROM "member_address"; DELETE FROM "member_tag"; DELETE FROM "member_level"; -DELETE FROM "member_group"; \ No newline at end of file +DELETE FROM "member_group"; +DELETE FROM "member_brokerage_record"; \ No newline at end of file diff --git a/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/create_tables.sql b/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/create_tables.sql index 5fdc526b0..ccefc4bf1 100644 --- a/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/create_tables.sql +++ b/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/create_tables.sql @@ -89,4 +89,25 @@ CREATE TABLE IF NOT EXISTS "member_group" "deleted" bit NOT NULL DEFAULT FALSE, "tenant_id" bigint not null default '0', PRIMARY KEY ("id") -) COMMENT '用户分组'; \ No newline at end of file +) COMMENT '用户分组'; +CREATE TABLE IF NOT EXISTS "member_brokerage_record" +( + "id" int NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "user_id" bigint NOT NULL, + "biz_id" varchar NOT NULL, + "biz_type" varchar NOT NULL, + "title" varchar NOT NULL, + "price" int NOT NULL, + "total_price" int NOT NULL, + "description" varchar NOT NULL, + "status" varchar NOT NULL, + "frozen_days" int NOT NULL, + "unfreeze_time" varchar, + "creator" varchar DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint not null default '0', + PRIMARY KEY ("id") +) COMMENT '佣金记录'; \ No newline at end of file From 090058a2ba16bee4f9321dcf7a9839c78c4cf2a2 Mon Sep 17 00:00:00 2001 From: owen Date: Tue, 5 Sep 2023 09:27:12 +0800 Subject: [PATCH 09/50] =?UTF-8?q?member:=20=E4=BD=A3=E9=87=91=E4=B8=8D?= =?UTF-8?q?=E5=86=BB=E7=BB=93=E6=97=B6=EF=BC=8C=E7=9B=B4=E6=8E=A5=E5=B0=B1?= =?UTF-8?q?=E6=98=AF=E7=BB=93=E7=AE=97=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../brokerage/record/MemberBrokerageRecordConvert.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/brokerage/record/MemberBrokerageRecordConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/brokerage/record/MemberBrokerageRecordConvert.java index d36ef1c03..393bacb72 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/brokerage/record/MemberBrokerageRecordConvert.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/brokerage/record/MemberBrokerageRecordConvert.java @@ -30,6 +30,10 @@ public interface MemberBrokerageRecordConvert { PageResult convertPage(PageResult page); default MemberBrokerageRecordDO convert(MemberUserDO user, String bizId, int brokerageFrozenDays, int brokerage, LocalDateTime unfreezeTime) { + // 不冻结时,佣金直接就是结算状态 + Integer status = brokerageFrozenDays > 0 + ? BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus() + : BrokerageRecordStatusEnum.SETTLEMENT.getStatus(); return new MemberBrokerageRecordDO() .setUserId(user.getId()) .setBizType(BrokerageRecordBizTypeEnum.ORDER.getType()) @@ -38,7 +42,7 @@ public interface MemberBrokerageRecordConvert { .setTotalPrice(user.getBrokeragePrice()) .setTitle(BrokerageRecordBizTypeEnum.ORDER.getTitle()) .setDescription(StrUtil.format(BrokerageRecordBizTypeEnum.ORDER.getDescription(), String.valueOf(brokerage / 100.0))) - .setStatus(BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus()) + .setStatus(status) .setFrozenDays(brokerageFrozenDays) .setUnfreezeTime(unfreezeTime); } From f3ca0f066b64d43c3b35c9b204e135a18c9529c9 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Tue, 5 Sep 2023 12:44:34 +0800 Subject: [PATCH 10/50] =?UTF-8?q?=E4=BC=9A=E5=91=98=E9=92=B1=E5=8C=85=20?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E8=AE=A2=E5=8D=95=E5=92=8C=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E9=80=80=E6=AC=BE=E5=8D=95=E7=9A=84=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wallet/PayWalletTransactionMapper.java | 5 +- .../framework/pay/wallet/WalletPayClient.java | 75 ++++++++++++++++++- .../pay/service/wallet/PayWalletService.java | 4 +- .../service/wallet/PayWalletServiceImpl.java | 6 +- .../wallet/PayWalletTransactionService.java | 4 +- .../PayWalletTransactionServiceImpl.java | 6 +- 6 files changed, 81 insertions(+), 19 deletions(-) diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletTransactionMapper.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletTransactionMapper.java index 3d329d118..7831e77bd 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletTransactionMapper.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletTransactionMapper.java @@ -30,9 +30,8 @@ public interface PayWalletTransactionMapper extends BaseMapperX { private PayWalletService wallService; + private PayWalletTransactionService walletTransactionService; + + private PayOrderService payOrderService; + + private PayRefundService payRefundService; + public WalletPayClient(Long channelId, NonePayClientConfig config) { super(channelId, PayChannelEnum.WALLET.getCode(), config); } @@ -38,6 +54,9 @@ public class WalletPayClient extends AbstractPayClient { if (wallService == null) { wallService = SpringUtil.getBean(PayWalletService.class); } + if (walletTransactionService == null) { + walletTransactionService = SpringUtil.getBean(PayWalletTransactionService.class); + } } @Override @@ -47,7 +66,7 @@ public class WalletPayClient extends AbstractPayClient { String userType = MapUtil.getStr(reqDTO.getChannelExtras(), "user_type"); Assert.notEmpty(userId, "用户 id 不能为空"); Assert.notEmpty(userType, "用户类型不能为空"); - PayWalletTransactionDO transaction = wallService.pay(Long.valueOf(userId), Integer.valueOf(userType), + PayWalletTransactionDO transaction = wallService.orderPay(Long.valueOf(userId), Integer.valueOf(userType), reqDTO.getOutTradeNo(), reqDTO.getPrice()); return PayOrderRespDTO.successOf(transaction.getNo(), transaction.getCreator(), transaction.getCreateTime(), @@ -73,13 +92,37 @@ public class WalletPayClient extends AbstractPayClient { @Override protected PayOrderRespDTO doGetOrder(String outTradeNo) { - throw new UnsupportedOperationException("待实现"); + if (payOrderService == null) { + payOrderService = SpringUtil.getBean(PayOrderService.class); + } + PayOrderExtensionDO orderExtension = payOrderService.getOrderExtensionByNo(outTradeNo); + // 支付交易拓展单不存在, 返回关闭状态 + if (orderExtension == null) { + return PayOrderRespDTO.closedOf(String.valueOf(ORDER_EXTENSION_NOT_FOUND.getCode()), + ORDER_EXTENSION_NOT_FOUND.getMsg(), outTradeNo, ""); + } + // 关闭状态 + if (PayOrderStatusEnum.isClosed(orderExtension.getStatus())) { + return PayOrderRespDTO.closedOf(orderExtension.getChannelErrorCode(), + orderExtension.getChannelErrorMsg(), outTradeNo, ""); + } + // 成功状态 + if (PayOrderStatusEnum.isSuccess(orderExtension.getStatus())) { + PayWalletTransactionDO walletTransaction = walletTransactionService.getWalletTransaction( + String.valueOf(orderExtension.getOrderId()), PayWalletBizTypeEnum.PAYMENT); + Assert.notNull(walletTransaction, "支付单 {} 钱包流水不能为空", outTradeNo); + return PayOrderRespDTO.successOf(walletTransaction.getNo(), walletTransaction.getCreator(), + walletTransaction.getCreateTime(), outTradeNo, walletTransaction); + } + // 其它状态为无效状态 + log.error("[doGetOrder] 支付单 {} 的状态不正确", outTradeNo); + throw new IllegalStateException(String.format("支付单[%s] 状态不正确", outTradeNo)); } @Override protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) { try { - PayWalletTransactionDO payWalletTransaction = wallService.refund(reqDTO.getOutRefundNo(), + PayWalletTransactionDO payWalletTransaction = wallService.orderRefund(reqDTO.getOutRefundNo(), reqDTO.getRefundPrice(), reqDTO.getReason()); return PayRefundRespDTO.successOf(payWalletTransaction.getNo(), payWalletTransaction.getCreateTime(), reqDTO.getOutRefundNo(), payWalletTransaction); @@ -104,7 +147,31 @@ public class WalletPayClient extends AbstractPayClient { @Override protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) { - throw new UnsupportedOperationException("待实现"); + if (payRefundService == null) { + payRefundService = SpringUtil.getBean(PayRefundService.class); + } + PayRefundDO payRefund = payRefundService.getRefundByNo(outRefundNo); + // 支付退款单不存在, 返回退款失败状态 + if (payRefund == null) { + return PayRefundRespDTO.failureOf(String.valueOf(REFUND_NOT_FOUND), REFUND_NOT_FOUND.getMsg(), + outRefundNo, ""); + } + // 退款失败 + if (PayRefundStatusRespEnum.isFailure(payRefund.getStatus())) { + return PayRefundRespDTO.failureOf(payRefund.getChannelErrorCode(), payRefund.getChannelErrorMsg(), + outRefundNo, ""); + } + // 退款成功 + if (PayRefundStatusRespEnum.isSuccess(payRefund.getStatus())) { + PayWalletTransactionDO walletTransaction = walletTransactionService.getWalletTransaction( + String.valueOf(payRefund.getId()), PayWalletBizTypeEnum.PAYMENT_REFUND); + Assert.notNull(walletTransaction, "支付退款单 {} 钱包流水不能为空", outRefundNo); + return PayRefundRespDTO.successOf(walletTransaction.getNo(), walletTransaction.getCreateTime(), + outRefundNo, walletTransaction); + } + // 其它状态为无效状态 + log.error("[doGetRefund] 支付退款单 {} 的状态不正确", outRefundNo); + throw new IllegalStateException(String.format("支付退款单[%s] 状态不正确", outRefundNo)); } } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java index 370b776a7..3ea75ad09 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java @@ -27,7 +27,7 @@ public interface PayWalletService { * @param outTradeNo 外部订单号 * @param price 金额 */ - PayWalletTransactionDO pay(Long userId, Integer userType, String outTradeNo, Integer price); + PayWalletTransactionDO orderPay(Long userId, Integer userType, String outTradeNo, Integer price); /** @@ -64,6 +64,6 @@ public interface PayWalletService { * @param refundPrice 退款金额 * @param reason 退款原因 */ - PayWalletTransactionDO refund(String outRefundNo, Integer refundPrice, String reason); + PayWalletTransactionDO orderRefund(String outRefundNo, Integer refundPrice, String reason); } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java index a3606323b..ea607c0e8 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java @@ -75,7 +75,7 @@ public class PayWalletServiceImpl implements PayWalletService { @Override @Transactional(rollbackFor = Exception.class) - public PayWalletTransactionDO pay(Long userId, Integer userType, String outTradeNo, Integer price) { + public PayWalletTransactionDO orderPay(Long userId, Integer userType, String outTradeNo, Integer price) { // 判断支付交易拓展单是否存 PayOrderExtensionDO orderExtension = payOrderService.getOrderExtensionByNo(outTradeNo); if (orderExtension == null) { @@ -150,7 +150,7 @@ public class PayWalletServiceImpl implements PayWalletService { @Override @Transactional(rollbackFor = Exception.class) - public PayWalletTransactionDO refund(String outRefundNo, Integer refundPrice, String reason) { + public PayWalletTransactionDO orderRefund(String outRefundNo, Integer refundPrice, String reason) { // 1.1 判断退款单是否存在 PayRefundDO payRefund = payRefundService.getRefundByNo(outRefundNo); if (payRefund == null) { @@ -182,7 +182,7 @@ public class PayWalletServiceImpl implements PayWalletService { throw exception(WALLET_REFUND_AMOUNT_ERROR); } PayWalletTransactionDO refundTransaction = payWalletTransactionService.getWalletTransaction( - payWalletTransaction.getWalletId(), refundId, PAYMENT_REFUND); + String.valueOf(refundId), PAYMENT_REFUND); if (refundTransaction != null) { throw exception(WALLET_REFUND_EXIST); } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionService.java index e0714081b..432e2f2e0 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionService.java @@ -40,11 +40,9 @@ public interface PayWalletTransactionService { /** * 获取钱包流水 * - * @param walletId 钱包编号 * @param bizId 业务编号 * @param type 业务类型 * @return 钱包流水 */ - PayWalletTransactionDO getWalletTransaction(Long walletId, Long bizId, PayWalletBizTypeEnum type); - + PayWalletTransactionDO getWalletTransaction(String bizId, PayWalletBizTypeEnum type); } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java index 1b156576a..971f59416 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java @@ -22,7 +22,6 @@ public class PayWalletTransactionServiceImpl implements PayWalletTransactionServ @Resource private PayWalletService payWalletService; - @Resource private PayWalletTransactionMapper payWalletTransactionMapper; @@ -45,8 +44,7 @@ public class PayWalletTransactionServiceImpl implements PayWalletTransactionServ } @Override - public PayWalletTransactionDO getWalletTransaction(Long walletId, Long bizId, PayWalletBizTypeEnum type) { - return payWalletTransactionMapper.selectByWalletIdAndBiz(walletId, bizId, type.getType()); + public PayWalletTransactionDO getWalletTransaction(String bizId, PayWalletBizTypeEnum type) { + return payWalletTransactionMapper.selectByBiz(bizId, type.getType()); } - } From 2f6092005b09aac72896f67adab6716aa2363083 Mon Sep 17 00:00:00 2001 From: owen Date: Tue, 5 Sep 2023 18:54:00 +0800 Subject: [PATCH 11/50] =?UTF-8?q?member:=20=E4=BD=A3=E9=87=91=E8=A7=A3?= =?UTF-8?q?=E5=86=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/enums/ErrorCodeConstants.java | 1 + .../record/MemberBrokerageRecordMapper.java | 15 +++++ .../dal/mysql/user/MemberUserMapper.java | 16 ++++++ .../MemberBrokerageRecordUnfreezeJob.java | 29 ++++++++++ .../record/MemberBrokerageRecordService.java | 8 +++ .../MemberBrokerageRecordServiceImpl.java | 57 +++++++++++++++++++ .../service/user/MemberUserService.java | 4 +- .../service/user/MemberUserServiceImpl.java | 9 ++- 8 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/job/brokerage/MemberBrokerageRecordUnfreezeJob.java diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java index ba283ab0c..dc6439e74 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java @@ -13,6 +13,7 @@ public interface ErrorCodeConstants { ErrorCode USER_NOT_EXISTS = new ErrorCode(1004001000, "用户不存在"); ErrorCode USER_MOBILE_NOT_EXISTS = new ErrorCode(1004001001, "手机号未注册用户"); ErrorCode USER_MOBILE_USED = new ErrorCode(1004001002, "修改手机失败,该手机号({})已经被使用"); + ErrorCode MEMBER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH = new ErrorCode(1004001003, "用户冻结佣金({})数量不足"); // ========== AUTH 模块 1004003000 ========== ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1004003000, "登录失败,账号密码不正确"); diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java index 52f85c1a1..fd3ce05fc 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java @@ -5,8 +5,12 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; import cn.iocoder.yudao.module.member.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; +import java.time.LocalDateTime; +import java.util.List; + /** * 佣金记录 Mapper * @@ -24,4 +28,15 @@ public interface MemberBrokerageRecordMapper extends BaseMapperX selectListByStatusAndUnfreezeTimeLt(Integer status, LocalDateTime unfreezeTime) { + return selectList(new LambdaQueryWrapper() + .eq(MemberBrokerageRecordDO::getStatus, status) + .lt(MemberBrokerageRecordDO::getUnfreezeTime, unfreezeTime)); + } + + default int updateByIdAndStatus(Integer id, Integer status, MemberBrokerageRecordDO updateObj) { + return update(updateObj, new LambdaQueryWrapper() + .eq(MemberBrokerageRecordDO::getId, id) + .eq(MemberBrokerageRecordDO::getStatus, status)); + } } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java index 39a7307c1..cafe10285 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java @@ -92,4 +92,20 @@ public interface MemberUserMapper extends BaseMapperX { update(null, lambdaUpdateWrapper); } + /** + * 更新用户冻结佣金(减少) + * + * @param id 用户编号 + * @param incrCount 减少冻结佣金(负数) + * @return 更新条数 + */ + default int updateFrozenBrokeragePriceDecr(Long id, int incrCount) { + Assert.isTrue(incrCount < 0); + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() + .setSql(" frozen_brokerage_price = frozen_brokerage_price + " + incrCount + // 负数,所以使用 + 号 + ", brokerage_price = brokerage_price + " + -incrCount) // 负数,所以使用 - 号 + .eq(MemberUserDO::getId, id) + .ge(MemberUserDO::getFrozenBrokeragePrice, -incrCount); // cas 逻辑 + return update(null, lambdaUpdateWrapper); + } } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/job/brokerage/MemberBrokerageRecordUnfreezeJob.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/job/brokerage/MemberBrokerageRecordUnfreezeJob.java new file mode 100644 index 000000000..f4512cf08 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/job/brokerage/MemberBrokerageRecordUnfreezeJob.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.member.job.brokerage; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; +import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; +import cn.iocoder.yudao.module.member.service.brokerage.record.MemberBrokerageRecordService; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * 佣金解冻 Job + * + * @author owen + */ +@Component +@TenantJob +public class MemberBrokerageRecordUnfreezeJob implements JobHandler { + + @Resource + private MemberBrokerageRecordService memberBrokerageRecordService; + + @Override + public String execute(String param) { + int count = memberBrokerageRecordService.unfreezeRecord(); + return StrUtil.format("解冻佣金 {} 个", count); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordService.java index 16b82f78f..1d0f4e816 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordService.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordService.java @@ -37,4 +37,12 @@ public interface MemberBrokerageRecordService { * @param list 请求参数列表 */ void addBrokerage(Long userId, List list); + + /** + * 解冻佣金:将待结算的佣金记录,状态修改为已结算 + * + * @return 解冻佣金的数量 + */ + int unfreezeRecord(); + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImpl.java index 80c753fb5..58dc25af5 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImpl.java @@ -1,8 +1,10 @@ package cn.iocoder.yudao.module.member.service.brokerage.record; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.BooleanUtil; import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.member.api.brokerage.dto.BrokerageAddReqDTO; import cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; @@ -11,10 +13,12 @@ import cn.iocoder.yudao.module.member.dal.dataobject.brokerage.record.MemberBrok import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointConfigDO; import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; import cn.iocoder.yudao.module.member.dal.mysql.brokerage.record.MemberBrokerageRecordMapper; +import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageRecordStatusEnum; import cn.iocoder.yudao.module.member.service.point.MemberPointConfigService; import cn.iocoder.yudao.module.member.service.user.MemberUserService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; @@ -52,6 +56,7 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe } @Override + @Transactional(rollbackFor = Exception.class) public void addBrokerage(Long buyerId, List list) { MemberPointConfigDO memberConfig = memberConfigService.getPointConfig(); // 0 未启用分销功能 @@ -148,4 +153,56 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe } } + @Override + public int unfreezeRecord() { + // 1. 查询待结算的佣金记录 + List records = memberBrokerageRecordMapper.selectListByStatusAndUnfreezeTimeLt( + BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus(), LocalDateTime.now()); + if (CollUtil.isEmpty(records)) { + return 0; + } + + // 2. 遍历执行 + int count = 0; + for (MemberBrokerageRecordDO record : records) { + try { + boolean successful = getSelf().unfreezeRecord(record); + if (successful) { + count++; + } + } catch (Exception e) { + log.error("[unfreezeRecord][record({}) 更新为已结算失败]", record.getId(), e); + } + } + return count; + } + + @Transactional(rollbackFor = Exception.class) + public boolean unfreezeRecord(MemberBrokerageRecordDO record) { + // 更新记录状态 + MemberBrokerageRecordDO updateObj = new MemberBrokerageRecordDO() + .setStatus(BrokerageRecordStatusEnum.SETTLEMENT.getStatus()) + .setUnfreezeTime(LocalDateTime.now()); + int updateRows = memberBrokerageRecordMapper.updateByIdAndStatus(record.getId(), record.getStatus(), updateObj); + if (updateRows == 0) { + log.error("[unfreezeRecord][record({}) 更新为已结算失败]", record.getId()); + return false; + } + + // 更新用户冻结佣金 + memberUserService.updateUserFrozenBrokeragePrice(record.getUserId(), record.getPrice()); + + log.info("[unfreezeRecord][record({}) 更新为已结算成功]", record.getId()); + return true; + } + + /** + * 获得自身的代理对象,解决 AOP 生效问题 + * + * @return 自己 + */ + private MemberBrokerageRecordServiceImpl getSelf() { + return SpringUtil.getBean(getClass()); + } + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java index 206f9f1c7..380ad2c6c 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java @@ -176,7 +176,7 @@ public interface MemberUserService { MemberUserDO getBrokerageUser(Long id); /** - * 增加用户佣金 + * 更新用户佣金 * * @param id 用户编号 * @param brokeragePrice 用户可用佣金 @@ -184,7 +184,7 @@ public interface MemberUserService { void updateUserBrokeragePrice(Long id, int brokeragePrice); /** - * 增加用户佣金 + * 更新用户冻结佣金 * * @param id 用户编号 * @param frozenBrokeragePrice 用户冻结佣金 diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java index db80661c6..0bd17facf 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java @@ -278,7 +278,14 @@ public class MemberUserServiceImpl implements MemberUserService { @Override @Transactional(rollbackFor = Exception.class) public void updateUserFrozenBrokeragePrice(Long id, int frozenBrokeragePrice) { - memberUserMapper.updateFrozenBrokeragePriceIncr(id, frozenBrokeragePrice); + if (frozenBrokeragePrice > 0) { + memberUserMapper.updateFrozenBrokeragePriceIncr(id, frozenBrokeragePrice); + } else if (frozenBrokeragePrice < 0) { + int updateRows = memberUserMapper.updateFrozenBrokeragePriceDecr(id, frozenBrokeragePrice); + if (updateRows == 0) { + throw exception(MEMBER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH); + } + } } } From a708521b9d010bb960eb3434c8007df7ead9e21f Mon Sep 17 00:00:00 2001 From: owen Date: Tue, 5 Sep 2023 19:05:01 +0800 Subject: [PATCH 12/50] =?UTF-8?q?member:=20=E4=BD=A3=E9=87=91=E8=A7=A3?= =?UTF-8?q?=E5=86=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../brokerage/record/MemberBrokerageRecordServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImpl.java index 58dc25af5..c3d6bcebc 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImpl.java @@ -190,7 +190,7 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe } // 更新用户冻结佣金 - memberUserService.updateUserFrozenBrokeragePrice(record.getUserId(), record.getPrice()); + memberUserService.updateUserFrozenBrokeragePrice(record.getUserId(), -record.getPrice()); log.info("[unfreezeRecord][record({}) 更新为已结算成功]", record.getId()); return true; From 9eb7837b67c0ed8b9d4e85efac33372a0a79ae27 Mon Sep 17 00:00:00 2001 From: owen Date: Tue, 5 Sep 2023 19:43:07 +0800 Subject: [PATCH 13/50] =?UTF-8?q?member:=20=E4=BD=A3=E9=87=91=E5=A4=B1?= =?UTF-8?q?=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../order/TradeOrderUpdateServiceImpl.java | 9 ++++-- .../api/brokerage/BrokerageApiImpl.java | 2 +- .../record/MemberBrokerageRecordMapper.java | 5 +++ .../dal/mysql/user/MemberUserMapper.java | 32 ++++++++++++++++++- .../record/MemberBrokerageRecordService.java | 10 ++++-- .../MemberBrokerageRecordServiceImpl.java | 26 ++++++++++++++- .../service/user/MemberUserService.java | 8 +++++ .../service/user/MemberUserServiceImpl.java | 22 ++++++++++--- 8 files changed, 102 insertions(+), 12 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index afb125e08..e2a0f6baf 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -635,12 +635,12 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { .setRefundStatus(TradeOrderRefundStatusEnum.PART.getStatus()).setRefundPrice(orderRefundPrice)); } - // TODO 芋艿:未来如果有分佣,需要更新相关分佣订单为已失效 - // 扣减用户积分 getSelf().reduceUserPointAsync(order.getUserId(), orderRefundPrice, afterSaleId); // 扣减用户经验 getSelf().reduceUserExperienceAsync(order.getUserId(), orderRefundPrice, afterSaleId); + // 更新分佣记录为已失效 + getSelf().cancelBrokerageAsync(order.getUserId(), id); } @Override @@ -757,6 +757,11 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { brokerageApi.addBrokerage(userId, list); } + @Async + protected void cancelBrokerageAsync(Long userId, Long orderItemId) { + brokerageApi.cancelBrokerage(userId, String.valueOf(orderItemId)); + } + /** * 获得自身的代理对象,解决 AOP 生效问题 * diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/BrokerageApiImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/BrokerageApiImpl.java index 2891bdcc1..662c5165a 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/BrokerageApiImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/BrokerageApiImpl.java @@ -27,6 +27,6 @@ public class BrokerageApiImpl implements BrokerageApi { @Override public void cancelBrokerage(Long userId, String bizId) { - + memberBrokerageRecordService.cancelBrokerage(userId, bizId); } } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java index fd3ce05fc..52154aea5 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java @@ -39,4 +39,9 @@ public interface MemberBrokerageRecordMapper extends BaseMapperX { update(null, lambdaUpdateWrapper); } + /** + * 更新用户可用佣金(减少) + * 注意:理论上佣金可能已经提现,这时会扣出负数,确保平台不会造成损失 + * + * @param id 用户编号 + * @param incrCount 增加佣金(负数) + */ + default void updateBrokeragePriceDecr(Long id, int incrCount) { + Assert.isTrue(incrCount < 0); + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() + .setSql(" brokerage_price = brokerage_price + " + incrCount) // 负数,所以使用 + 号 + .eq(MemberUserDO::getId, id); + update(null, lambdaUpdateWrapper); + } + /** * 更新用户冻结佣金(增加) * @@ -94,12 +109,27 @@ public interface MemberUserMapper extends BaseMapperX { /** * 更新用户冻结佣金(减少) + * 注意:理论上冻结佣金可能已经解冻,这时会扣出负数,确保平台不会造成损失 + * + * @param id 用户编号 + * @param incrCount 减少冻结佣金(负数) + */ + default void updateFrozenBrokeragePriceDecr(Long id, int incrCount) { + Assert.isTrue(incrCount < 0); + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() + .setSql(" frozen_brokerage_price = frozen_brokerage_price + " + incrCount) // 负数,所以使用 + 号 + .eq(MemberUserDO::getId, id); + update(null, lambdaUpdateWrapper); + } + + /** + * 更新用户冻结佣金(减少), 更新用户佣金(增加) * * @param id 用户编号 * @param incrCount 减少冻结佣金(负数) * @return 更新条数 */ - default int updateFrozenBrokeragePriceDecr(Long id, int incrCount) { + default int updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(Long id, int incrCount) { Assert.isTrue(incrCount < 0); LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() .setSql(" frozen_brokerage_price = frozen_brokerage_price + " + incrCount + // 负数,所以使用 + 号 diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordService.java index 1d0f4e816..cd966e670 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordService.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordService.java @@ -33,16 +33,22 @@ public interface MemberBrokerageRecordService { /** * 增加佣金 * - * @param userId 会员ID + * @param userId 会员编号 * @param list 请求参数列表 */ void addBrokerage(Long userId, List list); + /** + * 取消佣金:将佣金记录,状态修改为已失效 + * @param userId 会员编号 + * @param bizId 业务编号 + */ + void cancelBrokerage(Long userId, String bizId); + /** * 解冻佣金:将待结算的佣金记录,状态修改为已结算 * * @return 解冻佣金的数量 */ int unfreezeRecord(); - } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImpl.java index c3d6bcebc..32656910c 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImpl.java @@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.member.dal.dataobject.brokerage.record.MemberBrok import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointConfigDO; import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; import cn.iocoder.yudao.module.member.dal.mysql.brokerage.record.MemberBrokerageRecordMapper; +import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageRecordBizTypeEnum; import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageRecordStatusEnum; import cn.iocoder.yudao.module.member.service.point.MemberPointConfigService; import cn.iocoder.yudao.module.member.service.user.MemberUserService; @@ -85,6 +86,29 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe addBrokerage(secondUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageSecondPercent(), BrokerageAddReqDTO::getSkuSecondBrokeragePrice); } + @Override + @Transactional(rollbackFor = Exception.class) + public void cancelBrokerage(Long userId, String bizId) { + MemberBrokerageRecordDO record = memberBrokerageRecordMapper.selectByUserIdAndBizTypeAndBizId(BrokerageRecordBizTypeEnum.ORDER.getType(), bizId); + if (record == null || ObjectUtil.notEqual(record.getUserId(), userId)) { + log.error("[cancelBrokerage][userId({})][bizId({}) 更新为已失效失败:记录不存在]", userId, bizId); + return; + } + + MemberBrokerageRecordDO updateObj = new MemberBrokerageRecordDO().setStatus(BrokerageRecordStatusEnum.CANCEL.getStatus()); + int updateRows = memberBrokerageRecordMapper.updateByIdAndStatus(record.getId(), record.getStatus(), updateObj); + if (updateRows == 0) { + log.error("[cancelBrokerage][record({}) 更新为已失效失败]", record.getId()); + return; + } + + if (BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus().equals(record.getStatus())) { + memberUserService.updateUserFrozenBrokeragePrice(userId, -record.getPrice()); + } else if (BrokerageRecordStatusEnum.SETTLEMENT.getStatus().equals(record.getStatus())) { + memberUserService.updateUserBrokeragePrice(userId, -record.getPrice()); + } + } + /** * 计算佣金 * @@ -190,7 +214,7 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe } // 更新用户冻结佣金 - memberUserService.updateUserFrozenBrokeragePrice(record.getUserId(), -record.getPrice()); + memberUserService.updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(record.getUserId(), -record.getPrice()); log.info("[unfreezeRecord][record({}) 更新为已结算成功]", record.getId()); return true; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java index 380ad2c6c..7f599a049 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java @@ -190,4 +190,12 @@ public interface MemberUserService { * @param frozenBrokeragePrice 用户冻结佣金 */ void updateUserFrozenBrokeragePrice(Long id, int frozenBrokeragePrice); + + /** + * 更新用户冻结佣金(减少), 更新用户佣金(增加) + * + * @param id 用户编号 + * @param frozenBrokeragePrice 减少冻结佣金(负数) + */ + void updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(Long id, int frozenBrokeragePrice); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java index 0bd17facf..53b452d7c 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.member.service.user; +import cn.hutool.core.lang.Assert; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; @@ -272,7 +273,11 @@ public class MemberUserServiceImpl implements MemberUserService { @Override @Transactional(rollbackFor = Exception.class) public void updateUserBrokeragePrice(Long id, int brokeragePrice) { - memberUserMapper.updateBrokeragePriceIncr(id, brokeragePrice); + if (brokeragePrice > 0) { + memberUserMapper.updateBrokeragePriceIncr(id, brokeragePrice); + } else if (brokeragePrice < 0) { + memberUserMapper.updateBrokeragePriceDecr(id, brokeragePrice); + } } @Override @@ -281,10 +286,17 @@ public class MemberUserServiceImpl implements MemberUserService { if (frozenBrokeragePrice > 0) { memberUserMapper.updateFrozenBrokeragePriceIncr(id, frozenBrokeragePrice); } else if (frozenBrokeragePrice < 0) { - int updateRows = memberUserMapper.updateFrozenBrokeragePriceDecr(id, frozenBrokeragePrice); - if (updateRows == 0) { - throw exception(MEMBER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH); - } + memberUserMapper.updateFrozenBrokeragePriceDecr(id, frozenBrokeragePrice); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(Long id, int frozenBrokeragePrice) { + Assert.isTrue(frozenBrokeragePrice < 0); + int updateRows = memberUserMapper.updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(id, frozenBrokeragePrice); + if (updateRows == 0) { + throw exception(MEMBER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH); } } From 0329f13fbf89c2026b2ab590d461f1f6c94e7224 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 5 Sep 2023 21:32:34 +0800 Subject: [PATCH 14/50] =?UTF-8?q?=E5=88=86=E4=BD=A3=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=8E=B7=E5=BE=97=E5=88=86=E9=94=80=E6=8E=92=E8=A1=8C?= =?UTF-8?q?=E5=88=86=E9=A1=B5=20API=20mock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AppBrokerageRecordController.java | 8 +- .../brokerage/AppBrokerageUserController.java | 93 +++++++++++++++++++ .../AppBrokerageWithdrawController.java | 6 +- .../record/AppBrokerageRecordPageReqVO.java | 2 +- .../vo/record/AppBrokerageRecordRespVO.java | 2 +- .../AppBrokerageUserRankByPriceRespVO.java | 22 +++++ ...AppBrokerageUserRankByUserCountRespVO.java | 6 +- .../user/AppBrokerageUserRankPageReqVO.java | 2 +- .../user/AppBrokerageUserSummaryRespVO.java | 2 +- .../withdraw/AppBrokerageWithdrawRespVO.java | 2 +- .../brokerage/AppBrokerageUserController.java | 59 ------------ 11 files changed, 130 insertions(+), 74 deletions(-) rename {yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member => yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade}/controller/app/brokerage/AppBrokerageRecordController.java (84%) create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java rename {yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member => yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade}/controller/app/brokerage/AppBrokerageWithdrawController.java (87%) rename {yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member => yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade}/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java (88%) rename {yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member => yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade}/controller/app/brokerage/vo/record/AppBrokerageRecordRespVO.java (92%) create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByPriceRespVO.java rename yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/user/AppBrokerageUserRankRespVO.java => yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByUserCountRespVO.java (75%) rename {yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member => yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade}/controller/app/brokerage/vo/user/AppBrokerageUserRankPageReqVO.java (91%) rename {yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member => yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade}/controller/app/brokerage/vo/user/AppBrokerageUserSummaryRespVO.java (92%) rename {yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member => yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade}/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawRespVO.java (92%) delete mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageUserController.java diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageRecordController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageRecordController.java similarity index 84% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageRecordController.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageRecordController.java index 8cf4d81e8..d4c72028f 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageRecordController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageRecordController.java @@ -1,10 +1,10 @@ -package cn.iocoder.yudao.module.member.controller.app.brokerage; +package cn.iocoder.yudao.module.trade.controller.app.brokerage; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; -import cn.iocoder.yudao.module.member.controller.app.brokerage.vo.record.AppBrokerageRecordPageReqVO; -import cn.iocoder.yudao.module.member.controller.app.brokerage.vo.record.AppBrokerageRecordRespVO; +import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordPageReqVO; +import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordRespVO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; @@ -21,7 +21,7 @@ import static java.util.Arrays.asList; @Tag(name = "用户 APP - 分销用户") @RestController -@RequestMapping("/member/brokerage-record") +@RequestMapping("/trade/brokerage-record") @Validated @Slf4j public class AppBrokerageRecordController { diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java new file mode 100644 index 000000000..dd3d17ff7 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.trade.controller.app.brokerage; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; +import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankByPriceRespVO; +import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankByUserCountRespVO; +import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankPageReqVO; +import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserSummaryRespVO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static java.util.Arrays.asList; + +@Tag(name = "用户 APP - 分销用户") +@RestController +@RequestMapping("/trade/brokerage-user") +@Validated +@Slf4j +public class AppBrokerageUserController { + + // TODO 芋艿:临时 mock => + @GetMapping("/get-summary") + @Operation(summary = "获得个人分销统计") + @PreAuthenticated + public CommonResult getBrokerageUserSummary() { + AppBrokerageUserSummaryRespVO respVO = new AppBrokerageUserSummaryRespVO() + .setYesterdayBrokeragePrice(1) + .setBrokeragePrice(2) + .setFrozenBrokeragePrice(3) + .setWithdrawBrokeragePrice(4); + return success(respVO); + } + + @GetMapping("/rank-page-by-user-count") + @Operation(summary = "获得分销用户排行分页(基于用户量)") + @PreAuthenticated + public CommonResult> getBrokerageUserRankPageByUserCount(AppBrokerageUserRankPageReqVO pageReqVO) { + AppBrokerageUserRankByUserCountRespVO vo1 = new AppBrokerageUserRankByUserCountRespVO() + .setUserId(1L).setNickname("芋1**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") + .setBrokerageUserCount(10); + AppBrokerageUserRankByUserCountRespVO vo2 = new AppBrokerageUserRankByUserCountRespVO() + .setUserId(2L).setNickname("芋2**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") + .setBrokerageUserCount(6); + AppBrokerageUserRankByUserCountRespVO vo3 = new AppBrokerageUserRankByUserCountRespVO() + .setUserId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") + .setBrokerageUserCount(4); + AppBrokerageUserRankByUserCountRespVO vo4 = new AppBrokerageUserRankByUserCountRespVO() + .setUserId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") + .setBrokerageUserCount(4); + return success(new PageResult<>(asList(vo1, vo2, vo3, vo4), 10L)); + } + + @GetMapping("/rank-page-by-price") + @Operation(summary = "获得分销用户排行分页(基于佣金)") + @PreAuthenticated + public CommonResult> getBrokerageUserRankPageByPrice(AppBrokerageUserRankPageReqVO pageReqVO) { + AppBrokerageUserRankByPriceRespVO vo1 = new AppBrokerageUserRankByPriceRespVO() + .setUserId(1L).setNickname("芋1**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") + .setBrokeragePrice(10); + AppBrokerageUserRankByPriceRespVO vo2 = new AppBrokerageUserRankByPriceRespVO() + .setUserId(2L).setNickname("芋2**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") + .setBrokeragePrice(6); + AppBrokerageUserRankByPriceRespVO vo3 = new AppBrokerageUserRankByPriceRespVO() + .setUserId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") + .setBrokeragePrice(4); + AppBrokerageUserRankByPriceRespVO vo4 = new AppBrokerageUserRankByPriceRespVO() + .setUserId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") + .setBrokeragePrice(4); + return success(new PageResult<>(asList(vo1, vo2, vo3, vo4), 10L)); + } + + @GetMapping("/get-rank-by-price") + @Operation(summary = "获得分销用户排行(基于佣金)") + @Parameter(name = "times", description = "时间段", required = true) + public CommonResult getBrokerageUserRankByPrice( + @RequestParam("times") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) LocalDateTime[] times) { + return success(1); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageWithdrawController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageWithdrawController.java similarity index 87% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageWithdrawController.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageWithdrawController.java index dde0a8a03..1f69b3593 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageWithdrawController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageWithdrawController.java @@ -1,9 +1,9 @@ -package cn.iocoder.yudao.module.member.controller.app.brokerage; +package cn.iocoder.yudao.module.trade.controller.app.brokerage; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; -import cn.iocoder.yudao.module.member.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawRespVO; +import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawRespVO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; @@ -19,7 +19,7 @@ import static java.util.Arrays.asList; @Tag(name = "用户 APP - 分销提现") @RestController -@RequestMapping("/member/brokerage-withdraw") +@RequestMapping("/trade/brokerage-withdraw") @Validated @Slf4j public class AppBrokerageWithdrawController { diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java similarity index 88% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java index c8bfabd5c..b7675e6ec 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.member.controller.app.brokerage.vo.record; +package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/record/AppBrokerageRecordRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordRespVO.java similarity index 92% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/record/AppBrokerageRecordRespVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordRespVO.java index 0459e15f9..221d19758 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/record/AppBrokerageRecordRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.member.controller.app.brokerage.vo.record; +package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByPriceRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByPriceRespVO.java new file mode 100644 index 000000000..28dab5f8f --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByPriceRespVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "用户 App - 分销排行用户(基于用户量) Response VO") +@Data +public class AppBrokerageUserRankByPriceRespVO { + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Long userId; + + @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小王") + private String nickname; + + @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://www.iocoder.cn/xxx.jpg") + private String avatar; + + @Schema(description = "佣金金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Integer brokeragePrice; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/user/AppBrokerageUserRankRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByUserCountRespVO.java similarity index 75% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/user/AppBrokerageUserRankRespVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByUserCountRespVO.java index 7835f5532..f0ea2e6c3 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/user/AppBrokerageUserRankRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByUserCountRespVO.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.module.member.controller.app.brokerage.vo.user; +package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -@Schema(description = "用户 App - 分销排行用户 Response VO") +@Schema(description = "用户 App - 分销排行用户(基于用户量) Response VO") @Data -public class AppBrokerageUserRankRespVO { +public class AppBrokerageUserRankByUserCountRespVO { @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") private Long userId; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/user/AppBrokerageUserRankPageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankPageReqVO.java similarity index 91% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/user/AppBrokerageUserRankPageReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankPageReqVO.java index 0ba1e9c75..de1d61a7b 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/user/AppBrokerageUserRankPageReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.member.controller.app.brokerage.vo.user; +package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/user/AppBrokerageUserSummaryRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserSummaryRespVO.java similarity index 92% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/user/AppBrokerageUserSummaryRespVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserSummaryRespVO.java index 635705253..5779d8010 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/user/AppBrokerageUserSummaryRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserSummaryRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.member.controller.app.brokerage.vo.user; +package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawRespVO.java similarity index 92% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawRespVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawRespVO.java index 3a3670097..4cfe930c8 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.member.controller.app.brokerage.vo.withdraw; +package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageUserController.java deleted file mode 100644 index 1b5bc6184..000000000 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/brokerage/AppBrokerageUserController.java +++ /dev/null @@ -1,59 +0,0 @@ -package cn.iocoder.yudao.module.member.controller.app.brokerage; - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; -import cn.iocoder.yudao.module.member.controller.app.brokerage.vo.user.AppBrokerageUserRankPageReqVO; -import cn.iocoder.yudao.module.member.controller.app.brokerage.vo.user.AppBrokerageUserRankRespVO; -import cn.iocoder.yudao.module.member.controller.app.brokerage.vo.user.AppBrokerageUserSummaryRespVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.extern.slf4j.Slf4j; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static java.util.Arrays.asList; - -@Tag(name = "用户 APP - 分销用户") -@RestController -@RequestMapping("/member/brokerage-user") -@Validated -@Slf4j -public class AppBrokerageUserController { - - // TODO 芋艿:临时 mock => - @GetMapping("/get-summary") - @Operation(summary = "获得个人分销统计") - @PreAuthenticated - public CommonResult getBrokerageUserSummary() { - AppBrokerageUserSummaryRespVO respVO = new AppBrokerageUserSummaryRespVO() - .setYesterdayBrokeragePrice(1) - .setBrokeragePrice(2) - .setFrozenBrokeragePrice(3) - .setWithdrawBrokeragePrice(4); - return success(respVO); - } - - @GetMapping("/rank-page") - @Operation(summary = "获得分销用户排行分页") - @PreAuthenticated - public CommonResult> getBrokerageUserRankPage(AppBrokerageUserRankPageReqVO pageReqVO) { - AppBrokerageUserRankRespVO vo1 = new AppBrokerageUserRankRespVO() - .setUserId(1L).setNickname("芋1**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") - .setBrokerageUserCount(10); - AppBrokerageUserRankRespVO vo2 = new AppBrokerageUserRankRespVO() - .setUserId(2L).setNickname("芋2**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") - .setBrokerageUserCount(6); - AppBrokerageUserRankRespVO vo3 = new AppBrokerageUserRankRespVO() - .setUserId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") - .setBrokerageUserCount(4); - AppBrokerageUserRankRespVO vo4 = new AppBrokerageUserRankRespVO() - .setUserId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") - .setBrokerageUserCount(4); - return success(new PageResult<>(asList(vo1, vo2, vo3, vo4), 10L)); - } - -} From 64745027380a7e4d99cda3d5af2d393c084171c5 Mon Sep 17 00:00:00 2001 From: owen Date: Tue, 5 Sep 2023 22:31:36 +0800 Subject: [PATCH 15/50] =?UTF-8?q?trade:=20=E5=A2=9E=E5=8A=A0=E4=BA=A4?= =?UTF-8?q?=E6=98=93=E4=B8=AD=E5=BF=83=E9=85=8D=E7=BD=AE=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/mysql/brokerage.sql | 55 +++++++----- .../admin/config/TradeConfigController.java | 45 ++++++++++ .../admin/config/vo/TradeConfigBaseVO.java | 71 +++++++++++++++ .../admin/config/vo/TradeConfigRespVO.java | 17 ++++ .../admin/config/vo/TradeConfigSaveReqVO.java | 14 +++ .../convert/config/TradeConfigConvert.java | 23 +++++ .../dal/dataobject/config/TradeConfigDO.java | 90 +++++++++++++++++++ .../dal/mysql/config/TradeConfigMapper.java | 15 ++++ .../service/config/TradeConfigService.java | 30 +++++++ .../config/TradeConfigServiceImpl.java | 44 +++++++++ 10 files changed, 384 insertions(+), 20 deletions(-) create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/TradeConfigController.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigBaseVO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigRespVO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigSaveReqVO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/config/TradeConfigConvert.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/config/TradeConfigDO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/config/TradeConfigMapper.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/config/TradeConfigService.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/config/TradeConfigServiceImpl.java diff --git a/sql/mysql/brokerage.sql b/sql/mysql/brokerage.sql index 187e07621..ed8c5fcbe 100644 --- a/sql/mysql/brokerage.sql +++ b/sql/mysql/brokerage.sql @@ -1,24 +1,25 @@ -- 增加配置 -alter table member_point_config - add column brokerage_enabled bit default 1 not null comment '是否启用分佣'; -alter table member_point_config - add column brokerage_enabled_condition tinyint default 0 not null comment '分佣模式:0-人人分销 1-指定分销'; -alter table member_point_config - add column brokerage_bind_mode tinyint default 0 not null comment '分销关系绑定模式: 0-没有推广人,1-新用户'; -alter table member_point_config - add column brokerage_post_urls varchar(2000) null comment '分销海报图地址数组'; -alter table member_point_config - add column brokerage_first_percent int not null comment '一级返佣比例'; -alter table member_point_config - add column brokerage_second_percent int not null comment '二级返佣比例'; -alter table member_point_config - add column brokerage_withdraw_min_price int not null comment '用户提现最低金额'; -alter table member_point_config - add column brokerage_bank_names varchar(200) not null comment '提现银行(字典类型=brokerage_bank_name)'; -alter table member_point_config - add column brokerage_frozen_days int default 7 not null comment '佣金冻结时间(天)'; -alter table member_point_config - add column brokerage_withdraw_type varchar(32) default '1,2,3,4' not null comment '提现方式:1-钱包;2-银行卡;3-微信;4-支付宝'; +create table trade_config +( + id bigint auto_increment comment '自增主键' + primary key, + brokerage_enabled bit default 1 not null comment '是否启用分佣', + brokerage_enabled_condition tinyint default 0 not null comment '分佣模式:0-人人分销 1-指定分销', + brokerage_bind_mode tinyint default 0 not null comment '分销关系绑定模式: 0-没有推广人,1-新用户', + brokerage_post_urls varchar(2000) default '' null comment '分销海报图地址数组', + brokerage_first_percent int default 0 not null comment '一级返佣比例', + brokerage_second_percent int default 0 not null comment '二级返佣比例', + brokerage_withdraw_min_price int default 0 not null comment '用户提现最低金额', + brokerage_bank_names varchar(200) default '' not null comment '提现银行(字典类型=brokerage_bank_name)', + brokerage_frozen_days int default 7 not null comment '佣金冻结时间(天)', + brokerage_withdraw_type varchar(32) default '1,2,3,4' not null comment '提现方式:1-钱包;2-银行卡;3-微信;4-支付宝', + creator varchar(64) collate utf8mb4_unicode_ci default '' null comment '创建者', + create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间', + updater varchar(64) collate utf8mb4_unicode_ci default '' null comment '更新者', + update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间', + deleted bit default b'0' not null comment '是否删除', + tenant_id bigint default 0 not null comment '租户编号' +) comment '交易中心配置'; -- 用户表增加分销相关字段 alter table member_user @@ -187,3 +188,17 @@ SELECT @parentId := LAST_INSERT_ID(); -- 按钮 SQL INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) VALUES ('佣金提现查询', 'member:brokerage-withdraw:query', 3, 1, @parentId, '', '', '', 0); + +-- 交易中心配置:菜单 SQL +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name) +VALUES ('交易中心配置', '', 2, 0, 2072, 'config', '', 'trade/config/index', 0, 'TradeConfig'); + +-- 按钮父菜单ID +-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码 +SELECT @parentId := LAST_INSERT_ID(); + +-- 按钮 SQL +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES ('交易中心配置查询', 'trade:config:query', 3, 1, @parentId, '', '', '', 0); +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES ('交易中心配置保存', 'trade:config:save', 3, 2, @parentId, '', '', '', 0); \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/TradeConfigController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/TradeConfigController.java new file mode 100644 index 000000000..e41f98081 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/TradeConfigController.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.trade.controller.admin.config; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.trade.controller.admin.config.vo.TradeConfigRespVO; +import cn.iocoder.yudao.module.trade.controller.admin.config.vo.TradeConfigSaveReqVO; +import cn.iocoder.yudao.module.trade.convert.config.TradeConfigConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; +import cn.iocoder.yudao.module.trade.service.config.TradeConfigService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - 交易中心配置") +@RestController +@RequestMapping("/trade/config") +@Validated +public class TradeConfigController { + + @Resource + private TradeConfigService tradeConfigService; + + @PutMapping("/save") + @Operation(summary = "更新交易中心配置") + @PreAuthorize("@ss.hasPermission('trade:config:save')") + public CommonResult updateConfig(@Valid @RequestBody TradeConfigSaveReqVO updateReqVO) { + tradeConfigService.saveTradeConfig(updateReqVO); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得交易中心配置") + @PreAuthorize("@ss.hasPermission('trade:config:query')") + public CommonResult getConfig() { + TradeConfigDO config = tradeConfigService.getTradeConfig(); + return success(TradeConfigConvert.INSTANCE.convert(config)); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigBaseVO.java new file mode 100644 index 000000000..4ee51e3b8 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigBaseVO.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.trade.controller.admin.config.vo; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageBindModeEnum; +import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageEnabledConditionEnum; +import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageWithdrawTypeEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.hibernate.validator.constraints.Range; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.PositiveOrZero; +import java.util.List; + +/** + * 交易中心配置 Base VO,提供给添加、修改、详细的子 VO 使用 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 + */ +@Data +public class TradeConfigBaseVO { + + // ========== 分销相关 ========== + + @Schema(description = "是否启用分佣", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "是否启用分佣不能为空") + private Boolean brokerageEnabled; + + @Schema(description = "分佣模式", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "分佣模式不能为空") + @InEnum(value = BrokerageEnabledConditionEnum.class, message = "分佣模式必须是 {value}") + private Integer brokerageEnabledCondition; + + @Schema(description = "分销关系绑定模式", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "分销关系绑定模式不能为空") + @InEnum(value = BrokerageBindModeEnum.class, message = "分销关系绑定模式必须是 {value}") + private Integer brokerageBindMode; + + @Schema(description = "分销海报图地址数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/yudao.jpg]") + private List brokeragePostUrls; + + @Schema(description = "一级返佣比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") + @NotNull(message = "一级返佣比例不能为空") + @Range(min = 0, max = 100, message = "一级返佣比例必须在 0 - 100 之间") + private Integer brokerageFirstPercent; + + @Schema(description = "二级返佣比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") + @NotNull(message = "二级返佣比例不能为空") + @Range(min = 0, max = 100, message = "二级返佣比例必须在 0 - 100 之间") + private Integer brokerageSecondPercent; + + @Schema(description = "用户提现最低金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") + @NotNull(message = "用户提现最低金额不能为空") + @PositiveOrZero(message = "用户提现最低金额不能是负数") + private Integer brokerageWithdrawMinPrice; + + @Schema(description = "提现银行", requiredMode = Schema.RequiredMode.REQUIRED, example = "[0, 1]") + @NotEmpty(message = "提现银行不能为空") + private List brokerageBankNames; + + @Schema(description = "佣金冻结时间(天)", requiredMode = Schema.RequiredMode.REQUIRED, example = "7") + @NotNull(message = "佣金冻结时间(天)不能为空") + @PositiveOrZero(message = "佣金冻结时间不能是负数") + private Integer brokerageFrozenDays; + + @Schema(description = "提现方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "[0, 1]") + @NotNull(message = "提现方式不能为空") + @InEnum(value = BrokerageWithdrawTypeEnum.class, message = "提现方式必须是 {value}") + private List brokerageWithdrawType; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigRespVO.java new file mode 100644 index 000000000..52aff751f --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigRespVO.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.trade.controller.admin.config.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - 交易中心配置 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class TradeConfigRespVO extends TradeConfigBaseVO { + + @Schema(description = "自增主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigSaveReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigSaveReqVO.java new file mode 100644 index 000000000..03a0c41df --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigSaveReqVO.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.trade.controller.admin.config.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - 交易中心配置更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class TradeConfigSaveReqVO extends TradeConfigBaseVO { + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/config/TradeConfigConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/config/TradeConfigConvert.java new file mode 100644 index 000000000..031f1198a --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/config/TradeConfigConvert.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.trade.convert.config; + +import cn.iocoder.yudao.module.trade.controller.admin.config.vo.TradeConfigRespVO; +import cn.iocoder.yudao.module.trade.controller.admin.config.vo.TradeConfigSaveReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * 交易中心配置 Convert + * + * @author owen + */ +@Mapper +public interface TradeConfigConvert { + + TradeConfigConvert INSTANCE = Mappers.getMapper(TradeConfigConvert.class); + + TradeConfigDO convert(TradeConfigSaveReqVO bean); + + TradeConfigRespVO convert(TradeConfigDO bean); + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/config/TradeConfigDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/config/TradeConfigDO.java new file mode 100644 index 000000000..5538186e1 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/config/TradeConfigDO.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.trade.dal.dataobject.config; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.framework.mybatis.core.type.IntegerListTypeHandler; +import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageBindModeEnum; +import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageEnabledConditionEnum; +import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageWithdrawTypeEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import lombok.*; + +import java.util.List; + +/** + * 交易中心配置 DO + * + * @author owen + */ +@TableName(value = "trade_config", autoResultMap = true) +@KeySequence("trade_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TradeConfigDO extends BaseDO { + + /** + * 自增主键 + */ + @TableId + private Long id; + + // ========== 分销相关 ========== + + /** + * 是否启用分佣 + */ + private Boolean brokerageEnabled; + /** + * 分佣模式 + *

+ * 枚举 {@link BrokerageEnabledConditionEnum 对应的类} + */ + private Integer brokerageEnabledCondition; + /** + * 分销关系绑定模式 + *

+ * 枚举 {@link BrokerageBindModeEnum 对应的类} + */ + private Integer brokerageBindMode; + /** + * 分销海报图地址数组 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List brokeragePostUrls; + /** + * 一级返佣比例 + */ + private Integer brokerageFirstPercent; + /** + * 二级返佣比例 + */ + private Integer brokerageSecondPercent; + /** + * 用户提现最低金额 + */ + private Integer brokerageWithdrawMinPrice; + /** + * 提现银行 + */ + @TableField(typeHandler = IntegerListTypeHandler.class) + private List brokerageBankNames; + /** + * 佣金冻结时间(天) + */ + private Integer brokerageFrozenDays; + /** + * 提现方式 + *

+ * 枚举 {@link BrokerageWithdrawTypeEnum 对应的类} + */ + @TableField(typeHandler = IntegerListTypeHandler.class) + private List brokerageWithdrawType; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/config/TradeConfigMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/config/TradeConfigMapper.java new file mode 100644 index 000000000..18a3f4df7 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/config/TradeConfigMapper.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.trade.dal.mysql.config; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 交易中心配置 Mapper + * + * @author owen + */ +@Mapper +public interface TradeConfigMapper extends BaseMapperX { + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/config/TradeConfigService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/config/TradeConfigService.java new file mode 100644 index 000000000..c00825f2e --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/config/TradeConfigService.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.trade.service.config; + +import cn.iocoder.yudao.module.trade.controller.admin.config.vo.TradeConfigSaveReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; + +import javax.validation.Valid; + +/** + * 交易中心配置 Service 接口 + * + * @author owen + */ +public interface TradeConfigService { + + + /** + * 更新交易中心配置 + * + * @param updateReqVO 更新信息 + */ + void saveTradeConfig(@Valid TradeConfigSaveReqVO updateReqVO); + + /** + * 获得交易中心配置 + * + * @return 交易中心配置 + */ + TradeConfigDO getTradeConfig(); + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/config/TradeConfigServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/config/TradeConfigServiceImpl.java new file mode 100644 index 000000000..c859cdee6 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/config/TradeConfigServiceImpl.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.trade.service.config; + +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.trade.controller.admin.config.vo.TradeConfigSaveReqVO; +import cn.iocoder.yudao.module.trade.convert.config.TradeConfigConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; +import cn.iocoder.yudao.module.trade.dal.mysql.config.TradeConfigMapper; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 交易中心配置 Service 实现类 + * + * @author owen + */ +@Service +@Validated +public class TradeConfigServiceImpl implements TradeConfigService { + + @Resource + private TradeConfigMapper tradeConfigMapper; + + @Override + public void saveTradeConfig(TradeConfigSaveReqVO saveReqVO) { + // 存在,则进行更新 + TradeConfigDO dbConfig = getTradeConfig(); + if (dbConfig != null) { + tradeConfigMapper.updateById(TradeConfigConvert.INSTANCE.convert(saveReqVO).setId(dbConfig.getId())); + return; + } + // 不存在,则进行插入 + tradeConfigMapper.insert(TradeConfigConvert.INSTANCE.convert(saveReqVO)); + } + + @Override + public TradeConfigDO getTradeConfig() { + List list = tradeConfigMapper.selectList(); + return CollectionUtils.getFirst(list); + } + +} From a68691f2d93623404628fce2d7f222c4240cec5d Mon Sep 17 00:00:00 2001 From: owen Date: Tue, 5 Sep 2023 23:45:53 +0800 Subject: [PATCH 16/50] =?UTF-8?q?trade:=20=E5=A2=9E=E5=8A=A0=E5=88=86?= =?UTF-8?q?=E9=94=80=E7=94=A8=E6=88=B7=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/mysql/brokerage.sql | 133 ++++++++++-------- .../trade/enums/ErrorCodeConstants.java | 4 + .../user/TradeBrokerageUserController.java | 71 ++++++++++ .../user/vo/TradeBrokerageUserBaseVO.java | 43 ++++++ ...eBrokerageUserClearBrokerageUserReqVO.java | 18 +++ .../user/vo/TradeBrokerageUserPageReqVO.java | 30 ++++ .../user/vo/TradeBrokerageUserRespVO.java | 22 +++ ...kerageUserUpdateBrokerageEnabledReqVO.java | 22 +++ ...BrokerageUserUpdateBrokerageUserReqVO.java | 22 +++ .../user/TradeBrokerageUserConvert.java | 27 ++++ .../brokerage/user/TradeBrokerageUserDO.java | 56 ++++++++ .../user/TradeBrokerageUserMapper.java | 26 ++++ .../user/TradeBrokerageUserService.java | 56 ++++++++ .../user/TradeBrokerageUserServiceImpl.java | 63 +++++++++ .../TradeBrokerageUserServiceImplTest.java | 64 +++++++++ .../src/test/resources/sql/clean.sql | 1 + .../src/test/resources/sql/create_tables.sql | 18 +++ 17 files changed, 616 insertions(+), 60 deletions(-) create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/TradeBrokerageUserController.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserBaseVO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserClearBrokerageUserReqVO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserPageReqVO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserRespVO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserUpdateBrokerageEnabledReqVO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserUpdateBrokerageUserReqVO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/TradeBrokerageUserConvert.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/TradeBrokerageUserDO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/TradeBrokerageUserMapper.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserService.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImpl.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImplTest.java diff --git a/sql/mysql/brokerage.sql b/sql/mysql/brokerage.sql index ed8c5fcbe..161dfa256 100644 --- a/sql/mysql/brokerage.sql +++ b/sql/mysql/brokerage.sql @@ -1,8 +1,7 @@ --- 增加配置 +-- 增加配置表 create table trade_config ( - id bigint auto_increment comment '自增主键' - primary key, + id bigint auto_increment comment '自增主键' primary key, brokerage_enabled bit default 1 not null comment '是否启用分佣', brokerage_enabled_condition tinyint default 0 not null comment '分佣模式:0-人人分销 1-指定分销', brokerage_bind_mode tinyint default 0 not null comment '分销关系绑定模式: 0-没有推广人,1-新用户', @@ -21,22 +20,26 @@ create table trade_config tenant_id bigint default 0 not null comment '租户编号' ) comment '交易中心配置'; --- 用户表增加分销相关字段 -alter table member_user - add column brokerage_user_id bigint not null comment '推广员编号'; -alter table member_user - add column brokerage_bind_time datetime null comment '推广员绑定时间'; -alter table member_user - add column brokerage_enabled bit default 1 not null comment '是否成为推广员'; -alter table member_user - add column brokerage_time datetime null comment '成为分销员时间'; -alter table member_user - add column brokerage_price int default 0 not null comment '可用佣金'; -alter table member_user - add column frozen_brokerage_price int default 0 not null comment '冻结佣金'; +-- 增加分销用户扩展表 +create table trade_brokerage_user +( + id bigint auto_increment comment '用户编号' primary key, + brokerage_user_id bigint not null comment '推广员编号', + brokerage_bind_time datetime null comment '推广员绑定时间', + brokerage_enabled bit default 1 not null comment '是否成为推广员', + brokerage_time datetime null comment '成为分销员时间', + brokerage_price int default 0 not null comment '可用佣金', + frozen_brokerage_price int default 0 not null comment '冻结佣金', + creator varchar(64) collate utf8mb4_unicode_ci default '' null comment '创建者', + create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间', + updater varchar(64) collate utf8mb4_unicode_ci default '' null comment '更新者', + update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间', + deleted bit default b'0' not null comment '是否删除', + tenant_id bigint default 0 not null comment '租户编号' +) comment '分销用户'; -create index idx_invite_user_id on member_user (brokerage_user_id) comment '推广员编号'; -create index idx_agent on member_user (brokerage_enabled) comment '是否成为推广员'; +create index idx_invite_user_id on trade_brokerage_user (brokerage_user_id) comment '推广员编号'; +create index idx_agent on trade_brokerage_user (brokerage_enabled) comment '是否成为推广员'; create table member_brokerage_record @@ -150,55 +153,65 @@ values ('brokerage_bank_name', '工商银行', 0, 0), ('brokerage_bank_name', '交通银行', 4, 4), ('brokerage_bank_name', '招商银行', 5, 5); --- 增加菜单:分销员管理 -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name) -VALUES ('分销员', '', 2, 7, 2262, 'brokerage', 'user', 'member/brokerage/user/index', 0, 'MemberBrokerageUser'); --- 按钮父菜单ID -SELECT @parentId := LAST_INSERT_ID(); --- 按钮 SQL -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) -VALUES ('分销员查询', 'member:brokerage-user:query', 3, 1, @parentId, '', '', '', 0); -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) -VALUES ('分销员创建', 'member:brokerage-user:create', 3, 2, @parentId, '', '', '', 0); -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) -VALUES ('分销员更新', 'member:brokerage-user:update', 3, 3, @parentId, '', '', '', 0); -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) -VALUES ('分销员删除', 'member:brokerage-user:delete', 3, 4, @parentId, '', '', '', 0); - --- 增加菜单:佣金记录 -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name) -VALUES ('佣金记录', '', 2, 8, 2262, 'brokerage-record', 'list', 'member/brokerage/record/index', 0, - 'MemberBrokerageRecord'); --- 按钮父菜单ID --- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码 -SELECT @parentId := LAST_INSERT_ID(); --- 按钮 SQL -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) -VALUES ('佣金记录查询', 'member:member-brokerage-record:query', 3, 1, @parentId, '', 'table', '', 0); - --- 增加菜单:佣金提现 -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name) -VALUES ('佣金提现', '', 2, 9, 2262, 'brokerage-withdraw', '', 'member/brokerage/withdraw/index', 0, - 'MemberBrokerageWithdraw'); - --- 按钮父菜单ID --- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码 -SELECT @parentId := LAST_INSERT_ID(); - --- 按钮 SQL -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) -VALUES ('佣金提现查询', 'member:brokerage-withdraw:query', 3, 1, @parentId, '', '', '', 0); -- 交易中心配置:菜单 SQL INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name) -VALUES ('交易中心配置', '', 2, 0, 2072, 'config', '', 'trade/config/index', 0, 'TradeConfig'); - +VALUES ('交易中心配置', '', 2, 0, 2072, 'config', 'ep:setting', 'trade/config/index', 0, 'TradeConfig'); -- 按钮父菜单ID -- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码 SELECT @parentId := LAST_INSERT_ID(); - -- 按钮 SQL INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) VALUES ('交易中心配置查询', 'trade:config:query', 3, 1, @parentId, '', '', '', 0); INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) -VALUES ('交易中心配置保存', 'trade:config:save', 3, 2, @parentId, '', '', '', 0); \ No newline at end of file +VALUES ('交易中心配置保存', 'trade:config:save', 3, 2, @parentId, '', '', '', 0); + + +-- 增加菜单:分销 +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name) +VALUES ('分销', '', 1, 5, 2072, 'brokerage', 'fa-solid:project-diagram', '', 0, ''); +-- 按钮父菜单ID +SELECT @brokerageMenuId := LAST_INSERT_ID(); + +-- 增加菜单:分销员 +-- 菜单 SQL +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name) +VALUES ('分销用户', '', 2, 0, @brokerageMenuId, 'brokerage-user', 'fa-solid:user-tie', 'trade/brokerage/user/index', 0, + 'TradeBrokerageUser'); +-- 按钮父菜单ID +-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码 +SELECT @parentId := LAST_INSERT_ID(); +-- 按钮 SQL +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES ('分销用户查询', 'trade:brokerage-user:query', 3, 1, @parentId, '', '', '', 0); +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES ('分销用户修改推广员', 'trade:brokerage-user:update-brokerage-user', 3, 2, @parentId, '', '', '', 0); +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES ('分销用户清除推广员', 'trade:brokerage-user:clear-brokerage-user', 3, 3, @parentId, '', '', '', 0); +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES ('分销用户修改推广资格', 'trade:brokerage-user:update-brokerage-enable', 3, 4, @parentId, '', '', '', 0); + + +-- 增加菜单:佣金记录 +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name) +VALUES ('佣金记录', '', 2, 1, @brokerageMenuId, 'brokerage-record', 'fa:money', 'trade/brokerage/record/index', 0, + 'TradeBrokerageRecord'); +-- 按钮父菜单ID +-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码 +SELECT @parentId := LAST_INSERT_ID(); +-- 按钮 SQL +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES ('佣金记录查询', 'trade:brokerage-record:query', 3, 1, @parentId, '', '', '', 0); + +-- 增加菜单:佣金提现 +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name) +VALUES ('佣金提现', '', 2, 2, @brokerageMenuId, 'brokerage-withdraw', 'fa:credit-card', + 'trade/brokerage/withdraw/index', 0, 'TradeBrokerageWithdraw'); +-- 按钮父菜单ID +-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码 +SELECT @parentId := LAST_INSERT_ID(); +-- 按钮 SQL +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES ('佣金提现查询', 'trade:brokerage-withdraw:query', 3, 1, @parentId, '', '', '', 0); +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES ('佣金提现审核', 'trade:brokerage-withdraw:audit', 3, 2, @parentId, '', '', '', 0); \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java index 40f604e94..3107dbedf 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java @@ -74,4 +74,8 @@ public interface ErrorCodeConstants { // ========== 物流 PICK_UP 模块 1011006000 ========== ErrorCode PICK_UP_STORE_NOT_EXISTS = new ErrorCode(1011006000, "自提门店不存在"); + + // ========== 分销 分销用户 模块 1011007000 ========== + ErrorCode BROKERAGE_USER_NOT_EXISTS = new ErrorCode(1011007000, "分销用户不存在"); + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/TradeBrokerageUserController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/TradeBrokerageUserController.java new file mode 100644 index 000000000..e4cc63fb9 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/TradeBrokerageUserController.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.user; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.*; +import cn.iocoder.yudao.module.trade.convert.brokerage.user.TradeBrokerageUserConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; +import cn.iocoder.yudao.module.trade.service.brokerage.user.TradeBrokerageUserService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - 分销用户") +@RestController +@RequestMapping("/trade/brokerage-user") +@Validated +public class TradeBrokerageUserController { + + @Resource + private TradeBrokerageUserService brokerageUserService; + + @PutMapping("/update-brokerage-user") + @Operation(summary = "修改推广员") + @PreAuthorize("@ss.hasPermission('trade:brokerage-user:update-brokerage-user')") + public CommonResult updateBrokerageUser(@Valid @RequestBody TradeBrokerageUserUpdateBrokerageUserReqVO updateReqVO) { + brokerageUserService.updateBrokerageUserId(updateReqVO.getId(), updateReqVO.getBrokerageUserId()); + return success(true); + } + + @PutMapping("/clear-brokerage-user") + @Operation(summary = "清除推广员") + @PreAuthorize("@ss.hasPermission('trade:brokerage-user:clear-brokerage-user')") + public CommonResult clearBrokerageUser(@Valid @RequestBody TradeBrokerageUserClearBrokerageUserReqVO updateReqVO) { + brokerageUserService.updateBrokerageUserId(updateReqVO.getId(), null); + return success(true); + } + + @PutMapping("/update-brokerage-enable") + @Operation(summary = "修改推广资格") + @PreAuthorize("@ss.hasPermission('trade:brokerage-user:update-brokerage-enable')") + public CommonResult updateBrokerageEnabled(@Valid @RequestBody TradeBrokerageUserUpdateBrokerageEnabledReqVO updateReqVO) { + brokerageUserService.updateBrokerageEnabled(updateReqVO.getId(), updateReqVO.getBrokerageEnabled()); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得分销用户") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('trade:brokerage-user:query')") + public CommonResult getBrokerageUser(@RequestParam("id") Long id) { + TradeBrokerageUserDO brokerageUser = brokerageUserService.getBrokerageUser(id); + return success(TradeBrokerageUserConvert.INSTANCE.convert(brokerageUser)); + } + + @GetMapping("/page") + @Operation(summary = "获得分销用户分页") + @PreAuthorize("@ss.hasPermission('trade:brokerage-user:query')") + public CommonResult> getBrokerageUserPage(@Valid TradeBrokerageUserPageReqVO pageVO) { + PageResult pageResult = brokerageUserService.getBrokerageUserPage(pageVO); + return success(TradeBrokerageUserConvert.INSTANCE.convertPage(pageResult)); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserBaseVO.java new file mode 100644 index 000000000..d75e6a1b1 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserBaseVO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +/** + * 分销用户 Base VO,提供给添加、修改、详细的子 VO 使用 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 + */ +@Data +public class TradeBrokerageUserBaseVO { + + @Schema(description = "推广员编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4587") + @NotNull(message = "推广员编号不能为空") + private Long brokerageUserId; + + @Schema(description = "推广员绑定时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime brokerageBindTime; + + @Schema(description = "推广资格", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "推广资格不能为空") + private Boolean brokerageEnabled; + + @Schema(description = "成为分销员时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime brokerageTime; + + @Schema(description = "可用佣金", requiredMode = Schema.RequiredMode.REQUIRED, example = "11089") + @NotNull(message = "可用佣金不能为空") + private Integer brokeragePrice; + + @Schema(description = "冻结佣金", requiredMode = Schema.RequiredMode.REQUIRED, example = "30916") + @NotNull(message = "冻结佣金不能为空") + private Integer frozenBrokeragePrice; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserClearBrokerageUserReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserClearBrokerageUserReqVO.java new file mode 100644 index 000000000..18a5a5e85 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserClearBrokerageUserReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.ToString; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 分销用户 - 清除推广员 Request VO") +@Data +@ToString(callSuper = true) +public class TradeBrokerageUserClearBrokerageUserReqVO { + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019") + @NotNull(message = "用户编号不能为空") + private Long id; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserPageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserPageReqVO.java new file mode 100644 index 000000000..ec63775d3 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserPageReqVO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 分销用户分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class TradeBrokerageUserPageReqVO extends PageParam { + + @Schema(description = "推广员编号", example = "4587") + private Long brokerageUserId; + + @Schema(description = "推广资格") + private Boolean brokerageEnabled; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserRespVO.java new file mode 100644 index 000000000..090eb04b5 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserRespVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 分销用户 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class TradeBrokerageUserRespVO extends TradeBrokerageUserBaseVO { + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019") + private Long id; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserUpdateBrokerageEnabledReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserUpdateBrokerageEnabledReqVO.java new file mode 100644 index 000000000..002eed371 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserUpdateBrokerageEnabledReqVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.ToString; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 分销用户 - 修改推广员 Request VO") +@Data +@ToString(callSuper = true) +public class TradeBrokerageUserUpdateBrokerageEnabledReqVO { + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019") + @NotNull(message = "用户编号不能为空") + private Long id; + + @Schema(description = "推广资格", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "推广资格不能为空") + private Boolean brokerageEnabled; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserUpdateBrokerageUserReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserUpdateBrokerageUserReqVO.java new file mode 100644 index 000000000..28ea301c1 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserUpdateBrokerageUserReqVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.ToString; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 分销用户 - 修改推广员 Request VO") +@Data +@ToString(callSuper = true) +public class TradeBrokerageUserUpdateBrokerageUserReqVO { + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019") + @NotNull(message = "用户编号不能为空") + private Long id; + + @Schema(description = "推广员编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4587") + @NotNull(message = "推广员编号不能为空") + private Long brokerageUserId; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/TradeBrokerageUserConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/TradeBrokerageUserConvert.java new file mode 100644 index 000000000..1a62bded0 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/TradeBrokerageUserConvert.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.trade.convert.brokerage.user; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.TradeBrokerageUserRespVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 分销用户 Convert + * + * @author owen + */ +@Mapper +public interface TradeBrokerageUserConvert { + + TradeBrokerageUserConvert INSTANCE = Mappers.getMapper(TradeBrokerageUserConvert.class); + + TradeBrokerageUserRespVO convert(TradeBrokerageUserDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/TradeBrokerageUserDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/TradeBrokerageUserDO.java new file mode 100644 index 000000000..0bc552dca --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/TradeBrokerageUserDO.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.time.LocalDateTime; + +/** + * 分销用户 DO + * + * @author owen + */ +@TableName("trade_brokerage_user") +@KeySequence("trade_brokerage_user_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TradeBrokerageUserDO extends BaseDO { + + /** + * 用户编号 + */ + @TableId + private Long id; + /** + * 推广员编号 + */ + private Long brokerageUserId; + /** + * 推广员绑定时间 + */ + private LocalDateTime brokerageBindTime; + /** + * 推广资格 + */ + private Boolean brokerageEnabled; + /** + * 成为分销员时间 + */ + private LocalDateTime brokerageTime; + /** + * 可用佣金 + */ + private Integer brokeragePrice; + /** + * 冻结佣金 + */ + private Integer frozenBrokeragePrice; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/TradeBrokerageUserMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/TradeBrokerageUserMapper.java new file mode 100644 index 000000000..93656837a --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/TradeBrokerageUserMapper.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.TradeBrokerageUserPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 分销用户 Mapper + * + * @author owen + */ +@Mapper +public interface TradeBrokerageUserMapper extends BaseMapperX { + + default PageResult selectPage(TradeBrokerageUserPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(TradeBrokerageUserDO::getBrokerageUserId, reqVO.getBrokerageUserId()) + .eqIfPresent(TradeBrokerageUserDO::getBrokerageEnabled, reqVO.getBrokerageEnabled()) + .betweenIfPresent(TradeBrokerageUserDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(TradeBrokerageUserDO::getId)); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserService.java new file mode 100644 index 000000000..58970d724 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserService.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.trade.service.brokerage.user; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.TradeBrokerageUserPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; + +import java.util.Collection; +import java.util.List; + +/** + * 分销用户 Service 接口 + * + * @author owen + */ +public interface TradeBrokerageUserService { + + /** + * 获得分销用户 + * + * @param id 编号 + * @return 分销用户 + */ + TradeBrokerageUserDO getBrokerageUser(Long id); + + /** + * 获得分销用户列表 + * + * @param ids 编号 + * @return 分销用户列表 + */ + List getBrokerageUserList(Collection ids); + + /** + * 获得分销用户分页 + * + * @param pageReqVO 分页查询 + * @return 分销用户分页 + */ + PageResult getBrokerageUserPage(TradeBrokerageUserPageReqVO pageReqVO); + + /** + * 修改推广员编号 + * + * @param id 用户编号 + * @param brokerageUserId 推广员编号 + */ + void updateBrokerageUserId(Long id, Long brokerageUserId); + + /** + * 修改推广资格 + * + * @param id 用户编号 + * @param brokerageEnabled 推广资格 + */ + void updateBrokerageEnabled(Long id, Boolean brokerageEnabled); +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImpl.java new file mode 100644 index 000000000..acbda456b --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImpl.java @@ -0,0 +1,63 @@ +package cn.iocoder.yudao.module.trade.service.brokerage.user; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.TradeBrokerageUserPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; +import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user.TradeBrokerageUserMapper; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.BROKERAGE_USER_NOT_EXISTS; + +/** + * 分销用户 Service 实现类 + * + * @author owen + */ +@Service +@Validated +public class TradeBrokerageUserServiceImpl implements TradeBrokerageUserService { + + @Resource + private TradeBrokerageUserMapper brokerageUserMapper; + + private void validateBrokerageUserExists(Long id) { + if (brokerageUserMapper.selectById(id) == null) { + throw exception(BROKERAGE_USER_NOT_EXISTS); + } + } + + @Override + public TradeBrokerageUserDO getBrokerageUser(Long id) { + return brokerageUserMapper.selectById(id); + } + + @Override + public List getBrokerageUserList(Collection ids) { + return brokerageUserMapper.selectBatchIds(ids); + } + + @Override + public PageResult getBrokerageUserPage(TradeBrokerageUserPageReqVO pageReqVO) { + return brokerageUserMapper.selectPage(pageReqVO); + } + + @Override + public void updateBrokerageUserId(Long id, Long brokerageUserId) { + // 校验存在 + validateBrokerageUserExists(id); + + } + + @Override + public void updateBrokerageEnabled(Long id, Boolean brokerageEnabled) { + // 校验存在 + validateBrokerageUserExists(id); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImplTest.java b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImplTest.java new file mode 100644 index 000000000..49e8aa351 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImplTest.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.trade.service.brokerage.user; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.TradeBrokerageUserPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; +import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user.TradeBrokerageUserMapper; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; + +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * {@link TradeBrokerageUserServiceImpl} 的单元测试类 + * + * @author owen + */ +@Import(TradeBrokerageUserServiceImpl.class) +public class TradeBrokerageUserServiceImplTest extends BaseDbUnitTest { + + @Resource + private TradeBrokerageUserServiceImpl brokerageUserService; + + @Resource + private TradeBrokerageUserMapper brokerageUserMapper; + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetBrokerageUserPage() { + // mock 数据 + TradeBrokerageUserDO dbBrokerageUser = randomPojo(TradeBrokerageUserDO.class, o -> { // 等会查询到 + o.setBrokerageUserId(null); + o.setBrokerageEnabled(null); + o.setCreateTime(null); + }); + brokerageUserMapper.insert(dbBrokerageUser); + // 测试 brokerageUserId 不匹配 + brokerageUserMapper.insert(cloneIgnoreId(dbBrokerageUser, o -> o.setBrokerageUserId(null))); + // 测试 brokerageEnabled 不匹配 + brokerageUserMapper.insert(cloneIgnoreId(dbBrokerageUser, o -> o.setBrokerageEnabled(null))); + // 测试 createTime 不匹配 + brokerageUserMapper.insert(cloneIgnoreId(dbBrokerageUser, o -> o.setCreateTime(null))); + // 准备参数 + TradeBrokerageUserPageReqVO reqVO = new TradeBrokerageUserPageReqVO(); + reqVO.setBrokerageUserId(null); + reqVO.setBrokerageEnabled(null); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + PageResult pageResult = brokerageUserService.getBrokerageUserPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbBrokerageUser, pageResult.getList().get(0)); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/clean.sql b/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/clean.sql index dfa4a5b42..b0715ca16 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/clean.sql +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/clean.sql @@ -2,3 +2,4 @@ DELETE FROM trade_order; DELETE FROM trade_order_item; DELETE FROM trade_after_sale; DELETE FROM trade_after_sale_log; +DELETE FROM "trade_brokerage_user"; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql b/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql index e30b0d225..df68fd53b 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql @@ -125,3 +125,21 @@ CREATE TABLE IF NOT EXISTS "trade_after_sale_log" ( "deleted" bit NOT NULL DEFAULT FALSE, PRIMARY KEY ("id") ) COMMENT '交易售后日志'; + +CREATE TABLE IF NOT EXISTS "trade_brokerage_user" +( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "brokerage_user_id" bigint NOT NULL, + "brokerage_bind_time" varchar, + "brokerage_enabled" bit NOT NULL, + "brokerage_time" varchar, + "brokerage_price" int NOT NULL, + "frozen_brokerage_price" int NOT NULL, + "creator" varchar DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT '0', + PRIMARY KEY ("id") +) COMMENT '分销用户'; \ No newline at end of file From e4b153a866903ffcbbec803a97b05867991a5515 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 5 Sep 2023 23:49:35 +0800 Subject: [PATCH 17/50] =?UTF-8?q?=E5=88=86=E4=BD=A3=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=8E=B7=E5=BE=97=E5=88=86=E9=94=80=E6=8E=92=E8=A1=8C?= =?UTF-8?q?=E5=88=86=E9=A1=B5=20API=20mock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/common/pojo/SortingField.java | 33 +++--------- .../brokerage/AppBrokerageUserController.java | 51 +++++++++++++------ ...AppBrokerageUserChildSummaryPageReqVO.java | 25 +++++++++ .../AppBrokerageUserChildSummaryRespVO.java | 33 ++++++++++++ ...a => AppBrokerageUserMySummaryRespVO.java} | 8 ++- .../AppBrokerageUserRankByPriceRespVO.java | 4 +- ...AppBrokerageUserRankByUserCountRespVO.java | 4 +- 7 files changed, 111 insertions(+), 47 deletions(-) create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserChildSummaryPageReqVO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserChildSummaryRespVO.java rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/{AppBrokerageUserSummaryRespVO.java => AppBrokerageUserMySummaryRespVO.java} (69%) diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/SortingField.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/SortingField.java index 98411730e..07a68b064 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/SortingField.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/SortingField.java @@ -1,5 +1,9 @@ package cn.iocoder.yudao.framework.common.pojo; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + import java.io.Serializable; /** @@ -7,6 +11,9 @@ import java.io.Serializable; * * 类名加了 ing 的原因是,避免和 ES SortField 重名。 */ +@Data +@NoArgsConstructor +@AllArgsConstructor public class SortingField implements Serializable { /** @@ -27,30 +34,4 @@ public class SortingField implements Serializable { */ private String order; - // 空构造方法,解决反序列化 - public SortingField() { - } - - public SortingField(String field, String order) { - this.field = field; - this.order = order; - } - - public String getField() { - return field; - } - - public SortingField setField(String field) { - this.field = field; - return this; - } - - public String getOrder() { - return order; - } - - public SortingField setOrder(String order) { - this.order = order; - return this; - } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java index dd3d17ff7..31de03ea1 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java @@ -3,10 +3,7 @@ package cn.iocoder.yudao.module.trade.controller.app.brokerage; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; -import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankByPriceRespVO; -import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankByUserCountRespVO; -import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankPageReqVO; -import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserSummaryRespVO; +import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.*; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -35,53 +32,75 @@ public class AppBrokerageUserController { @GetMapping("/get-summary") @Operation(summary = "获得个人分销统计") @PreAuthenticated - public CommonResult getBrokerageUserSummary() { - AppBrokerageUserSummaryRespVO respVO = new AppBrokerageUserSummaryRespVO() + public CommonResult getBrokerageUserSummary() { + AppBrokerageUserMySummaryRespVO respVO = new AppBrokerageUserMySummaryRespVO() .setYesterdayBrokeragePrice(1) .setBrokeragePrice(2) .setFrozenBrokeragePrice(3) - .setWithdrawBrokeragePrice(4); + .setWithdrawBrokeragePrice(4) + .setFirstBrokerageUserCount(166) + .setSecondBrokerageUserCount(233); return success(respVO); } + // TODO 芋艿:临时 mock => @GetMapping("/rank-page-by-user-count") @Operation(summary = "获得分销用户排行分页(基于用户量)") @PreAuthenticated public CommonResult> getBrokerageUserRankPageByUserCount(AppBrokerageUserRankPageReqVO pageReqVO) { AppBrokerageUserRankByUserCountRespVO vo1 = new AppBrokerageUserRankByUserCountRespVO() - .setUserId(1L).setNickname("芋1**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") + .setId(1L).setNickname("芋1**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") .setBrokerageUserCount(10); AppBrokerageUserRankByUserCountRespVO vo2 = new AppBrokerageUserRankByUserCountRespVO() - .setUserId(2L).setNickname("芋2**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") + .setId(2L).setNickname("芋2**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") .setBrokerageUserCount(6); AppBrokerageUserRankByUserCountRespVO vo3 = new AppBrokerageUserRankByUserCountRespVO() - .setUserId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") + .setId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") .setBrokerageUserCount(4); AppBrokerageUserRankByUserCountRespVO vo4 = new AppBrokerageUserRankByUserCountRespVO() - .setUserId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") + .setId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") .setBrokerageUserCount(4); return success(new PageResult<>(asList(vo1, vo2, vo3, vo4), 10L)); } + // TODO 芋艿:临时 mock => @GetMapping("/rank-page-by-price") @Operation(summary = "获得分销用户排行分页(基于佣金)") @PreAuthenticated - public CommonResult> getBrokerageUserRankPageByPrice(AppBrokerageUserRankPageReqVO pageReqVO) { + public CommonResult> getBrokerageUserChildSummaryPageByPrice(AppBrokerageUserRankPageReqVO pageReqVO) { AppBrokerageUserRankByPriceRespVO vo1 = new AppBrokerageUserRankByPriceRespVO() - .setUserId(1L).setNickname("芋1**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") + .setId(1L).setNickname("芋1**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") .setBrokeragePrice(10); AppBrokerageUserRankByPriceRespVO vo2 = new AppBrokerageUserRankByPriceRespVO() - .setUserId(2L).setNickname("芋2**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") + .setId(2L).setNickname("芋2**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") .setBrokeragePrice(6); AppBrokerageUserRankByPriceRespVO vo3 = new AppBrokerageUserRankByPriceRespVO() - .setUserId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") + .setId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") .setBrokeragePrice(4); AppBrokerageUserRankByPriceRespVO vo4 = new AppBrokerageUserRankByPriceRespVO() - .setUserId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") + .setId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") .setBrokeragePrice(4); return success(new PageResult<>(asList(vo1, vo2, vo3, vo4), 10L)); } + // TODO 芋艿:临时 mock => + @GetMapping("/child-summary-page") + @Operation(summary = "获得下级分销统计分页") + @PreAuthenticated + public CommonResult> getBrokerageUserChildSummaryPage( + AppBrokerageUserChildSummaryPageReqVO pageReqVO) { + AppBrokerageUserChildSummaryRespVO vo1 = new AppBrokerageUserChildSummaryRespVO() + .setId(1L).setNickname("芋1**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") + .setBrokeragePrice(10).setBrokeragePrice(20).setBrokerageOrderCount(30) + .setBrokerageTime(LocalDateTime.now()); + AppBrokerageUserChildSummaryRespVO vo2 = new AppBrokerageUserChildSummaryRespVO() + .setId(1L).setNickname("芋2**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") + .setBrokeragePrice(20).setBrokeragePrice(30).setBrokerageOrderCount(40) + .setBrokerageTime(LocalDateTime.now()); + return success(new PageResult<>(asList(vo1, vo2), 10L)); + } + + // TODO 芋艿:临时 mock => @GetMapping("/get-rank-by-price") @Operation(summary = "获得分销用户排行(基于佣金)") @Parameter(name = "times", description = "时间段", required = true) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserChildSummaryPageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserChildSummaryPageReqVO.java new file mode 100644 index 000000000..066fc0912 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserChildSummaryPageReqVO.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.SortingField; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "用户 App - 下级分销统计分页 Request VO") +@Data +public class AppBrokerageUserChildSummaryPageReqVO extends PageParam { + + public static final String SORT_FIELD_USER_COUNT = "userCount"; + public static final String SORT_FIELD_ORDER_COUNT = "orderCount"; + public static final String SORT_FIELD_PRICE = "price"; + + @Schema(description = "用户昵称", example = "李") // 模糊匹配 + private String nickname; + + @Schema(description = "排序字段", example = "userCount") + private SortingField sortingField; + + @Schema(description = "下级的级别", example = "1") // 1 - 直接下级;2 - 间接下级 + private Integer level; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserChildSummaryRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserChildSummaryRespVO.java new file mode 100644 index 000000000..1beb1b5e2 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserChildSummaryRespVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "用户 App - 下级分销统计 Response VO") +@Data +public class AppBrokerageUserChildSummaryRespVO { + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Long id; + + @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小王") + private String nickname; + + @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xxx.jpg") + private String avatar; + + @Schema(description = "佣金金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Integer brokeragePrice; + + @Schema(description = "分销订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") + private Integer brokerageOrderCount; + + @Schema(description = "分销用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "30") + private Integer brokerageUserCount; + + @Schema(description = "成为分销员时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime brokerageTime; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserSummaryRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserMySummaryRespVO.java similarity index 69% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserSummaryRespVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserMySummaryRespVO.java index 5779d8010..64fafe329 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserSummaryRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserMySummaryRespVO.java @@ -5,7 +5,7 @@ import lombok.Data; @Schema(description = "用户 App - 个人分销统计 Response VO") @Data -public class AppBrokerageUserSummaryRespVO { +public class AppBrokerageUserMySummaryRespVO { @Schema(description = "昨天的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") private Integer yesterdayBrokeragePrice; @@ -19,4 +19,10 @@ public class AppBrokerageUserSummaryRespVO { @Schema(description = "冻结的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "234") private Integer frozenBrokeragePrice; + @Schema(description = "分销用户数量(一级)", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Integer firstBrokerageUserCount; + + @Schema(description = "分销用户数量(二级)", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Integer secondBrokerageUserCount; + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByPriceRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByPriceRespVO.java index 28dab5f8f..91345ea78 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByPriceRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByPriceRespVO.java @@ -8,12 +8,12 @@ import lombok.Data; public class AppBrokerageUserRankByPriceRespVO { @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - private Long userId; + private Long id; @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小王") private String nickname; - @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://www.iocoder.cn/xxx.jpg") + @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xxx.jpg") private String avatar; @Schema(description = "佣金金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByUserCountRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByUserCountRespVO.java index f0ea2e6c3..1a6de8138 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByUserCountRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByUserCountRespVO.java @@ -8,12 +8,12 @@ import lombok.Data; public class AppBrokerageUserRankByUserCountRespVO { @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - private Long userId; + private Long id; @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小王") private String nickname; - @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://www.iocoder.cn/xxx.jpg") + @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xxx.jpg") private String avatar; @Schema(description = "邀请用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") From 9336a0a1024ccdc5dd30a1d56cf054a884082477 Mon Sep 17 00:00:00 2001 From: owen Date: Wed, 6 Sep 2023 00:16:47 +0800 Subject: [PATCH 18/50] =?UTF-8?q?trade:=20=E5=88=86=E9=94=80=E4=B8=9A?= =?UTF-8?q?=E5=8A=A1=E4=BB=8E=20member=20=E6=A8=A1=E5=9D=97=20=E8=BD=AC?= =?UTF-8?q?=E7=A7=BB=E5=88=B0=20trade=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../brokerage/BrokerageBindModeEnum.java | 2 +- .../BrokerageEnabledConditionEnum.java | 2 +- .../brokerage/BrokerageRecordBizTypeEnum.java | 2 +- .../brokerage/BrokerageRecordStatusEnum.java | 2 +- .../BrokerageWithdrawStatusEnum.java | 2 +- .../brokerage/BrokerageWithdrawTypeEnum.java | 2 +- .../yudao-module-trade-biz/pom.xml | 4 + .../MemberBrokerageRecordController.java | 14 ++-- .../vo/MemberBrokerageRecordBaseVO.java | 2 +- .../vo/MemberBrokerageRecordPageReqVO.java | 2 +- .../vo/MemberBrokerageRecordRespVO.java | 2 +- .../admin/config/vo/TradeConfigBaseVO.java | 6 +- .../record/MemberBrokerageRecordConvert.java | 14 ++-- .../convert/order/TradeOrderConvert.java | 2 +- .../record/MemberBrokerageRecordDO.java | 6 +- .../dal/dataobject/config/TradeConfigDO.java | 6 +- .../record/MemberBrokerageRecordMapper.java | 6 +- .../user/TradeBrokerageUserMapper.java | 77 +++++++++++++++++++ .../MemberBrokerageRecordUnfreezeJob.java | 4 +- .../record/MemberBrokerageRecordService.java | 8 +- .../MemberBrokerageRecordServiceImpl.java | 46 +++++------ .../record/bo}/BrokerageAddReqDTO.java | 2 +- .../user/TradeBrokerageUserService.java | 32 ++++++++ .../user/TradeBrokerageUserServiceImpl.java | 43 +++++++++++ .../order/TradeOrderUpdateServiceImpl.java | 10 +-- .../MemberBrokerageRecordServiceImplTest.java | 16 ++-- .../member/api/brokerage/BrokerageApi.java | 30 -------- .../api/brokerage/BrokerageApiImpl.java | 32 -------- .../vo/config/MemberPointConfigBaseVO.java | 57 -------------- .../dataobject/point/MemberPointConfigDO.java | 60 --------------- .../dal/mysql/user/MemberUserMapper.java | 77 ------------------- .../service/user/MemberUserService.java | 32 -------- .../service/user/MemberUserServiceImpl.java | 41 ---------- 33 files changed, 235 insertions(+), 408 deletions(-) rename {yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member => yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade}/enums/brokerage/BrokerageBindModeEnum.java (93%) rename {yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member => yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade}/enums/brokerage/BrokerageEnabledConditionEnum.java (93%) rename {yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member => yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade}/enums/brokerage/BrokerageRecordBizTypeEnum.java (94%) rename {yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member => yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade}/enums/brokerage/BrokerageRecordStatusEnum.java (92%) rename {yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member => yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade}/enums/brokerage/BrokerageWithdrawStatusEnum.java (93%) rename {yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member => yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade}/enums/brokerage/BrokerageWithdrawTypeEnum.java (92%) rename {yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member => yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade}/controller/admin/brokerage/record/MemberBrokerageRecordController.java (76%) rename {yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member => yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade}/controller/admin/brokerage/record/vo/MemberBrokerageRecordBaseVO.java (96%) rename {yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member => yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade}/controller/admin/brokerage/record/vo/MemberBrokerageRecordPageReqVO.java (92%) rename {yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member => yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade}/controller/admin/brokerage/record/vo/MemberBrokerageRecordRespVO.java (89%) rename {yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member => yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade}/convert/brokerage/record/MemberBrokerageRecordConvert.java (70%) rename {yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member => yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade}/dal/dataobject/brokerage/record/MemberBrokerageRecordDO.java (86%) rename {yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member => yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade}/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java (88%) rename {yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member => yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade}/job/brokerage/MemberBrokerageRecordUnfreezeJob.java (81%) rename {yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member => yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade}/service/brokerage/record/MemberBrokerageRecordService.java (76%) rename {yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member => yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade}/service/brokerage/record/MemberBrokerageRecordServiceImpl.java (79%) rename {yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/dto => yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo}/BrokerageAddReqDTO.java (89%) rename {yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member => yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade}/service/brokerage/record/MemberBrokerageRecordServiceImplTest.java (87%) delete mode 100644 yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/BrokerageApi.java delete mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/BrokerageApiImpl.java diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageBindModeEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageBindModeEnum.java similarity index 93% rename from yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageBindModeEnum.java rename to yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageBindModeEnum.java index 2ee7e891f..6946167bc 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageBindModeEnum.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageBindModeEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.member.enums.brokerage; +package cn.iocoder.yudao.module.trade.enums.brokerage; import cn.iocoder.yudao.framework.common.core.IntArrayValuable; import lombok.AllArgsConstructor; diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageEnabledConditionEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageEnabledConditionEnum.java similarity index 93% rename from yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageEnabledConditionEnum.java rename to yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageEnabledConditionEnum.java index 5422b98b7..6d984a284 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageEnabledConditionEnum.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageEnabledConditionEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.member.enums.brokerage; +package cn.iocoder.yudao.module.trade.enums.brokerage; import cn.iocoder.yudao.framework.common.core.IntArrayValuable; import lombok.AllArgsConstructor; diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageRecordBizTypeEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageRecordBizTypeEnum.java similarity index 94% rename from yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageRecordBizTypeEnum.java rename to yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageRecordBizTypeEnum.java index d30758a88..ce449f0b8 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageRecordBizTypeEnum.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageRecordBizTypeEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.member.enums.brokerage; +package cn.iocoder.yudao.module.trade.enums.brokerage; import cn.iocoder.yudao.framework.common.core.IntArrayValuable; import lombok.AllArgsConstructor; diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageRecordStatusEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageRecordStatusEnum.java similarity index 92% rename from yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageRecordStatusEnum.java rename to yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageRecordStatusEnum.java index 75ddc9e0a..827390998 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageRecordStatusEnum.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageRecordStatusEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.member.enums.brokerage; +package cn.iocoder.yudao.module.trade.enums.brokerage; import cn.iocoder.yudao.framework.common.core.IntArrayValuable; import lombok.AllArgsConstructor; diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageWithdrawStatusEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageWithdrawStatusEnum.java similarity index 93% rename from yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageWithdrawStatusEnum.java rename to yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageWithdrawStatusEnum.java index 6d0232deb..a80aad02a 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageWithdrawStatusEnum.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageWithdrawStatusEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.member.enums.brokerage; +package cn.iocoder.yudao.module.trade.enums.brokerage; import cn.iocoder.yudao.framework.common.core.IntArrayValuable; import lombok.AllArgsConstructor; diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageWithdrawTypeEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageWithdrawTypeEnum.java similarity index 92% rename from yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageWithdrawTypeEnum.java rename to yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageWithdrawTypeEnum.java index 21d0712b9..46edf010e 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/brokerage/BrokerageWithdrawTypeEnum.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageWithdrawTypeEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.member.enums.brokerage; +package cn.iocoder.yudao.module.trade.enums.brokerage; import cn.iocoder.yudao.framework.common.core.IntArrayValuable; import lombok.AllArgsConstructor; diff --git a/yudao-module-mall/yudao-module-trade-biz/pom.xml b/yudao-module-mall/yudao-module-trade-biz/pom.xml index 810446fa9..02f31a9f0 100644 --- a/yudao-module-mall/yudao-module-trade-biz/pom.xml +++ b/yudao-module-mall/yudao-module-trade-biz/pom.xml @@ -54,6 +54,10 @@ cn.iocoder.boot yudao-spring-boot-starter-biz-operatelog + + cn.iocoder.boot + yudao-spring-boot-starter-biz-tenant + cn.iocoder.boot yudao-spring-boot-starter-biz-ip diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/MemberBrokerageRecordController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/MemberBrokerageRecordController.java similarity index 76% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/MemberBrokerageRecordController.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/MemberBrokerageRecordController.java index 92cb0ae1a..c4bc9bb37 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/MemberBrokerageRecordController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/MemberBrokerageRecordController.java @@ -1,12 +1,12 @@ -package cn.iocoder.yudao.module.member.controller.admin.brokerage.record; +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.record; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; -import cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo.MemberBrokerageRecordRespVO; -import cn.iocoder.yudao.module.member.convert.brokerage.record.MemberBrokerageRecordConvert; -import cn.iocoder.yudao.module.member.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; -import cn.iocoder.yudao.module.member.service.brokerage.record.MemberBrokerageRecordService; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.MemberBrokerageRecordRespVO; +import cn.iocoder.yudao.module.trade.convert.brokerage.record.MemberBrokerageRecordConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; +import cn.iocoder.yudao.module.trade.service.brokerage.record.MemberBrokerageRecordService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -24,7 +24,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @Tag(name = "管理后台 - 佣金记录") @RestController -@RequestMapping("/member/member-brokerage-record") +@RequestMapping("/trade/member-brokerage-record") @Validated public class MemberBrokerageRecordController { diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/vo/MemberBrokerageRecordBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/MemberBrokerageRecordBaseVO.java similarity index 96% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/vo/MemberBrokerageRecordBaseVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/MemberBrokerageRecordBaseVO.java index ef6762be1..51cd4a631 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/vo/MemberBrokerageRecordBaseVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/MemberBrokerageRecordBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo; +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/vo/MemberBrokerageRecordPageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/MemberBrokerageRecordPageReqVO.java similarity index 92% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/vo/MemberBrokerageRecordPageReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/MemberBrokerageRecordPageReqVO.java index 04a9ed94c..3a5e05527 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/vo/MemberBrokerageRecordPageReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/MemberBrokerageRecordPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo; +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/vo/MemberBrokerageRecordRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/MemberBrokerageRecordRespVO.java similarity index 89% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/vo/MemberBrokerageRecordRespVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/MemberBrokerageRecordRespVO.java index 417b5320d..3550a64ba 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/brokerage/record/vo/MemberBrokerageRecordRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/MemberBrokerageRecordRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo; +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigBaseVO.java index 4ee51e3b8..ee20156f1 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigBaseVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigBaseVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.trade.controller.admin.config.vo; import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageBindModeEnum; -import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageEnabledConditionEnum; -import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageWithdrawTypeEnum; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageBindModeEnum; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageEnabledConditionEnum; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.hibernate.validator.constraints.Range; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/brokerage/record/MemberBrokerageRecordConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/MemberBrokerageRecordConvert.java similarity index 70% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/brokerage/record/MemberBrokerageRecordConvert.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/MemberBrokerageRecordConvert.java index 393bacb72..48af52cf5 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/brokerage/record/MemberBrokerageRecordConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/MemberBrokerageRecordConvert.java @@ -1,12 +1,12 @@ -package cn.iocoder.yudao.module.member.convert.brokerage.record; +package cn.iocoder.yudao.module.trade.convert.brokerage.record; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo.MemberBrokerageRecordRespVO; -import cn.iocoder.yudao.module.member.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; -import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; -import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageRecordBizTypeEnum; -import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageRecordStatusEnum; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.MemberBrokerageRecordRespVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -29,7 +29,7 @@ public interface MemberBrokerageRecordConvert { PageResult convertPage(PageResult page); - default MemberBrokerageRecordDO convert(MemberUserDO user, String bizId, int brokerageFrozenDays, int brokerage, LocalDateTime unfreezeTime) { + default MemberBrokerageRecordDO convert(TradeBrokerageUserDO user, String bizId, int brokerageFrozenDays, int brokerage, LocalDateTime unfreezeTime) { // 不冻结时,佣金直接就是结算状态 Integer status = brokerageFrozenDays > 0 ? BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus() diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java index e46ce66b6..d17b81124 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java @@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.common.util.string.StrUtils; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; -import cn.iocoder.yudao.module.member.api.brokerage.dto.BrokerageAddReqDTO; +import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.BrokerageAddReqDTO; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; import cn.iocoder.yudao.module.pay.enums.DictTypeConstants; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/brokerage/record/MemberBrokerageRecordDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/MemberBrokerageRecordDO.java similarity index 86% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/brokerage/record/MemberBrokerageRecordDO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/MemberBrokerageRecordDO.java index 88e6ba7d9..94d37ff89 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/brokerage/record/MemberBrokerageRecordDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/MemberBrokerageRecordDO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.module.member.dal.dataobject.brokerage.record; +package cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageRecordBizTypeEnum; -import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageRecordStatusEnum; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/config/TradeConfigDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/config/TradeConfigDO.java index 5538186e1..a0c6d3858 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/config/TradeConfigDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/config/TradeConfigDO.java @@ -2,9 +2,9 @@ package cn.iocoder.yudao.module.trade.dal.dataobject.config; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.mybatis.core.type.IntegerListTypeHandler; -import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageBindModeEnum; -import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageEnabledConditionEnum; -import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageWithdrawTypeEnum; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageBindModeEnum; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageEnabledConditionEnum; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawTypeEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java similarity index 88% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java index 52154aea5..da89b8bba 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java @@ -1,10 +1,10 @@ -package cn.iocoder.yudao.module.member.dal.mysql.brokerage.record; +package cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; -import cn.iocoder.yudao.module.member.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/TradeBrokerageUserMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/TradeBrokerageUserMapper.java index 93656837a..f0c221311 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/TradeBrokerageUserMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/TradeBrokerageUserMapper.java @@ -1,10 +1,12 @@ package cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user; +import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.TradeBrokerageUserPageReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; /** @@ -23,4 +25,79 @@ public interface TradeBrokerageUserMapper extends BaseMapperX 0); + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() + .setSql(" brokerage_price = brokerage_price + " + incrCount) + .eq(TradeBrokerageUserDO::getId, id); + update(null, lambdaUpdateWrapper); + } + + /** + * 更新用户可用佣金(减少) + * 注意:理论上佣金可能已经提现,这时会扣出负数,确保平台不会造成损失 + * + * @param id 用户编号 + * @param incrCount 增加佣金(负数) + */ + default void updateBrokeragePriceDecr(Long id, int incrCount) { + Assert.isTrue(incrCount < 0); + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() + .setSql(" brokerage_price = brokerage_price + " + incrCount) // 负数,所以使用 + 号 + .eq(TradeBrokerageUserDO::getId, id); + update(null, lambdaUpdateWrapper); + } + + /** + * 更新用户冻结佣金(增加) + * + * @param id 用户编号 + * @param incrCount 增加冻结佣金(正数) + */ + default void updateFrozenBrokeragePriceIncr(Long id, int incrCount) { + Assert.isTrue(incrCount > 0); + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() + .setSql(" frozen_brokerage_price = frozen_brokerage_price + " + incrCount) + .eq(TradeBrokerageUserDO::getId, id); + update(null, lambdaUpdateWrapper); + } + + /** + * 更新用户冻结佣金(减少) + * 注意:理论上冻结佣金可能已经解冻,这时会扣出负数,确保平台不会造成损失 + * + * @param id 用户编号 + * @param incrCount 减少冻结佣金(负数) + */ + default void updateFrozenBrokeragePriceDecr(Long id, int incrCount) { + Assert.isTrue(incrCount < 0); + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() + .setSql(" frozen_brokerage_price = frozen_brokerage_price + " + incrCount) // 负数,所以使用 + 号 + .eq(TradeBrokerageUserDO::getId, id); + update(null, lambdaUpdateWrapper); + } + + /** + * 更新用户冻结佣金(减少), 更新用户佣金(增加) + * + * @param id 用户编号 + * @param incrCount 减少冻结佣金(负数) + * @return 更新条数 + */ + default int updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(Long id, int incrCount) { + Assert.isTrue(incrCount < 0); + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() + .setSql(" frozen_brokerage_price = frozen_brokerage_price + " + incrCount + // 负数,所以使用 + 号 + ", brokerage_price = brokerage_price + " + -incrCount) // 负数,所以使用 - 号 + .eq(TradeBrokerageUserDO::getId, id) + .ge(TradeBrokerageUserDO::getFrozenBrokeragePrice, -incrCount); // cas 逻辑 + return update(null, lambdaUpdateWrapper); + } + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/job/brokerage/MemberBrokerageRecordUnfreezeJob.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/brokerage/MemberBrokerageRecordUnfreezeJob.java similarity index 81% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/job/brokerage/MemberBrokerageRecordUnfreezeJob.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/brokerage/MemberBrokerageRecordUnfreezeJob.java index f4512cf08..d41bc840c 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/job/brokerage/MemberBrokerageRecordUnfreezeJob.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/brokerage/MemberBrokerageRecordUnfreezeJob.java @@ -1,9 +1,9 @@ -package cn.iocoder.yudao.module.member.job.brokerage; +package cn.iocoder.yudao.module.trade.job.brokerage; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; -import cn.iocoder.yudao.module.member.service.brokerage.record.MemberBrokerageRecordService; +import cn.iocoder.yudao.module.trade.service.brokerage.record.MemberBrokerageRecordService; import org.springframework.stereotype.Component; import javax.annotation.Resource; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/MemberBrokerageRecordService.java similarity index 76% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordService.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/MemberBrokerageRecordService.java index cd966e670..5cdd9e1b5 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/MemberBrokerageRecordService.java @@ -1,9 +1,9 @@ -package cn.iocoder.yudao.module.member.service.brokerage.record; +package cn.iocoder.yudao.module.trade.service.brokerage.record; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.member.api.brokerage.dto.BrokerageAddReqDTO; -import cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; -import cn.iocoder.yudao.module.member.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; +import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.BrokerageAddReqDTO; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; import java.util.List; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/MemberBrokerageRecordServiceImpl.java similarity index 79% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImpl.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/MemberBrokerageRecordServiceImpl.java index 32656910c..e56ae5dab 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/MemberBrokerageRecordServiceImpl.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.member.service.brokerage.record; +package cn.iocoder.yudao.module.trade.service.brokerage.record; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.BooleanUtil; @@ -6,17 +6,17 @@ import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.member.api.brokerage.dto.BrokerageAddReqDTO; -import cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; -import cn.iocoder.yudao.module.member.convert.brokerage.record.MemberBrokerageRecordConvert; -import cn.iocoder.yudao.module.member.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; -import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointConfigDO; -import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; -import cn.iocoder.yudao.module.member.dal.mysql.brokerage.record.MemberBrokerageRecordMapper; -import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageRecordBizTypeEnum; -import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageRecordStatusEnum; -import cn.iocoder.yudao.module.member.service.point.MemberPointConfigService; -import cn.iocoder.yudao.module.member.service.user.MemberUserService; +import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.BrokerageAddReqDTO; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; +import cn.iocoder.yudao.module.trade.convert.brokerage.record.MemberBrokerageRecordConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; +import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record.MemberBrokerageRecordMapper; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; +import cn.iocoder.yudao.module.trade.service.brokerage.user.TradeBrokerageUserService; +import cn.iocoder.yudao.module.trade.service.config.TradeConfigService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -42,9 +42,9 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe @Resource private MemberBrokerageRecordMapper memberBrokerageRecordMapper; @Resource - private MemberPointConfigService memberConfigService; + private TradeConfigService tradeConfigService; @Resource - private MemberUserService memberUserService; + private TradeBrokerageUserService tradeBrokerageUserService; @Override public MemberBrokerageRecordDO getMemberBrokerageRecord(Integer id) { @@ -59,7 +59,7 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe @Override @Transactional(rollbackFor = Exception.class) public void addBrokerage(Long buyerId, List list) { - MemberPointConfigDO memberConfig = memberConfigService.getPointConfig(); + TradeConfigDO memberConfig = tradeConfigService.getTradeConfig(); // 0 未启用分销功能 if (memberConfig == null || !BooleanUtil.isTrue(memberConfig.getBrokerageEnabled())) { log.warn("[addBrokerage][增加佣金失败:brokerageEnabled 未配置,buyerId({})", buyerId); @@ -67,7 +67,7 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe } // 1.1 获得一级推广人 - MemberUserDO firstUser = memberUserService.getBrokerageUser(buyerId); + TradeBrokerageUserDO firstUser = tradeBrokerageUserService.getInviteBrokerageUser(buyerId); if (firstUser == null || !BooleanUtil.isTrue(firstUser.getBrokerageEnabled())) { return; } @@ -77,7 +77,7 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe // 2.1 获得二级推广员 - MemberUserDO secondUser = memberUserService.getUser(firstUser.getBrokerageUserId()); + TradeBrokerageUserDO secondUser = tradeBrokerageUserService.getBrokerageUser(firstUser.getBrokerageUserId()); if (secondUser == null || !BooleanUtil.isTrue(secondUser.getBrokerageEnabled())) { return; } @@ -103,9 +103,9 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe } if (BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus().equals(record.getStatus())) { - memberUserService.updateUserFrozenBrokeragePrice(userId, -record.getPrice()); + tradeBrokerageUserService.updateUserFrozenBrokeragePrice(userId, -record.getPrice()); } else if (BrokerageRecordStatusEnum.SETTLEMENT.getStatus().equals(record.getStatus())) { - memberUserService.updateUserBrokeragePrice(userId, -record.getPrice()); + tradeBrokerageUserService.updateUserBrokeragePrice(userId, -record.getPrice()); } } @@ -140,7 +140,7 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe * @param brokeragePercent 佣金比例 * @param skuBrokeragePriceFun 商品 SKU 设置的佣金 */ - private void addBrokerage(MemberUserDO user, List list, Integer brokerageFrozenDays, + private void addBrokerage(TradeBrokerageUserDO user, List list, Integer brokerageFrozenDays, Integer brokeragePercent, Function skuBrokeragePriceFun) { // 处理冻结时间 brokerageFrozenDays = ObjectUtil.defaultIfNull(brokerageFrozenDays, 0); @@ -170,10 +170,10 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe if (brokerageFrozenDays > 0) { // 更新用户冻结佣金 - memberUserService.updateUserFrozenBrokeragePrice(user.getId(), totalBrokerage); + tradeBrokerageUserService.updateUserFrozenBrokeragePrice(user.getId(), totalBrokerage); } else { // 更新用户可用佣金 - memberUserService.updateUserBrokeragePrice(user.getId(), totalBrokerage); + tradeBrokerageUserService.updateUserBrokeragePrice(user.getId(), totalBrokerage); } } @@ -214,7 +214,7 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe } // 更新用户冻结佣金 - memberUserService.updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(record.getUserId(), -record.getPrice()); + tradeBrokerageUserService.updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(record.getUserId(), -record.getPrice()); log.info("[unfreezeRecord][record({}) 更新为已结算成功]", record.getId()); return true; diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/dto/BrokerageAddReqDTO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/BrokerageAddReqDTO.java similarity index 89% rename from yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/dto/BrokerageAddReqDTO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/BrokerageAddReqDTO.java index c46645201..a15ef76c0 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/dto/BrokerageAddReqDTO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/BrokerageAddReqDTO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.member.api.brokerage.dto; +package cn.iocoder.yudao.module.trade.service.brokerage.record.bo; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserService.java index 58970d724..773342e55 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserService.java @@ -53,4 +53,36 @@ public interface TradeBrokerageUserService { * @param brokerageEnabled 推广资格 */ void updateBrokerageEnabled(Long id, Boolean brokerageEnabled); + + /** + * 获得用户的推广人 + * + * @param id 用户编号 + * @return 用户的推广人 + */ + TradeBrokerageUserDO getInviteBrokerageUser(Long id); + + /** + * 更新用户佣金 + * + * @param id 用户编号 + * @param brokeragePrice 用户可用佣金 + */ + void updateUserBrokeragePrice(Long id, int brokeragePrice); + + /** + * 更新用户冻结佣金 + * + * @param id 用户编号 + * @param frozenBrokeragePrice 用户冻结佣金 + */ + void updateUserFrozenBrokeragePrice(Long id, int frozenBrokeragePrice); + + /** + * 更新用户冻结佣金(减少), 更新用户佣金(增加) + * + * @param id 用户编号 + * @param frozenBrokeragePrice 减少冻结佣金(负数) + */ + void updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(Long id, int frozenBrokeragePrice); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImpl.java index acbda456b..9691a8154 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImpl.java @@ -1,17 +1,21 @@ package cn.iocoder.yudao.module.trade.service.brokerage.user; +import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.TradeBrokerageUserPageReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user.TradeBrokerageUserMapper; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.util.Collection; import java.util.List; +import java.util.Optional; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.MEMBER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH; import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.BROKERAGE_USER_NOT_EXISTS; /** @@ -60,4 +64,43 @@ public class TradeBrokerageUserServiceImpl implements TradeBrokerageUserService validateBrokerageUserExists(id); } + @Override + public TradeBrokerageUserDO getInviteBrokerageUser(Long id) { + return Optional.ofNullable(id) + .map(this::getBrokerageUser) + .map(TradeBrokerageUserDO::getBrokerageUserId) + .map(this::getBrokerageUser) + .orElse(null); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateUserBrokeragePrice(Long id, int brokeragePrice) { + if (brokeragePrice > 0) { + brokerageUserMapper.updateBrokeragePriceIncr(id, brokeragePrice); + } else if (brokeragePrice < 0) { + brokerageUserMapper.updateBrokeragePriceDecr(id, brokeragePrice); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateUserFrozenBrokeragePrice(Long id, int frozenBrokeragePrice) { + if (frozenBrokeragePrice > 0) { + brokerageUserMapper.updateFrozenBrokeragePriceIncr(id, frozenBrokeragePrice); + } else if (frozenBrokeragePrice < 0) { + brokerageUserMapper.updateFrozenBrokeragePriceDecr(id, frozenBrokeragePrice); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(Long id, int frozenBrokeragePrice) { + Assert.isTrue(frozenBrokeragePrice < 0); + int updateRows = brokerageUserMapper.updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(id, frozenBrokeragePrice); + if (updateRows == 0) { + throw exception(MEMBER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH); + } + } + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index e2a0f6baf..9ab4842b8 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -12,8 +12,8 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.module.member.api.address.AddressApi; import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; -import cn.iocoder.yudao.module.member.api.brokerage.BrokerageApi; -import cn.iocoder.yudao.module.member.api.brokerage.dto.BrokerageAddReqDTO; +import cn.iocoder.yudao.module.trade.service.brokerage.record.MemberBrokerageRecordService; +import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.BrokerageAddReqDTO; import cn.iocoder.yudao.module.member.api.level.MemberLevelApi; import cn.iocoder.yudao.module.member.api.point.MemberPointApi; import cn.iocoder.yudao.module.member.api.user.MemberUserApi; @@ -120,7 +120,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @Resource private MemberPointApi memberPointApi; @Resource - private BrokerageApi brokerageApi; + private MemberBrokerageRecordService memberBrokerageRecordService; @Resource private ProductCommentApi productCommentApi; @@ -754,12 +754,12 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { List orderItems = tradeOrderItemMapper.selectListByOrderId(orderId); List list = convertList(orderItems, item -> TradeOrderConvert.INSTANCE.convert(item, productSkuApi.getSku(item.getSkuId()))); - brokerageApi.addBrokerage(userId, list); + memberBrokerageRecordService.addBrokerage(userId, list); } @Async protected void cancelBrokerageAsync(Long userId, Long orderItemId) { - brokerageApi.cancelBrokerage(userId, String.valueOf(orderItemId)); + memberBrokerageRecordService.cancelBrokerage(userId, String.valueOf(orderItemId)); } /** diff --git a/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImplTest.java b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/MemberBrokerageRecordServiceImplTest.java similarity index 87% rename from yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImplTest.java rename to yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/MemberBrokerageRecordServiceImplTest.java index d5991b4e8..ae367ae63 100644 --- a/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImplTest.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/MemberBrokerageRecordServiceImplTest.java @@ -1,13 +1,13 @@ -package cn.iocoder.yudao.module.member.service.brokerage.record; +package cn.iocoder.yudao.module.trade.service.brokerage.record; import cn.hutool.core.util.NumberUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; -import cn.iocoder.yudao.module.member.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; -import cn.iocoder.yudao.module.member.dal.mysql.brokerage.record.MemberBrokerageRecordMapper; -import cn.iocoder.yudao.module.member.service.point.MemberPointConfigService; -import cn.iocoder.yudao.module.member.service.user.MemberUserService; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; +import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record.MemberBrokerageRecordMapper; +import cn.iocoder.yudao.module.trade.service.brokerage.user.TradeBrokerageUserService; +import cn.iocoder.yudao.module.trade.service.config.TradeConfigService; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; @@ -39,9 +39,9 @@ public class MemberBrokerageRecordServiceImplTest extends BaseDbUnitTest { private MemberBrokerageRecordMapper memberBrokerageRecordMapper; @MockBean - private MemberPointConfigService memberPointConfigService; + private TradeConfigService tradeConfigService; @MockBean - private MemberUserService memberUserService; + private TradeBrokerageUserService tradeBrokerageUserService; @Test @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/BrokerageApi.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/BrokerageApi.java deleted file mode 100644 index d01ce5845..000000000 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/BrokerageApi.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.module.member.api.brokerage; - -import cn.iocoder.yudao.module.member.api.brokerage.dto.BrokerageAddReqDTO; - -import java.util.List; - -/** - * 佣金 API 接口 - * - * @author owen - */ -public interface BrokerageApi { - - /** - * 增加佣金 - * - * @param userId 会员ID - * @param list 请求参数列表 - */ - void addBrokerage(Long userId, List list); - - /** - * 取消佣金 - * - * @param userId 会员ID - * @param bizId 业务编号 - */ - void cancelBrokerage(Long userId, String bizId); - -} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/BrokerageApiImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/BrokerageApiImpl.java deleted file mode 100644 index 662c5165a..000000000 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/brokerage/BrokerageApiImpl.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.iocoder.yudao.module.member.api.brokerage; - -import cn.iocoder.yudao.module.member.api.brokerage.dto.BrokerageAddReqDTO; -import cn.iocoder.yudao.module.member.service.brokerage.record.MemberBrokerageRecordService; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import javax.annotation.Resource; -import java.util.List; - -/** - * 佣金 API 实现类 - * - * @author owen - */ -@Service -@Validated -public class BrokerageApiImpl implements BrokerageApi { - - @Resource - private MemberBrokerageRecordService memberBrokerageRecordService; - - @Override - public void addBrokerage(Long userId, List list) { - memberBrokerageRecordService.addBrokerage(userId, list); - } - - @Override - public void cancelBrokerage(Long userId, String bizId) { - memberBrokerageRecordService.cancelBrokerage(userId, bizId); - } -} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/vo/config/MemberPointConfigBaseVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/vo/config/MemberPointConfigBaseVO.java index acdadb6bc..f946e4a27 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/vo/config/MemberPointConfigBaseVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/vo/config/MemberPointConfigBaseVO.java @@ -1,17 +1,9 @@ package cn.iocoder.yudao.module.member.controller.admin.point.vo.config; -import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageBindModeEnum; -import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageEnabledConditionEnum; -import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageWithdrawTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import org.hibernate.validator.constraints.Range; -import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; -import javax.validation.constraints.PositiveOrZero; -import java.util.List; /** * 会员积分配置 Base VO,提供给添加、修改、详细的子 VO 使用 @@ -36,53 +28,4 @@ public class MemberPointConfigBaseVO { @NotNull(message = "1 元赠送积分不能为空") private Integer tradeGivePoint; - // ========== 分销相关 ========== - - @Schema(description = "是否启用分佣", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - @NotNull(message = "是否启用分佣不能为空") - private Boolean brokerageEnabled; - - @Schema(description = "分佣模式", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") - @NotNull(message = "分佣模式不能为空") - @InEnum(value = BrokerageEnabledConditionEnum.class, message = "分佣模式必须是 {value}") - private Integer brokerageEnabledCondition; - - @Schema(description = "分销关系绑定模式", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") - @NotNull(message = "分销关系绑定模式不能为空") - @InEnum(value = BrokerageBindModeEnum.class, message = "分销关系绑定模式必须是 {value}") - private Integer brokerageBindMode; - - @Schema(description = "分销海报图地址数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/yudao.jpg]") - private List brokeragePostUrls; - - @Schema(description = "一级返佣比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") - @NotNull(message = "一级返佣比例不能为空") - @Range(min = 0, max = 100, message = "一级返佣比例必须在 0 - 100 之间") - private Integer brokerageFirstPercent; - - @Schema(description = "二级返佣比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") - @NotNull(message = "二级返佣比例不能为空") - @Range(min = 0, max = 100, message = "二级返佣比例必须在 0 - 100 之间") - private Integer brokerageSecondPercent; - - @Schema(description = "用户提现最低金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") - @NotNull(message = "用户提现最低金额不能为空") - @PositiveOrZero(message = "用户提现最低金额不能是负数") - private Integer brokerageWithdrawMinPrice; - - @Schema(description = "提现银行", requiredMode = Schema.RequiredMode.REQUIRED, example = "[0, 1]") - @NotEmpty(message = "提现银行不能为空") - private List brokerageBankNames; - - @Schema(description = "佣金冻结时间(天)", requiredMode = Schema.RequiredMode.REQUIRED, example = "7") - @NotNull(message = "佣金冻结时间(天)不能为空") - @PositiveOrZero(message = "佣金冻结时间不能是负数") - private Integer brokerageFrozenDays; - - @Schema(description = "提现方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "[0, 1]") - @NotNull(message = "提现方式不能为空") - @InEnum(value = BrokerageWithdrawTypeEnum.class, message = "提现方式必须是 {value}") - private List brokerageWithdrawType; - - } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/point/MemberPointConfigDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/point/MemberPointConfigDO.java index 8f44bd948..4a6354b03 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/point/MemberPointConfigDO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/point/MemberPointConfigDO.java @@ -1,19 +1,11 @@ package cn.iocoder.yudao.module.member.dal.dataobject.point; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.framework.mybatis.core.type.IntegerListTypeHandler; -import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageBindModeEnum; -import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageEnabledConditionEnum; -import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageWithdrawTypeEnum; import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; -import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import lombok.*; -import java.util.List; - /** * 会员积分配置 DO * @@ -53,56 +45,4 @@ public class MemberPointConfigDO extends BaseDO { */ private Integer tradeGivePoint; - // ========== 分销相关 ========== - - /** - * 是否启用分佣 - */ - private Boolean brokerageEnabled; - /** - * 分佣模式 - * - * 枚举 {@link BrokerageEnabledConditionEnum 对应的类} - */ - private Integer brokerageEnabledCondition; - /** - * 分销关系绑定模式 - * - * 枚举 {@link BrokerageBindModeEnum 对应的类} - */ - private Integer brokerageBindMode; - /** - * 分销海报图地址数组 - */ - @TableField(typeHandler = JacksonTypeHandler.class) - private List brokeragePostUrls; - /** - * 一级返佣比例 - */ - private Integer brokerageFirstPercent; - /** - * 二级返佣比例 - */ - private Integer brokerageSecondPercent; - /** - * 用户提现最低金额 - */ - private Integer brokerageWithdrawMinPrice; - /** - * 提现银行 - */ - @TableField(typeHandler = IntegerListTypeHandler.class) - private List brokerageBankNames; - /** - * 佣金冻结时间(天) - */ - private Integer brokerageFrozenDays; - /** - * 提现方式 - * - * 枚举 {@link BrokerageWithdrawTypeEnum 对应的类} - */ - @TableField(typeHandler = IntegerListTypeHandler.class) - private List brokerageWithdrawType; - } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java index 2dc47be90..7e35cdf2a 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java @@ -1,14 +1,12 @@ package cn.iocoder.yudao.module.member.dal.mysql.user; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserPageReqVO; import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; import java.util.List; @@ -63,79 +61,4 @@ public interface MemberUserMapper extends BaseMapperX { return selectCount(new LambdaQueryWrapperX() .apply("FIND_IN_SET({0}, tag_ids)", tagId)); } - - /** - * 更新用户可用佣金(增加) - * - * @param id 用户编号 - * @param incrCount 增加佣金(正数) - */ - default void updateBrokeragePriceIncr(Long id, int incrCount) { - Assert.isTrue(incrCount > 0); - LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() - .setSql(" brokerage_price = brokerage_price + " + incrCount) - .eq(MemberUserDO::getId, id); - update(null, lambdaUpdateWrapper); - } - - /** - * 更新用户可用佣金(减少) - * 注意:理论上佣金可能已经提现,这时会扣出负数,确保平台不会造成损失 - * - * @param id 用户编号 - * @param incrCount 增加佣金(负数) - */ - default void updateBrokeragePriceDecr(Long id, int incrCount) { - Assert.isTrue(incrCount < 0); - LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() - .setSql(" brokerage_price = brokerage_price + " + incrCount) // 负数,所以使用 + 号 - .eq(MemberUserDO::getId, id); - update(null, lambdaUpdateWrapper); - } - - /** - * 更新用户冻结佣金(增加) - * - * @param id 用户编号 - * @param incrCount 增加冻结佣金(正数) - */ - default void updateFrozenBrokeragePriceIncr(Long id, int incrCount) { - Assert.isTrue(incrCount > 0); - LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() - .setSql(" frozen_brokerage_price = frozen_brokerage_price + " + incrCount) - .eq(MemberUserDO::getId, id); - update(null, lambdaUpdateWrapper); - } - - /** - * 更新用户冻结佣金(减少) - * 注意:理论上冻结佣金可能已经解冻,这时会扣出负数,确保平台不会造成损失 - * - * @param id 用户编号 - * @param incrCount 减少冻结佣金(负数) - */ - default void updateFrozenBrokeragePriceDecr(Long id, int incrCount) { - Assert.isTrue(incrCount < 0); - LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() - .setSql(" frozen_brokerage_price = frozen_brokerage_price + " + incrCount) // 负数,所以使用 + 号 - .eq(MemberUserDO::getId, id); - update(null, lambdaUpdateWrapper); - } - - /** - * 更新用户冻结佣金(减少), 更新用户佣金(增加) - * - * @param id 用户编号 - * @param incrCount 减少冻结佣金(负数) - * @return 更新条数 - */ - default int updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(Long id, int incrCount) { - Assert.isTrue(incrCount < 0); - LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() - .setSql(" frozen_brokerage_price = frozen_brokerage_price + " + incrCount + // 负数,所以使用 + 号 - ", brokerage_price = brokerage_price + " + -incrCount) // 负数,所以使用 - 号 - .eq(MemberUserDO::getId, id) - .ge(MemberUserDO::getFrozenBrokeragePrice, -incrCount); // cas 逻辑 - return update(null, lambdaUpdateWrapper); - } } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java index 7f599a049..f1a0a7265 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java @@ -166,36 +166,4 @@ public interface MemberUserService { * @param point 积分数量 */ void updateUserPoint(Long userId, Integer point); - - /** - * 获得用户的推广人 - * - * @param id 用户编号 - * @return 用户的推广人 - */ - MemberUserDO getBrokerageUser(Long id); - - /** - * 更新用户佣金 - * - * @param id 用户编号 - * @param brokeragePrice 用户可用佣金 - */ - void updateUserBrokeragePrice(Long id, int brokeragePrice); - - /** - * 更新用户冻结佣金 - * - * @param id 用户编号 - * @param frozenBrokeragePrice 用户冻结佣金 - */ - void updateUserFrozenBrokeragePrice(Long id, int frozenBrokeragePrice); - - /** - * 更新用户冻结佣金(减少), 更新用户佣金(增加) - * - * @param id 用户编号 - * @param frozenBrokeragePrice 减少冻结佣金(负数) - */ - void updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(Long id, int frozenBrokeragePrice); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java index 53b452d7c..c5b674cc8 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.member.service.user; -import cn.hutool.core.lang.Assert; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; @@ -31,7 +30,6 @@ import javax.validation.Valid; import java.time.LocalDateTime; import java.util.Collection; import java.util.List; -import java.util.Optional; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; @@ -261,43 +259,4 @@ public class MemberUserServiceImpl implements MemberUserService { memberUserMapper.updateById(new MemberUserDO().setId(userId).setPoint(point)); } - @Override - public MemberUserDO getBrokerageUser(Long id) { - return Optional.ofNullable(id) - .map(this::getUser) - .map(MemberUserDO::getBrokerageUserId) - .map(this::getUser) - .orElse(null); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void updateUserBrokeragePrice(Long id, int brokeragePrice) { - if (brokeragePrice > 0) { - memberUserMapper.updateBrokeragePriceIncr(id, brokeragePrice); - } else if (brokeragePrice < 0) { - memberUserMapper.updateBrokeragePriceDecr(id, brokeragePrice); - } - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void updateUserFrozenBrokeragePrice(Long id, int frozenBrokeragePrice) { - if (frozenBrokeragePrice > 0) { - memberUserMapper.updateFrozenBrokeragePriceIncr(id, frozenBrokeragePrice); - } else if (frozenBrokeragePrice < 0) { - memberUserMapper.updateFrozenBrokeragePriceDecr(id, frozenBrokeragePrice); - } - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(Long id, int frozenBrokeragePrice) { - Assert.isTrue(frozenBrokeragePrice < 0); - int updateRows = memberUserMapper.updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(id, frozenBrokeragePrice); - if (updateRows == 0) { - throw exception(MEMBER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH); - } - } - } From fa53a3b15e4f214df3cddf8950907b4232b39649 Mon Sep 17 00:00:00 2001 From: owen Date: Wed, 6 Sep 2023 00:35:40 +0800 Subject: [PATCH 19/50] =?UTF-8?q?trade:=20MemberBrokerageRecord=20?= =?UTF-8?q?=E9=87=8D=E5=91=BD=E5=90=8D=E4=B8=BA=20TradeBrokerageRecord?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/mysql/brokerage.sql | 14 ++--- ...va => TradeBrokerageRecordController.java} | 32 +++++----- ...O.java => TradeBrokerageRecordBaseVO.java} | 2 +- ...ava => TradeBrokerageRecordPageReqVO.java} | 2 +- ...O.java => TradeBrokerageRecordRespVO.java} | 2 +- ....java => TradeBrokerageRecordConvert.java} | 18 +++--- .../convert/order/TradeOrderConvert.java | 6 +- ...ordDO.java => TradeBrokerageRecordDO.java} | 6 +- .../record/MemberBrokerageRecordMapper.java | 47 --------------- .../record/TradeBrokerageRecordMapper.java | 47 +++++++++++++++ ...a => TradeBrokerageRecordUnfreezeJob.java} | 8 +-- ....java => TradeBrokerageRecordService.java} | 14 ++--- ...a => TradeBrokerageRecordServiceImpl.java} | 58 +++++++++---------- ...eAddReqDTO.java => BrokerageAddReqBO.java} | 4 +- .../order/TradeOrderUpdateServiceImpl.java | 12 ++-- ... TradeBrokerageRecordServiceImplTest.java} | 42 +++++++------- .../src/test/resources/sql/clean.sql | 3 +- .../src/test/resources/sql/create_tables.sql | 23 +++++++- .../src/test/resources/sql/clean.sql | 3 +- .../src/test/resources/sql/create_tables.sql | 23 +------- 20 files changed, 183 insertions(+), 183 deletions(-) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/{MemberBrokerageRecordController.java => TradeBrokerageRecordController.java} (51%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/{MemberBrokerageRecordBaseVO.java => TradeBrokerageRecordBaseVO.java} (98%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/{MemberBrokerageRecordPageReqVO.java => TradeBrokerageRecordPageReqVO.java} (94%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/{MemberBrokerageRecordRespVO.java => TradeBrokerageRecordRespVO.java} (88%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/{MemberBrokerageRecordConvert.java => TradeBrokerageRecordConvert.java} (69%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/{MemberBrokerageRecordDO.java => TradeBrokerageRecordDO.java} (85%) delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/TradeBrokerageRecordMapper.java rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/brokerage/{MemberBrokerageRecordUnfreezeJob.java => TradeBrokerageRecordUnfreezeJob.java} (63%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/{MemberBrokerageRecordService.java => TradeBrokerageRecordService.java} (74%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/{MemberBrokerageRecordServiceImpl.java => TradeBrokerageRecordServiceImpl.java} (78%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/{BrokerageAddReqDTO.java => BrokerageAddReqBO.java} (90%) rename yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/{MemberBrokerageRecordServiceImplTest.java => TradeBrokerageRecordServiceImplTest.java} (66%) diff --git a/sql/mysql/brokerage.sql b/sql/mysql/brokerage.sql index 161dfa256..127fcb728 100644 --- a/sql/mysql/brokerage.sql +++ b/sql/mysql/brokerage.sql @@ -42,7 +42,7 @@ create index idx_invite_user_id on trade_brokerage_user (brokerage_user_id) comm create index idx_agent on trade_brokerage_user (brokerage_enabled) comment '是否成为推广员'; -create table member_brokerage_record +create table trade_brokerage_record ( id int auto_increment comment '编号' primary key, @@ -65,12 +65,12 @@ create table member_brokerage_record ) comment '佣金记录'; -create index idx_user_id on member_brokerage_record (user_id) comment '用户编号'; -create index idx_biz on member_brokerage_record (biz_type, biz_id) comment '业务'; -create index idx_status on member_brokerage_record (status) comment '状态'; +create index idx_user_id on trade_brokerage_record (user_id) comment '用户编号'; +create index idx_biz on trade_brokerage_record (biz_type, biz_id) comment '业务'; +create index idx_status on trade_brokerage_record (status) comment '状态'; -create table member_brokerage_withdraw +create table trade_brokerage_withdraw ( id int auto_increment comment '编号' primary key, @@ -97,8 +97,8 @@ create table member_brokerage_withdraw ) comment '佣金提现'; -create index idx_user_id on member_brokerage_withdraw (user_id) comment '用户编号'; -create index idx_audit_status on member_brokerage_withdraw (status) comment '状态'; +create index idx_user_id on trade_brokerage_withdraw (user_id) comment '用户编号'; +create index idx_audit_status on trade_brokerage_withdraw (status) comment '状态'; -- 增加字典 insert into system_dict_type(type, name) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/MemberBrokerageRecordController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/TradeBrokerageRecordController.java similarity index 51% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/MemberBrokerageRecordController.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/TradeBrokerageRecordController.java index c4bc9bb37..38b2f4d71 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/MemberBrokerageRecordController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/TradeBrokerageRecordController.java @@ -2,11 +2,11 @@ package cn.iocoder.yudao.module.trade.controller.admin.brokerage.record; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.MemberBrokerageRecordRespVO; -import cn.iocoder.yudao.module.trade.convert.brokerage.record.MemberBrokerageRecordConvert; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; -import cn.iocoder.yudao.module.trade.service.brokerage.record.MemberBrokerageRecordService; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordPageReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordRespVO; +import cn.iocoder.yudao.module.trade.convert.brokerage.record.TradeBrokerageRecordConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.TradeBrokerageRecordDO; +import cn.iocoder.yudao.module.trade.service.brokerage.record.TradeBrokerageRecordService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -24,28 +24,28 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @Tag(name = "管理后台 - 佣金记录") @RestController -@RequestMapping("/trade/member-brokerage-record") +@RequestMapping("/trade/brokerage-record") @Validated -public class MemberBrokerageRecordController { +public class TradeBrokerageRecordController { @Resource - private MemberBrokerageRecordService memberBrokerageRecordService; + private TradeBrokerageRecordService tradeBrokerageRecordService; @GetMapping("/get") @Operation(summary = "获得佣金记录") @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('member:member-brokerage-record:query')") - public CommonResult getMemberBrokerageRecord(@RequestParam("id") Integer id) { - MemberBrokerageRecordDO memberBrokerageRecord = memberBrokerageRecordService.getMemberBrokerageRecord(id); - return success(MemberBrokerageRecordConvert.INSTANCE.convert(memberBrokerageRecord)); + @PreAuthorize("@ss.hasPermission('trade:brokerage-record:query')") + public CommonResult getBrokerageRecord(@RequestParam("id") Integer id) { + TradeBrokerageRecordDO tradeBrokerageRecord = tradeBrokerageRecordService.getBrokerageRecord(id); + return success(TradeBrokerageRecordConvert.INSTANCE.convert(tradeBrokerageRecord)); } @GetMapping("/page") @Operation(summary = "获得佣金记录分页") - @PreAuthorize("@ss.hasPermission('member:member-brokerage-record:query')") - public CommonResult> getMemberBrokerageRecordPage(@Valid MemberBrokerageRecordPageReqVO pageVO) { - PageResult pageResult = memberBrokerageRecordService.getMemberBrokerageRecordPage(pageVO); - return success(MemberBrokerageRecordConvert.INSTANCE.convertPage(pageResult)); + @PreAuthorize("@ss.hasPermission('trade:brokerage-record:query')") + public CommonResult> getBrokerageRecordPage(@Valid TradeBrokerageRecordPageReqVO pageVO) { + PageResult pageResult = tradeBrokerageRecordService.getBrokerageRecordPage(pageVO); + return success(TradeBrokerageRecordConvert.INSTANCE.convertPage(pageResult)); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/MemberBrokerageRecordBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordBaseVO.java similarity index 98% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/MemberBrokerageRecordBaseVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordBaseVO.java index 51cd4a631..1fb87f294 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/MemberBrokerageRecordBaseVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordBaseVO.java @@ -14,7 +14,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class MemberBrokerageRecordBaseVO { +public class TradeBrokerageRecordBaseVO { @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25973") @NotNull(message = "用户编号不能为空") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/MemberBrokerageRecordPageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordPageReqVO.java similarity index 94% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/MemberBrokerageRecordPageReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordPageReqVO.java index 3a5e05527..abd948f09 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/MemberBrokerageRecordPageReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordPageReqVO.java @@ -15,7 +15,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class MemberBrokerageRecordPageReqVO extends PageParam { +public class TradeBrokerageRecordPageReqVO extends PageParam { @Schema(description = "用户编号", example = "25973") private Long userId; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/MemberBrokerageRecordRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordRespVO.java similarity index 88% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/MemberBrokerageRecordRespVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordRespVO.java index 3550a64ba..724d7d3e5 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/MemberBrokerageRecordRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordRespVO.java @@ -11,7 +11,7 @@ import java.time.LocalDateTime; @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class MemberBrokerageRecordRespVO extends MemberBrokerageRecordBaseVO { +public class TradeBrokerageRecordRespVO extends TradeBrokerageRecordBaseVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28896") private Integer id; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/MemberBrokerageRecordConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/TradeBrokerageRecordConvert.java similarity index 69% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/MemberBrokerageRecordConvert.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/TradeBrokerageRecordConvert.java index 48af52cf5..b84e51354 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/MemberBrokerageRecordConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/TradeBrokerageRecordConvert.java @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.trade.convert.brokerage.record; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.MemberBrokerageRecordRespVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordRespVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.TradeBrokerageRecordDO; import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; @@ -19,22 +19,22 @@ import java.util.List; * @author owen */ @Mapper -public interface MemberBrokerageRecordConvert { +public interface TradeBrokerageRecordConvert { - MemberBrokerageRecordConvert INSTANCE = Mappers.getMapper(MemberBrokerageRecordConvert.class); + TradeBrokerageRecordConvert INSTANCE = Mappers.getMapper(TradeBrokerageRecordConvert.class); - MemberBrokerageRecordRespVO convert(MemberBrokerageRecordDO bean); + TradeBrokerageRecordRespVO convert(TradeBrokerageRecordDO bean); - List convertList(List list); + List convertList(List list); - PageResult convertPage(PageResult page); + PageResult convertPage(PageResult page); - default MemberBrokerageRecordDO convert(TradeBrokerageUserDO user, String bizId, int brokerageFrozenDays, int brokerage, LocalDateTime unfreezeTime) { + default TradeBrokerageRecordDO convert(TradeBrokerageUserDO user, String bizId, int brokerageFrozenDays, int brokerage, LocalDateTime unfreezeTime) { // 不冻结时,佣金直接就是结算状态 Integer status = brokerageFrozenDays > 0 ? BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus() : BrokerageRecordStatusEnum.SETTLEMENT.getStatus(); - return new MemberBrokerageRecordDO() + return new TradeBrokerageRecordDO() .setUserId(user.getId()) .setBizType(BrokerageRecordBizTypeEnum.ORDER.getType()) .setBizId(bizId) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java index d17b81124..f42af2d73 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java @@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.common.util.string.StrUtils; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; -import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.BrokerageAddReqDTO; +import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.BrokerageAddReqBO; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; import cn.iocoder.yudao.module.pay.enums.DictTypeConstants; @@ -275,8 +275,8 @@ public interface TradeOrderConvert { TradeOrderDO convert(TradeOrderRemarkReqVO reqVO); - default BrokerageAddReqDTO convert(TradeOrderItemDO item, ProductSkuRespDTO sku) { - return new BrokerageAddReqDTO().setBizId(String.valueOf(item.getId())) + default BrokerageAddReqBO convert(TradeOrderItemDO item, ProductSkuRespDTO sku) { + return new BrokerageAddReqBO().setBizId(String.valueOf(item.getId())) .setPayPrice(item.getPayPrice()).setCount(item.getCount()) .setSkuFirstBrokeragePrice(sku.getSubCommissionFirstPrice()) .setSkuSecondBrokeragePrice(sku.getSubCommissionSecondPrice()); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/MemberBrokerageRecordDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/TradeBrokerageRecordDO.java similarity index 85% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/MemberBrokerageRecordDO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/TradeBrokerageRecordDO.java index 94d37ff89..0bf7c0cf2 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/MemberBrokerageRecordDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/TradeBrokerageRecordDO.java @@ -15,15 +15,15 @@ import java.time.LocalDateTime; * * @author owen */ -@TableName("member_brokerage_record") -@KeySequence("member_brokerage_record_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@TableName("trade_brokerage_record") +@KeySequence("trade_brokerage_record_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) @Builder @NoArgsConstructor @AllArgsConstructor -public class MemberBrokerageRecordDO extends BaseDO { +public class TradeBrokerageRecordDO extends BaseDO { /** * 编号 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java deleted file mode 100644 index da89b8bba..000000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java +++ /dev/null @@ -1,47 +0,0 @@ -package cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import org.apache.ibatis.annotations.Mapper; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * 佣金记录 Mapper - * - * @author owen - */ -@Mapper -public interface MemberBrokerageRecordMapper extends BaseMapperX { - - default PageResult selectPage(MemberBrokerageRecordPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(MemberBrokerageRecordDO::getUserId, reqVO.getUserId()) - .eqIfPresent(MemberBrokerageRecordDO::getBizType, reqVO.getBizType()) - .eqIfPresent(MemberBrokerageRecordDO::getStatus, reqVO.getStatus()) - .betweenIfPresent(MemberBrokerageRecordDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(MemberBrokerageRecordDO::getId)); - } - - default List selectListByStatusAndUnfreezeTimeLt(Integer status, LocalDateTime unfreezeTime) { - return selectList(new LambdaQueryWrapper() - .eq(MemberBrokerageRecordDO::getStatus, status) - .lt(MemberBrokerageRecordDO::getUnfreezeTime, unfreezeTime)); - } - - default int updateByIdAndStatus(Integer id, Integer status, MemberBrokerageRecordDO updateObj) { - return update(updateObj, new LambdaQueryWrapper() - .eq(MemberBrokerageRecordDO::getId, id) - .eq(MemberBrokerageRecordDO::getStatus, status)); - } - - default MemberBrokerageRecordDO selectByUserIdAndBizTypeAndBizId(Integer bizType, String bizId) { - return selectOne(MemberBrokerageRecordDO::getBizType, bizType, - MemberBrokerageRecordDO::getBizId, bizId); - } -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/TradeBrokerageRecordMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/TradeBrokerageRecordMapper.java new file mode 100644 index 000000000..78efbc53a --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/TradeBrokerageRecordMapper.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.TradeBrokerageRecordDO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 佣金记录 Mapper + * + * @author owen + */ +@Mapper +public interface TradeBrokerageRecordMapper extends BaseMapperX { + + default PageResult selectPage(TradeBrokerageRecordPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(TradeBrokerageRecordDO::getUserId, reqVO.getUserId()) + .eqIfPresent(TradeBrokerageRecordDO::getBizType, reqVO.getBizType()) + .eqIfPresent(TradeBrokerageRecordDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(TradeBrokerageRecordDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(TradeBrokerageRecordDO::getId)); + } + + default List selectListByStatusAndUnfreezeTimeLt(Integer status, LocalDateTime unfreezeTime) { + return selectList(new LambdaQueryWrapper() + .eq(TradeBrokerageRecordDO::getStatus, status) + .lt(TradeBrokerageRecordDO::getUnfreezeTime, unfreezeTime)); + } + + default int updateByIdAndStatus(Integer id, Integer status, TradeBrokerageRecordDO updateObj) { + return update(updateObj, new LambdaQueryWrapper() + .eq(TradeBrokerageRecordDO::getId, id) + .eq(TradeBrokerageRecordDO::getStatus, status)); + } + + default TradeBrokerageRecordDO selectByUserIdAndBizTypeAndBizId(Integer bizType, String bizId) { + return selectOne(TradeBrokerageRecordDO::getBizType, bizType, + TradeBrokerageRecordDO::getBizId, bizId); + } +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/brokerage/MemberBrokerageRecordUnfreezeJob.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/brokerage/TradeBrokerageRecordUnfreezeJob.java similarity index 63% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/brokerage/MemberBrokerageRecordUnfreezeJob.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/brokerage/TradeBrokerageRecordUnfreezeJob.java index d41bc840c..94218d47e 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/brokerage/MemberBrokerageRecordUnfreezeJob.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/brokerage/TradeBrokerageRecordUnfreezeJob.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.trade.job.brokerage; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; -import cn.iocoder.yudao.module.trade.service.brokerage.record.MemberBrokerageRecordService; +import cn.iocoder.yudao.module.trade.service.brokerage.record.TradeBrokerageRecordService; import org.springframework.stereotype.Component; import javax.annotation.Resource; @@ -15,14 +15,14 @@ import javax.annotation.Resource; */ @Component @TenantJob -public class MemberBrokerageRecordUnfreezeJob implements JobHandler { +public class TradeBrokerageRecordUnfreezeJob implements JobHandler { @Resource - private MemberBrokerageRecordService memberBrokerageRecordService; + private TradeBrokerageRecordService tradeBrokerageRecordService; @Override public String execute(String param) { - int count = memberBrokerageRecordService.unfreezeRecord(); + int count = tradeBrokerageRecordService.unfreezeRecord(); return StrUtil.format("解冻佣金 {} 个", count); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/MemberBrokerageRecordService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordService.java similarity index 74% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/MemberBrokerageRecordService.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordService.java index 5cdd9e1b5..6b83bdbc0 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/MemberBrokerageRecordService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordService.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.trade.service.brokerage.record; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.BrokerageAddReqDTO; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.TradeBrokerageRecordDO; +import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.BrokerageAddReqBO; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordPageReqVO; import java.util.List; @@ -12,7 +12,7 @@ import java.util.List; * * @author owen */ -public interface MemberBrokerageRecordService { +public interface TradeBrokerageRecordService { /** * 获得佣金记录 @@ -20,7 +20,7 @@ public interface MemberBrokerageRecordService { * @param id 编号 * @return 佣金记录 */ - MemberBrokerageRecordDO getMemberBrokerageRecord(Integer id); + TradeBrokerageRecordDO getBrokerageRecord(Integer id); /** * 获得佣金记录分页 @@ -28,7 +28,7 @@ public interface MemberBrokerageRecordService { * @param pageReqVO 分页查询 * @return 佣金记录分页 */ - PageResult getMemberBrokerageRecordPage(MemberBrokerageRecordPageReqVO pageReqVO); + PageResult getBrokerageRecordPage(TradeBrokerageRecordPageReqVO pageReqVO); /** * 增加佣金 @@ -36,7 +36,7 @@ public interface MemberBrokerageRecordService { * @param userId 会员编号 * @param list 请求参数列表 */ - void addBrokerage(Long userId, List list); + void addBrokerage(Long userId, List list); /** * 取消佣金:将佣金记录,状态修改为已失效 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/MemberBrokerageRecordServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImpl.java similarity index 78% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/MemberBrokerageRecordServiceImpl.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImpl.java index e56ae5dab..5502bcbf7 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/MemberBrokerageRecordServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImpl.java @@ -6,13 +6,13 @@ import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.BrokerageAddReqDTO; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; -import cn.iocoder.yudao.module.trade.convert.brokerage.record.MemberBrokerageRecordConvert; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; +import cn.iocoder.yudao.module.trade.convert.brokerage.record.TradeBrokerageRecordConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.TradeBrokerageRecordDO; +import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.BrokerageAddReqBO; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordPageReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; -import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record.MemberBrokerageRecordMapper; +import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record.TradeBrokerageRecordMapper; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; import cn.iocoder.yudao.module.trade.service.brokerage.user.TradeBrokerageUserService; @@ -37,28 +37,28 @@ import java.util.function.Function; @Slf4j @Service @Validated -public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordService { +public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordService { @Resource - private MemberBrokerageRecordMapper memberBrokerageRecordMapper; + private TradeBrokerageRecordMapper tradeBrokerageRecordMapper; @Resource private TradeConfigService tradeConfigService; @Resource private TradeBrokerageUserService tradeBrokerageUserService; @Override - public MemberBrokerageRecordDO getMemberBrokerageRecord(Integer id) { - return memberBrokerageRecordMapper.selectById(id); + public TradeBrokerageRecordDO getBrokerageRecord(Integer id) { + return tradeBrokerageRecordMapper.selectById(id); } @Override - public PageResult getMemberBrokerageRecordPage(MemberBrokerageRecordPageReqVO pageReqVO) { - return memberBrokerageRecordMapper.selectPage(pageReqVO); + public PageResult getBrokerageRecordPage(TradeBrokerageRecordPageReqVO pageReqVO) { + return tradeBrokerageRecordMapper.selectPage(pageReqVO); } @Override @Transactional(rollbackFor = Exception.class) - public void addBrokerage(Long buyerId, List list) { + public void addBrokerage(Long buyerId, List list) { TradeConfigDO memberConfig = tradeConfigService.getTradeConfig(); // 0 未启用分销功能 if (memberConfig == null || !BooleanUtil.isTrue(memberConfig.getBrokerageEnabled())) { @@ -73,7 +73,7 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe } // 1.2 计算一级分佣 - addBrokerage(firstUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageFirstPercent(), BrokerageAddReqDTO::getSkuFirstBrokeragePrice); + addBrokerage(firstUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageFirstPercent(), BrokerageAddReqBO::getSkuFirstBrokeragePrice); // 2.1 获得二级推广员 @@ -83,20 +83,20 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe } // 2.2 计算二级分佣 - addBrokerage(secondUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageSecondPercent(), BrokerageAddReqDTO::getSkuSecondBrokeragePrice); + addBrokerage(secondUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageSecondPercent(), BrokerageAddReqBO::getSkuSecondBrokeragePrice); } @Override @Transactional(rollbackFor = Exception.class) public void cancelBrokerage(Long userId, String bizId) { - MemberBrokerageRecordDO record = memberBrokerageRecordMapper.selectByUserIdAndBizTypeAndBizId(BrokerageRecordBizTypeEnum.ORDER.getType(), bizId); + TradeBrokerageRecordDO record = tradeBrokerageRecordMapper.selectByUserIdAndBizTypeAndBizId(BrokerageRecordBizTypeEnum.ORDER.getType(), bizId); if (record == null || ObjectUtil.notEqual(record.getUserId(), userId)) { log.error("[cancelBrokerage][userId({})][bizId({}) 更新为已失效失败:记录不存在]", userId, bizId); return; } - MemberBrokerageRecordDO updateObj = new MemberBrokerageRecordDO().setStatus(BrokerageRecordStatusEnum.CANCEL.getStatus()); - int updateRows = memberBrokerageRecordMapper.updateByIdAndStatus(record.getId(), record.getStatus(), updateObj); + TradeBrokerageRecordDO updateObj = new TradeBrokerageRecordDO().setStatus(BrokerageRecordStatusEnum.CANCEL.getStatus()); + int updateRows = tradeBrokerageRecordMapper.updateByIdAndStatus(record.getId(), record.getStatus(), updateObj); if (updateRows == 0) { log.error("[cancelBrokerage][record({}) 更新为已失效失败]", record.getId()); return; @@ -140,8 +140,8 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe * @param brokeragePercent 佣金比例 * @param skuBrokeragePriceFun 商品 SKU 设置的佣金 */ - private void addBrokerage(TradeBrokerageUserDO user, List list, Integer brokerageFrozenDays, - Integer brokeragePercent, Function skuBrokeragePriceFun) { + private void addBrokerage(TradeBrokerageUserDO user, List list, Integer brokerageFrozenDays, + Integer brokeragePercent, Function skuBrokeragePriceFun) { // 处理冻结时间 brokerageFrozenDays = ObjectUtil.defaultIfNull(brokerageFrozenDays, 0); LocalDateTime unfreezeTime = null; @@ -151,12 +151,12 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe // 计算分佣 int totalBrokerage = 0; - List records = new ArrayList<>(); - for (BrokerageAddReqDTO dto : list) { + List records = new ArrayList<>(); + for (BrokerageAddReqBO dto : list) { int brokeragePerItem = calculateBrokerage(dto.getPayPrice(), brokeragePercent, skuBrokeragePriceFun.apply(dto)); if (brokeragePerItem > 0) { int brokerage = brokeragePerItem * dto.getCount(); - records.add(MemberBrokerageRecordConvert.INSTANCE.convert(user, dto.getBizId(), brokerageFrozenDays, brokerage, unfreezeTime)); + records.add(TradeBrokerageRecordConvert.INSTANCE.convert(user, dto.getBizId(), brokerageFrozenDays, brokerage, unfreezeTime)); totalBrokerage += brokerage; } } @@ -166,7 +166,7 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe } // 保存佣金记录 - memberBrokerageRecordMapper.insertBatch(records); + tradeBrokerageRecordMapper.insertBatch(records); if (brokerageFrozenDays > 0) { // 更新用户冻结佣金 @@ -180,7 +180,7 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe @Override public int unfreezeRecord() { // 1. 查询待结算的佣金记录 - List records = memberBrokerageRecordMapper.selectListByStatusAndUnfreezeTimeLt( + List records = tradeBrokerageRecordMapper.selectListByStatusAndUnfreezeTimeLt( BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus(), LocalDateTime.now()); if (CollUtil.isEmpty(records)) { return 0; @@ -188,7 +188,7 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe // 2. 遍历执行 int count = 0; - for (MemberBrokerageRecordDO record : records) { + for (TradeBrokerageRecordDO record : records) { try { boolean successful = getSelf().unfreezeRecord(record); if (successful) { @@ -202,12 +202,12 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe } @Transactional(rollbackFor = Exception.class) - public boolean unfreezeRecord(MemberBrokerageRecordDO record) { + public boolean unfreezeRecord(TradeBrokerageRecordDO record) { // 更新记录状态 - MemberBrokerageRecordDO updateObj = new MemberBrokerageRecordDO() + TradeBrokerageRecordDO updateObj = new TradeBrokerageRecordDO() .setStatus(BrokerageRecordStatusEnum.SETTLEMENT.getStatus()) .setUnfreezeTime(LocalDateTime.now()); - int updateRows = memberBrokerageRecordMapper.updateByIdAndStatus(record.getId(), record.getStatus(), updateObj); + int updateRows = tradeBrokerageRecordMapper.updateByIdAndStatus(record.getId(), record.getStatus(), updateObj); if (updateRows == 0) { log.error("[unfreezeRecord][record({}) 更新为已结算失败]", record.getId()); return false; @@ -225,7 +225,7 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe * * @return 自己 */ - private MemberBrokerageRecordServiceImpl getSelf() { + private TradeBrokerageRecordServiceImpl getSelf() { return SpringUtil.getBean(getClass()); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/BrokerageAddReqDTO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/BrokerageAddReqBO.java similarity index 90% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/BrokerageAddReqDTO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/BrokerageAddReqBO.java index a15ef76c0..a968d14ea 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/BrokerageAddReqDTO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/BrokerageAddReqBO.java @@ -5,13 +5,13 @@ import lombok.Data; import lombok.NoArgsConstructor; /** - * 佣金 增加 Request DTO + * 佣金 增加 Request BO * @author owen */ @Data @NoArgsConstructor @AllArgsConstructor -public class BrokerageAddReqDTO { +public class BrokerageAddReqBO { /** * 业务ID */ diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index 9ab4842b8..b75b7ac7c 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -12,8 +12,8 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.module.member.api.address.AddressApi; import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; -import cn.iocoder.yudao.module.trade.service.brokerage.record.MemberBrokerageRecordService; -import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.BrokerageAddReqDTO; +import cn.iocoder.yudao.module.trade.service.brokerage.record.TradeBrokerageRecordService; +import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.BrokerageAddReqBO; import cn.iocoder.yudao.module.member.api.level.MemberLevelApi; import cn.iocoder.yudao.module.member.api.point.MemberPointApi; import cn.iocoder.yudao.module.member.api.user.MemberUserApi; @@ -120,7 +120,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @Resource private MemberPointApi memberPointApi; @Resource - private MemberBrokerageRecordService memberBrokerageRecordService; + private TradeBrokerageRecordService tradeBrokerageRecordService; @Resource private ProductCommentApi productCommentApi; @@ -752,14 +752,14 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @Async protected void addBrokerageAsync(Long userId, Long orderId) { List orderItems = tradeOrderItemMapper.selectListByOrderId(orderId); - List list = convertList(orderItems, + List list = convertList(orderItems, item -> TradeOrderConvert.INSTANCE.convert(item, productSkuApi.getSku(item.getSkuId()))); - memberBrokerageRecordService.addBrokerage(userId, list); + tradeBrokerageRecordService.addBrokerage(userId, list); } @Async protected void cancelBrokerageAsync(Long userId, Long orderItemId) { - memberBrokerageRecordService.cancelBrokerage(userId, String.valueOf(orderItemId)); + tradeBrokerageRecordService.cancelBrokerage(userId, String.valueOf(orderItemId)); } /** diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/MemberBrokerageRecordServiceImplTest.java b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImplTest.java similarity index 66% rename from yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/MemberBrokerageRecordServiceImplTest.java rename to yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImplTest.java index ae367ae63..a6d8dffb1 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/MemberBrokerageRecordServiceImplTest.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImplTest.java @@ -3,9 +3,9 @@ package cn.iocoder.yudao.module.trade.service.brokerage.record; import cn.hutool.core.util.NumberUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; -import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record.MemberBrokerageRecordMapper; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.TradeBrokerageRecordDO; +import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record.TradeBrokerageRecordMapper; import cn.iocoder.yudao.module.trade.service.brokerage.user.TradeBrokerageUserService; import cn.iocoder.yudao.module.trade.service.config.TradeConfigService; import org.junit.jupiter.api.Disabled; @@ -26,17 +26,17 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; import static org.junit.jupiter.api.Assertions.assertEquals; /** - * {@link MemberBrokerageRecordServiceImpl} 的单元测试类 + * {@link TradeBrokerageRecordServiceImpl} 的单元测试类 * * @author owen */ -@Import(MemberBrokerageRecordServiceImpl.class) -public class MemberBrokerageRecordServiceImplTest extends BaseDbUnitTest { +@Import(TradeBrokerageRecordServiceImpl.class) +public class TradeBrokerageRecordServiceImplTest extends BaseDbUnitTest { @Resource - private MemberBrokerageRecordServiceImpl memberBrokerageRecordService; + private TradeBrokerageRecordServiceImpl tradeBrokerageRecordService; @Resource - private MemberBrokerageRecordMapper memberBrokerageRecordMapper; + private TradeBrokerageRecordMapper tradeBrokerageRecordMapper; @MockBean private TradeConfigService tradeConfigService; @@ -45,36 +45,36 @@ public class MemberBrokerageRecordServiceImplTest extends BaseDbUnitTest { @Test @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void testGetMemberBrokerageRecordPage() { + public void testGetBrokerageRecordPage() { // mock 数据 - MemberBrokerageRecordDO dbMemberBrokerageRecord = randomPojo(MemberBrokerageRecordDO.class, o -> { // 等会查询到 + TradeBrokerageRecordDO dbBrokerageRecord = randomPojo(TradeBrokerageRecordDO.class, o -> { // 等会查询到 o.setUserId(null); o.setBizType(null); o.setStatus(null); o.setCreateTime(null); }); - memberBrokerageRecordMapper.insert(dbMemberBrokerageRecord); + tradeBrokerageRecordMapper.insert(dbBrokerageRecord); // 测试 userId 不匹配 - memberBrokerageRecordMapper.insert(cloneIgnoreId(dbMemberBrokerageRecord, o -> o.setUserId(null))); + tradeBrokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setUserId(null))); // 测试 bizType 不匹配 - memberBrokerageRecordMapper.insert(cloneIgnoreId(dbMemberBrokerageRecord, o -> o.setBizType(null))); + tradeBrokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setBizType(null))); // 测试 status 不匹配 - memberBrokerageRecordMapper.insert(cloneIgnoreId(dbMemberBrokerageRecord, o -> o.setStatus(null))); + tradeBrokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setStatus(null))); // 测试 createTime 不匹配 - memberBrokerageRecordMapper.insert(cloneIgnoreId(dbMemberBrokerageRecord, o -> o.setCreateTime(null))); + tradeBrokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setCreateTime(null))); // 准备参数 - MemberBrokerageRecordPageReqVO reqVO = new MemberBrokerageRecordPageReqVO(); + TradeBrokerageRecordPageReqVO reqVO = new TradeBrokerageRecordPageReqVO(); reqVO.setUserId(null); reqVO.setBizType(null); reqVO.setStatus(null); reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); // 调用 - PageResult pageResult = memberBrokerageRecordService.getMemberBrokerageRecordPage(reqVO); + PageResult pageResult = tradeBrokerageRecordService.getBrokerageRecordPage(reqVO); // 断言 assertEquals(1, pageResult.getTotal()); assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbMemberBrokerageRecord, pageResult.getList().get(0)); + assertPojoEquals(dbBrokerageRecord, pageResult.getList().get(0)); } @Test @@ -84,7 +84,7 @@ public class MemberBrokerageRecordServiceImplTest extends BaseDbUnitTest { Integer percent = randomInt(1, 101); Integer skuBrokeragePrice = randomInt(); // 调用 - int brokerage = memberBrokerageRecordService.calculateBrokerage(payPrice, percent, skuBrokeragePrice); + int brokerage = tradeBrokerageRecordService.calculateBrokerage(payPrice, percent, skuBrokeragePrice); // 断言 assertEquals(brokerage, skuBrokeragePrice); } @@ -97,7 +97,7 @@ public class MemberBrokerageRecordServiceImplTest extends BaseDbUnitTest { Integer skuBrokeragePrice = randomEle(new Integer[]{0, null}); System.out.println("skuBrokeragePrice=" + skuBrokeragePrice); // 调用 - int brokerage = memberBrokerageRecordService.calculateBrokerage(payPrice, percent, skuBrokeragePrice); + int brokerage = tradeBrokerageRecordService.calculateBrokerage(payPrice, percent, skuBrokeragePrice); // 断言 assertEquals(brokerage, NumberUtil.div(NumberUtil.mul(payPrice, percent), 100, 0, RoundingMode.DOWN).intValue()); } @@ -109,7 +109,7 @@ public class MemberBrokerageRecordServiceImplTest extends BaseDbUnitTest { Integer percent = null; Integer skuBrokeragePrice = null; // 调用 - int brokerage = memberBrokerageRecordService.calculateBrokerage(payPrice, percent, skuBrokeragePrice); + int brokerage = tradeBrokerageRecordService.calculateBrokerage(payPrice, percent, skuBrokeragePrice); // 断言 assertEquals(brokerage, 0); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/clean.sql b/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/clean.sql index b0715ca16..f02fdcaf1 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/clean.sql +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/clean.sql @@ -2,4 +2,5 @@ DELETE FROM trade_order; DELETE FROM trade_order_item; DELETE FROM trade_after_sale; DELETE FROM trade_after_sale_log; -DELETE FROM "trade_brokerage_user"; +DELETE FROM trade_brokerage_user; +DELETE FROM trade_brokerage_record; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql b/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql index df68fd53b..02045d2c2 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql @@ -142,4 +142,25 @@ CREATE TABLE IF NOT EXISTS "trade_brokerage_user" "deleted" bit NOT NULL DEFAULT FALSE, "tenant_id" bigint NOT NULL DEFAULT '0', PRIMARY KEY ("id") -) COMMENT '分销用户'; \ No newline at end of file +) COMMENT '分销用户'; +CREATE TABLE IF NOT EXISTS "trade_brokerage_record" +( + "id" int NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "user_id" bigint NOT NULL, + "biz_id" varchar NOT NULL, + "biz_type" varchar NOT NULL, + "title" varchar NOT NULL, + "price" int NOT NULL, + "total_price" int NOT NULL, + "description" varchar NOT NULL, + "status" varchar NOT NULL, + "frozen_days" int NOT NULL, + "unfreeze_time" varchar, + "creator" varchar DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint not null default '0', + PRIMARY KEY ("id") +) COMMENT '佣金记录'; \ No newline at end of file diff --git a/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/clean.sql b/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/clean.sql index 6981982c4..f972e048d 100644 --- a/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/clean.sql +++ b/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/clean.sql @@ -2,5 +2,4 @@ DELETE FROM "member_user"; DELETE FROM "member_address"; DELETE FROM "member_tag"; DELETE FROM "member_level"; -DELETE FROM "member_group"; -DELETE FROM "member_brokerage_record"; \ No newline at end of file +DELETE FROM "member_group"; \ No newline at end of file diff --git a/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/create_tables.sql b/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/create_tables.sql index ccefc4bf1..5fdc526b0 100644 --- a/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/create_tables.sql +++ b/yudao-module-member/yudao-module-member-biz/src/test/resources/sql/create_tables.sql @@ -89,25 +89,4 @@ CREATE TABLE IF NOT EXISTS "member_group" "deleted" bit NOT NULL DEFAULT FALSE, "tenant_id" bigint not null default '0', PRIMARY KEY ("id") -) COMMENT '用户分组'; -CREATE TABLE IF NOT EXISTS "member_brokerage_record" -( - "id" int NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "user_id" bigint NOT NULL, - "biz_id" varchar NOT NULL, - "biz_type" varchar NOT NULL, - "title" varchar NOT NULL, - "price" int NOT NULL, - "total_price" int NOT NULL, - "description" varchar NOT NULL, - "status" varchar NOT NULL, - "frozen_days" int NOT NULL, - "unfreeze_time" varchar, - "creator" varchar DEFAULT '', - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar DEFAULT '', - "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - "tenant_id" bigint not null default '0', - PRIMARY KEY ("id") -) COMMENT '佣金记录'; \ No newline at end of file +) COMMENT '用户分组'; \ No newline at end of file From 3f51be6a2d26650f103f88d95a4cbe9ad942e2c3 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Wed, 6 Sep 2023 08:50:22 +0800 Subject: [PATCH 20/50] =?UTF-8?q?=E9=92=B1=E5=8C=85=E3=80=82=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E4=B8=8D=E9=9C=80=E8=A6=81=E7=9A=84=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/delegate/DelegatePayClient.java | 63 ------------------- .../core/client/impl/mock/MockPayClient.java | 5 +- .../client/impl/mock/MockPayClientConfig.java | 28 --------- .../core/enums/channel/PayChannelEnum.java | 3 +- .../admin/order/PayOrderController.java | 1 + 5 files changed, 5 insertions(+), 95 deletions(-) delete mode 100644 yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/delegate/DelegatePayClient.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClientConfig.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/delegate/DelegatePayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/delegate/DelegatePayClient.java deleted file mode 100644 index 65958d5a3..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/delegate/DelegatePayClient.java +++ /dev/null @@ -1,63 +0,0 @@ -package cn.iocoder.yudao.framework.pay.core.client.impl.delegate; - -import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; -import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; -import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; -import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; -import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; -import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; - -import java.util.Map; - -// TODO @jason:其它模块,主要是无法 pay client 初始化存在问题,所以我感觉,是不是可以搞个 PayClientInitializer 接口。这样,PayClientFactory 去 get 这个支付模式对应的 PayClientInitializer,通过它来创建。具体注入的地方,可以在 PayChannel init 方法那; -/** - * 代理支付 Client 的抽象类。 - * - * 用于支付 Client 由其它模块实现,例如钱包支付 - * - * @author jason - */ -public abstract class DelegatePayClient extends AbstractPayClient { - - private final DelegatePayClient delegate; - - public DelegatePayClient(Long channelId, String channelCode, PayClientConfig config) { - super(channelId, channelCode, config); - delegate = this; - } - - @Override - protected void doInit() { - delegate.doInit(); - } - - @Override - protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) { - return delegate.doUnifiedOrder(reqDTO); - } - - @Override - protected PayOrderRespDTO doGetOrder(String outTradeNo) { - return delegate.doGetOrder(outTradeNo); - } - - @Override - protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) { - return delegate.doUnifiedRefund(reqDTO); - } - - @Override - protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) { - return delegate.doGetRefund(outTradeNo, outRefundNo); - } - - @Override - protected PayRefundRespDTO doParseRefundNotify(Map params, String body) { - return delegate.doParseRefundNotify(params, body); - } - - @Override - protected PayOrderRespDTO doParseOrderNotify(Map params, String body) { - return delegate.doParseOrderNotify(params, body); - } -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClient.java index 1d3f4d48b..f26e76c28 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClient.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDT import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; +import cn.iocoder.yudao.framework.pay.core.client.impl.NonePayClientConfig; import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; import java.time.LocalDateTime; @@ -17,11 +18,11 @@ import java.util.Map; * * @author jason */ -public class MockPayClient extends AbstractPayClient { +public class MockPayClient extends AbstractPayClient { private static final String MOCK_RESP_SUCCESS_DATA = "MOCK_SUCCESS"; - public MockPayClient(Long channelId, MockPayClientConfig config) { + public MockPayClient(Long channelId, NonePayClientConfig config) { super(channelId, PayChannelEnum.MOCK.getCode(), config); } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClientConfig.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClientConfig.java deleted file mode 100644 index 3e35c52dc..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClientConfig.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.framework.pay.core.client.impl.mock; - -import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; -import lombok.Data; - -import javax.validation.Validator; - -/** - * 模拟支付的 PayClientConfig 实现类 - * - * @author jason - */ -@Data -public class MockPayClientConfig implements PayClientConfig { - - /** - * 配置名称 - * - * 如果不加任何属性,JsonUtils.parseObject2 解析会报错,所以暂时加个名称 - */ - private String name; - - @Override - public void validate(Validator validator) { - // 模拟支付配置无需校验 - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/channel/PayChannelEnum.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/channel/PayChannelEnum.java index cbe0a242a..411644153 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/channel/PayChannelEnum.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/channel/PayChannelEnum.java @@ -4,7 +4,6 @@ import cn.hutool.core.util.ArrayUtil; import cn.iocoder.yudao.framework.pay.core.client.impl.NonePayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig; -import cn.iocoder.yudao.framework.pay.core.client.impl.mock.MockPayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.impl.weixin.WxPayClientConfig; import lombok.AllArgsConstructor; import lombok.Getter; @@ -30,7 +29,7 @@ public enum PayChannelEnum { ALIPAY_QR("alipay_qr", "支付宝扫码支付", AlipayPayClientConfig.class), ALIPAY_BAR("alipay_bar", "支付宝条码支付", AlipayPayClientConfig.class), - MOCK("mock", "模拟支付", MockPayClientConfig.class), + MOCK("mock", "模拟支付", NonePayClientConfig.class), WALLET("wallet", "钱包支付", NonePayClientConfig.class); diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java index 3350b5877..a47031a2a 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java @@ -70,6 +70,7 @@ public class PayOrderController { @PostMapping("/submit") @Operation(summary = "提交支付订单") public CommonResult submitPayOrder(@RequestBody PayOrderSubmitReqVO reqVO) { + // 钱包支付需要 额外传 user_id 和 user_type if (Objects.equals(reqVO.getChannelCode(), PayChannelEnum.WALLET.getCode())) { Map channelExtras = reqVO.getChannelExtras() == null ? new HashMap<>(8) : reqVO.getChannelExtras(); channelExtras.put("user_id", String.valueOf(WebFrameworkUtils.getLoginUserId())); From 9074312fe301b54a093448427209529622e7b4d9 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Wed, 6 Sep 2023 10:34:24 +0800 Subject: [PATCH 21/50] =?UTF-8?q?=E5=90=8E=E5=8F=B0=E6=8E=A5=E5=85=A5?= =?UTF-8?q?=E9=92=B1=E5=8C=85=E6=94=AF=E4=BB=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-ui-admin/src/utils/constants.js | 4 ++ ...nnelForm.vue => noneConfigChannelForm.vue} | 53 ++++++++++--------- yudao-ui-admin/src/views/pay/app/index.vue | 25 +++++++-- .../src/views/pay/cashier/index.vue | 4 ++ 4 files changed, 56 insertions(+), 30 deletions(-) rename yudao-ui-admin/src/views/pay/app/components/{mockChannelForm.vue => noneConfigChannelForm.vue} (71%) diff --git a/yudao-ui-admin/src/utils/constants.js b/yudao-ui-admin/src/utils/constants.js index d62b1f8fc..2ce6d0041 100644 --- a/yudao-ui-admin/src/utils/constants.js +++ b/yudao-ui-admin/src/utils/constants.js @@ -163,6 +163,10 @@ export const PayChannelEnum = { MOCK : { "code": "mock", "name": "模拟支付" + }, + WALLET : { + "code": "wallet", + "name": "钱包支付" } } diff --git a/yudao-ui-admin/src/views/pay/app/components/mockChannelForm.vue b/yudao-ui-admin/src/views/pay/app/components/noneConfigChannelForm.vue similarity index 71% rename from yudao-ui-admin/src/views/pay/app/components/mockChannelForm.vue rename to yudao-ui-admin/src/views/pay/app/components/noneConfigChannelForm.vue index e2d6162f1..51fcc53dd 100644 --- a/yudao-ui-admin/src/views/pay/app/components/mockChannelForm.vue +++ b/yudao-ui-admin/src/views/pay/app/components/noneConfigChannelForm.vue @@ -5,7 +5,8 @@ + :label="parseInt(dict.value)" + > {{ dict.label }} @@ -22,16 +23,16 @@ diff --git a/yudao-ui-admin/src/views/pay/app/index.vue b/yudao-ui-admin/src/views/pay/app/index.vue index 67a15fe66..6819af711 100644 --- a/yudao-ui-admin/src/views/pay/app/index.vue +++ b/yudao-ui-admin/src/views/pay/app/index.vue @@ -170,6 +170,19 @@ + + + + + @@ -228,14 +241,14 @@ import { createApp, updateApp, changeAppStatus, deleteApp, getApp, getAppPage } import { PayChannelEnum, CommonStatusEnum } from "@/utils/constants"; import weixinChannelForm from "@/views/pay/app/components/weixinChannelForm"; import alipayChannelForm from "@/views/pay/app/components/alipayChannelForm"; -import mockChannelForm from '@/views/pay/app/components/mockChannelForm'; +import noneConfigChannelForm from '@/views/pay/app/components/noneConfigChannelForm'; export default { name: "PayApp", components: { weixinChannelForm, alipayChannelForm, - mockChannelForm + noneConfigChannelForm }, data() { return { @@ -391,7 +404,11 @@ export default { return } if (code === 'mock') { - this.$refs['mockChannelFormRef'].open(row.id, code); + this.$refs['noneConfigChannelFormRef'].open(row.id, code); + return + } + if (code === 'wallet') { + this.$refs['noneConfigChannelFormRef'].open(row.id, code); return } }, diff --git a/yudao-ui-admin/src/views/pay/cashier/index.vue b/yudao-ui-admin/src/views/pay/cashier/index.vue index 85d702760..c10c154aa 100644 --- a/yudao-ui-admin/src/views/pay/cashier/index.vue +++ b/yudao-ui-admin/src/views/pay/cashier/index.vue @@ -136,6 +136,10 @@ export default { name: '模拟支付', icon: require("@/assets/images/pay/icon/mock.svg"), code: "mock" + }, { + name: '钱包支付', + icon: require("@/assets/images/pay/icon/mock.svg"), + code: "wallet" }], submitLoading: false, // 提交支付的 loading interval: undefined, // 定时任务,轮询是否完成支付 From 2591ab5d36a19ece7b3acff1574410af80c4e3cd Mon Sep 17 00:00:00 2001 From: puhui999 Date: Wed, 6 Sep 2023 11:29:51 +0800 Subject: [PATCH 22/50] =?UTF-8?q?=E8=AE=A2=E5=8D=95=E4=B8=AD=E5=BF=83+?= =?UTF-8?q?=E8=90=A5=E9=94=80=E6=B4=BB=E5=8A=A8=EF=BC=9A=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E9=83=A8=E5=88=86=20TODO=20=E6=8F=90=E5=88=B0=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/common/pojo/CommonResult.java | 10 ++++- .../dto/BargainRecordCreateReqDTO.java | 25 +----------- .../api/combination/CombinationRecordApi.java | 26 ++++++++++--- .../CombinationRecordUpdateStatusReqDTO.java | 39 ------------------- .../promotion/enums/ErrorCodeConstants.java | 2 +- .../combination/CombinationRecordApiImpl.java | 21 ++++++---- .../combination/CombinationRecordDO.java | 6 +-- .../combination/CombinationRecordService.java | 15 ++++--- .../CombinationRecordServiceImpl.java | 21 +++++----- .../seckill/SeckillActivityServiceImpl.java | 12 ++---- .../module/promotion/util/PromotionUtils.java | 26 ------------- .../aftersale/TradeAfterSaleController.java | 10 ++++- .../vo/TradeAfterSaleDetailRespVO.java | 2 +- .../order/vo/TradeOrderDetailRespVO.java | 17 ++++---- .../aftersale/TradeAfterSaleConvert.java | 2 +- .../convert/order/TradeOrderConvert.java | 4 +- .../aftersale/TradeAfterSaleServiceImpl.java | 7 +--- .../order/TradeOrderUpdateServiceImpl.java | 4 +- 18 files changed, 97 insertions(+), 152 deletions(-) delete mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordUpdateStatusReqDTO.java diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/CommonResult.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/CommonResult.java index bfb291b6d..3a974456e 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/CommonResult.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/CommonResult.java @@ -41,7 +41,7 @@ public class CommonResult implements Serializable { * 因为 A 方法返回的 CommonResult 对象,不满足调用其的 B 方法的返回,所以需要进行转换。 * * @param result 传入的 result 对象 - * @param 返回的泛型 + * @param 返回的泛型 * @return 新的 CommonResult 对象 */ public static CommonResult error(CommonResult result) { @@ -68,6 +68,14 @@ public class CommonResult implements Serializable { return result; } + public static CommonResult success(T data, String msg) { + CommonResult result = new CommonResult<>(); + result.code = GlobalErrorCodeConstants.SUCCESS.getCode(); + result.data = data; + result.msg = msg; + return result; + } + public static boolean isSuccess(Integer code) { return Objects.equals(code, GlobalErrorCodeConstants.SUCCESS.getCode()); } diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/dto/BargainRecordCreateReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/dto/BargainRecordCreateReqDTO.java index 22ef80a1e..d7835b23c 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/dto/BargainRecordCreateReqDTO.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/dto/BargainRecordCreateReqDTO.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.promotion.api.bargain.dto; import lombok.Data; -import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; // TODO @芋艿:这块要在看看 @@ -40,17 +39,7 @@ public class BargainRecordCreateReqDTO { */ @NotNull(message = "订单编号不能为空") private Long orderId; - // TODO @puhui999:spuName、picUrl、 之类字段不用传递; - /** - * 商品名字 - */ - @NotEmpty(message = "商品名字不能为空") - private String spuName; - /** - * 商品图片 - */ - @NotEmpty(message = "商品图片不能为空") - private String picUrl; + /** * 砍价商品单价 */ @@ -61,17 +50,7 @@ public class BargainRecordCreateReqDTO { */ @NotNull(message = "商品原价不能为空") private Integer price; - // TODO @puhui999:nickname、avatar 不用传递,去查询; - /** - * 用户昵称 - */ - @NotEmpty(message = "用户昵称不能为空") - private String nickname; - /** - * 用户头像 - */ - @NotEmpty(message = "用户头像不能为空") - private String avatar; + /** * 开团状态:进行中 砍价成功 砍价失败 */ diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java index 631a70906..c03559785 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java @@ -2,9 +2,9 @@ package cn.iocoder.yudao.module.promotion.api.combination; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO; -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO; import javax.validation.Valid; +import java.time.LocalDateTime; import java.util.List; // TODO @芋艿:后面也再撸撸这几个接口 @@ -51,13 +51,29 @@ public interface CombinationRecordApi { */ void validateCombinationLimitCount(Long activityId, Integer count, Integer sumCount); - // TODO @puhui999:是不是搞成具体的方法,拼团成功,拼团失败,这种方法; + /** + * 更新拼团状态为 成功 + * + * @param userId 用户编号 + * @param orderId 订单编号 + */ + void updateRecordStatusToSuccess(Long userId, Long orderId); /** - * 更新开团记录状态 + * 更新拼团状态为 失败 * - * @param reqDTO 请求 DTO + * @param userId 用户编号 + * @param orderId 订单编号 */ - void updateCombinationRecordStatus(CombinationRecordUpdateStatusReqDTO reqDTO); + void updateRecordStatusToFailed(Long userId, Long orderId); + + /** + * 更新拼团状态为 进行中 + * + * @param userId 用户编号 + * @param orderId 订单编号 + * @param startTime 开始时间 + */ + void updateRecordStatusToInProgress(Long userId, Long orderId, LocalDateTime startTime); } diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordUpdateStatusReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordUpdateStatusReqDTO.java deleted file mode 100644 index 3ba49ff36..000000000 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordUpdateStatusReqDTO.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.iocoder.yudao.module.promotion.api.combination.dto; - -import lombok.Data; - -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; - -/** - * 拼团记录的更新状态 Request DTO - * - * @author HUIHUI - */ -@Data -public class CombinationRecordUpdateStatusReqDTO { - - /** - * 用户编号 - */ - @NotNull(message = "用户编号不能为空") - private Long userId; - - /** - * 订单编号 - */ - @NotNull(message = "订单编号不能为空") - private Long orderId; - - /** - * 开团状态:正在开团 拼团成功 拼团失败 - */ - @NotNull(message = "开团状态不能为空") - private Integer status; - - /** - * 团开始时间 - */ - private LocalDateTime startTime; - -} diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java index 8f5b8c803..dd4389d5d 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java @@ -51,7 +51,7 @@ public interface ErrorCodeConstants { // ========== 秒杀活动 1013008000 ========== ErrorCode SECKILL_ACTIVITY_NOT_EXISTS = new ErrorCode(1013008000, "秒杀活动不存在"); - ErrorCode SECKILL_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013008002, "存在商品参加了其它秒杀活动"); + ErrorCode SECKILL_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013008002, "存在商品参加了其它秒杀活动,秒杀时段冲突"); ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013008003, "秒杀活动已关闭,不能修改"); ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013008004, "秒杀活动未关闭或未结束,不能删除"); ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭"); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java index e9dd9d201..7f7ec6170 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java @@ -2,13 +2,13 @@ package cn.iocoder.yudao.module.promotion.api.combination; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO; -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO; import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService; import org.springframework.stereotype.Service; import javax.annotation.Resource; +import java.time.LocalDateTime; import java.util.List; /** @@ -43,12 +43,19 @@ public class CombinationRecordApiImpl implements CombinationRecordApi { } @Override - public void updateCombinationRecordStatus(CombinationRecordUpdateStatusReqDTO reqDTO) { - if (null == reqDTO.getStartTime()) { - recordService.updateCombinationRecordStatusByUserIdAndOrderId(reqDTO); - } else { - recordService.updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(reqDTO); - } + public void updateRecordStatusToSuccess(Long userId, Long orderId) { + recordService.updateCombinationRecordStatusByUserIdAndOrderId(CombinationRecordStatusEnum.SUCCESS.getStatus(), userId, orderId); + } + + @Override + public void updateRecordStatusToFailed(Long userId, Long orderId) { + recordService.updateCombinationRecordStatusByUserIdAndOrderId(CombinationRecordStatusEnum.FAILED.getStatus(), userId, orderId); + } + + @Override + public void updateRecordStatusToInProgress(Long userId, Long orderId, LocalDateTime startTime) { + recordService.updateRecordStatusAndStartTimeByUserIdAndOrderId(CombinationRecordStatusEnum.IN_PROGRESS.getStatus(), + userId, orderId, startTime); } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationRecordDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationRecordDO.java index f89c8f7ee..898d2a822 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationRecordDO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationRecordDO.java @@ -86,11 +86,11 @@ public class CombinationRecordDO extends BaseDO { */ private Boolean virtualGroup; /** - * 过期时间,单位:小时 + * 过期时间 * - * 关联 {@link CombinationActivityDO#getLimitDuration()} + * {@link CombinationRecordDO#getStartTime()} + {@link CombinationActivityDO#getLimitDuration()} 计算 */ - private Integer expireTime; + private LocalDateTime expireTime; /** * 开始时间 (订单付款后开始的时间) */ diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java index 6c12cb551..fbc51c6b9 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.promotion.service.combination; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO; import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; +import java.time.LocalDateTime; import java.util.List; /** @@ -16,9 +16,11 @@ public interface CombinationRecordService { /** * 更新拼团状态 * - * @param reqDTO 请求 DTO + * @param status 状态 + * @param userId 用户编号 + * @param orderId 订单编号 */ - void updateCombinationRecordStatusByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO); + void updateCombinationRecordStatusByUserIdAndOrderId(Integer status, Long userId, Long orderId); /** * 创建拼团记录 @@ -30,9 +32,12 @@ public interface CombinationRecordService { /** * 更新拼团状态和开始时间 * - * @param reqDTO 请求 DTO + * @param status 状态 + * @param userId 用户编号 + * @param orderId 订单编号 + * @param startTime 开始时间 */ - void updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO); + void updateRecordStatusAndStartTimeByUserIdAndOrderId(Integer status, Long userId, Long orderId, LocalDateTime startTime); /** * 获得拼团状态 diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java index 4e2f85e27..bc9c1df4c 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.promotion.service.combination; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO; import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; @@ -21,6 +20,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; // TODO 芋艿:等拼团记录做完,完整 review 下 + /** * 拼团记录 Service 实现类 * @@ -38,27 +38,27 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { @Override @Transactional(rollbackFor = Exception.class) - public void updateCombinationRecordStatusByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO) { + public void updateCombinationRecordStatusByUserIdAndOrderId(Integer status, Long userId, Long orderId) { // 校验拼团是否存在 - CombinationRecordDO recordDO = validateCombinationRecord(reqDTO.getUserId(), reqDTO.getOrderId()); + CombinationRecordDO recordDO = validateCombinationRecord(userId, orderId); // 更新状态 - recordDO.setStatus(reqDTO.getStatus()); + recordDO.setStatus(status); recordMapper.updateById(recordDO); } @Override @Transactional(rollbackFor = Exception.class) - public void updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO) { - CombinationRecordDO recordDO = validateCombinationRecord(reqDTO.getUserId(), reqDTO.getOrderId()); + public void updateRecordStatusAndStartTimeByUserIdAndOrderId(Integer status, Long userId, Long orderId, LocalDateTime startTime) { + CombinationRecordDO recordDO = validateCombinationRecord(userId, orderId); // 更新状态 - recordDO.setStatus(reqDTO.getStatus()); + recordDO.setStatus(status); // 更新开始时间 - recordDO.setStartTime(reqDTO.getStartTime()); + recordDO.setStartTime(startTime); recordMapper.updateById(recordDO); // 更新拼团参入人数 - List recordDOs = recordMapper.selectListByHeadIdAndStatus(recordDO.getHeadId(), reqDTO.getStatus()); + List recordDOs = recordMapper.selectListByHeadIdAndStatus(recordDO.getHeadId(), status); if (CollUtil.isNotEmpty(recordDOs)) { recordDOs.forEach(item -> { item.setUserCount(recordDOs.size()); @@ -115,8 +115,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { // 2. 创建拼团记录 CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO); record.setVirtualGroup(false); - // TODO @puhui999:过期时间,应该是 Date 哈; - record.setExpireTime(activity.getLimitDuration()); + record.setExpireTime(record.getStartTime().plusHours(activity.getLimitDuration())); record.setUserSize(activity.getUserSize()); recordMapper.insert(record); } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java index a3577a50b..531c35fcb 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java @@ -92,15 +92,9 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { if (activityId != null) { // 排除自己 activityList.removeIf(item -> ObjectUtil.equal(item.getId(), activityId)); } - // TODO @puhui999:一个 spu,参与两个活动应该没关系,关键是活动时间不充能重叠; - // 2.2 过滤出所有 spuId 有交集的活动,判断是否存在重叠 - List activityDOs1 = filterList(activityList, s -> ObjectUtil.equal(s.getSpuId(), spuId)); - if (isNotEmpty(activityDOs1)) { - throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS); - } - // 2.3 过滤出所有 configIds 有交集的活动,判断是否存在重叠 - List activityDOs2 = filterList(activityList, s -> containsAny(s.getConfigIds(), configIds)); - if (isNotEmpty(activityDOs2)) { + // 2.2 过滤出所有 configIds 有交集的活动,判断是否存在重叠 + List activityDOs = filterList(activityList, s -> containsAny(s.getConfigIds(), configIds)); + if (isNotEmpty(activityDOs)) { throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS); } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/util/PromotionUtils.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/util/PromotionUtils.java index dd5551fe2..2ad362fe2 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/util/PromotionUtils.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/util/PromotionUtils.java @@ -1,18 +1,9 @@ package cn.iocoder.yudao.module.promotion.util; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; import java.time.LocalDateTime; -import java.util.List; -import java.util.Set; -import java.util.function.Function; - -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.anyMatch; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; /** * 活动工具类 @@ -31,21 +22,4 @@ public class PromotionUtils { return LocalDateTimeUtils.beforeNow(endTime) ? CommonStatusEnum.DISABLE.getStatus() : CommonStatusEnum.ENABLE.getStatus(); } - /** - * 校验商品 sku 是否都存在 - * - * @param skus 数据库中的商品 skus - * @param products 需要校验的商品 - * @param func 获取需要校验的商品的 skuId - */ - public static void validateProductSkuAllExists(List skus, List products, Function func) { - // 校验 sku 个数是否一致 - Set skuIdsSet = CollectionUtils.convertSet(products, func); - Set skuIdsSet1 = CollectionUtils.convertSet(skus, ProductSkuRespDTO::getId); - // 校验 skuId 是否存在 - if (anyMatch(skuIdsSet, s -> !skuIdsSet1.contains(s))) { - throw exception(SKU_NOT_EXISTS); - } - } - } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java index 689f3540b..60afbc0ab 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java @@ -36,6 +36,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.AFTER_SALE_NOT_FOUND; @Tag(name = "管理后台 - 售后订单") @RestController @@ -76,6 +77,9 @@ public class TradeAfterSaleController { public CommonResult getOrderDetail(@RequestParam("id") Long id) { // 查询订单 TradeAfterSaleDO afterSale = afterSaleService.getAfterSale(id); + if (afterSale == null) { + return success(null, AFTER_SALE_NOT_FOUND.getMsg()); + } // 查询订单 TradeOrderDO order = tradeOrderQueryService.getOrder(afterSale.getOrderId()); // 查询订单项 @@ -92,7 +96,11 @@ public class TradeAfterSaleController { TradeAfterSaleLogRespDTO respVO = new TradeAfterSaleLogRespDTO(); respVO.setId((long) i); respVO.setUserId((long) i); - respVO.setUserType(1); + respVO.setUserType(i % 2 == 0 ? 2 : 1); + // 模拟系统操作 + if (i == 2) { + respVO.setUserType(3); + } respVO.setAfterSaleId(id); respVO.setOrderId((long) i); respVO.setOrderItemId((long) i); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleDetailRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleDetailRespVO.java index aff9f5087..af6db85c7 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleDetailRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleDetailRespVO.java @@ -35,7 +35,7 @@ public class TradeAfterSaleDetailRespVO extends TradeAfterSaleBaseVO { /** * 售后日志 */ - private List afterSaleLog; + private List logs; @Schema(description = "管理后台 - 交易订单的详情的订单项目") @Data diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderDetailRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderDetailRespVO.java index fa1e77d0e..4ba8ed4f8 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderDetailRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderDetailRespVO.java @@ -26,24 +26,23 @@ public class TradeOrderDetailRespVO extends TradeOrderBaseVO { private MemberUserRespVO user; /** - * TODO 订单操作日志, 先模拟一波;返回 logs,简洁,然后复数哈 + * TODO 订单操作日志, 先模拟一波 */ - private List orderLog; + private List logs; - // TODO @puhui999:swagger 注解 + @Schema(description = "管理后台 - 交易订单的操作日志") @Data public static class OrderLog { - /** - * 内容 - */ + @Schema(description = "操作详情", requiredMode = Schema.RequiredMode.REQUIRED, example = "订单发货") private String content; - /** - * 创建时间 - */ + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-06-01 10:50:20") private LocalDateTime createTime; + @Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer userType; + } @Schema(description = "管理后台 - 交易订单的详情的订单项目") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/TradeAfterSaleConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/TradeAfterSaleConvert.java index d4f481c37..0c84c6967 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/TradeAfterSaleConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/TradeAfterSaleConvert.java @@ -78,7 +78,7 @@ public interface TradeAfterSaleConvert { // 处理订单信息 respVO.setOrder(convert(order)); // 处理售后日志 - respVO.setAfterSaleLog(convertList1(logs)); + respVO.setLogs(convertList1(logs)); return respVO; } List convertList1(List list); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java index df7b296f0..07e9595fc 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java @@ -93,6 +93,7 @@ public interface TradeOrderConvert { items.forEach(item -> item.setIncrCount(-item.getIncrCount())); return new ProductSkuUpdateStockReqDTO(items); } + List convertList(List list); @Mappings({ @@ -151,9 +152,10 @@ public interface TradeOrderConvert { TradeOrderDetailRespVO.OrderLog orderLog = new TradeOrderDetailRespVO.OrderLog(); orderLog.setContent("订单操作" + i); orderLog.setCreateTime(LocalDateTime.now()); + orderLog.setUserType(i % 2 == 0 ? 2 : 1); orderLogs.add(orderLog); } - orderVO.setOrderLog(orderLogs); + orderVO.setLogs(orderLogs); return orderVO; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java index eae983799..f54563d42 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java @@ -90,12 +90,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa @Override public TradeAfterSaleDO getAfterSale(Long id) { - TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectById(id); - // TODO @puhui999;读不到,不要这里报错哈;交给前端报错;一般是读取信息不到,message 提示,然后 close tab; - if (afterSale == null) { - throw exception(AFTER_SALE_NOT_FOUND); - } - return afterSale; + return tradeAfterSaleMapper.selectById(id); } // TODO 芋艿:拼团失败,要不要发起售后的方式退款?还是走取消逻辑? diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index f887b71e8..c4cfaee83 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -28,7 +28,6 @@ import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; import cn.iocoder.yudao.module.promotion.api.bargain.BargainRecordApi; import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO; -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO; import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; @@ -352,8 +351,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { // 1、拼团活动 if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { // 更新拼团状态 TODO puhui999:订单支付失败或订单支付过期删除这条拼团记录 - combinationRecordApi.updateCombinationRecordStatus(new CombinationRecordUpdateStatusReqDTO().setUserId(order.getUserId()) - .setOrderId(order.getId()).setStatus(CombinationRecordStatusEnum.IN_PROGRESS.getStatus()).setStartTime(LocalDateTime.now())); + combinationRecordApi.updateRecordStatusToInProgress(order.getUserId(), order.getId(), LocalDateTime.now()); } // TODO 芋艿:发送订单变化的消息 From 62a4e8242b924381501ced897e098d0789d81696 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 6 Sep 2023 23:50:23 +0800 Subject: [PATCH 23/50] =?UTF-8?q?=E5=88=86=E9=94=80=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E6=8F=90=E7=8E=B0=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../brokerage/AppBrokerageUserController.java | 11 ++++++ .../AppBrokerageWithdrawController.java | 14 +++++-- .../vo/user/AppBrokerageUserRespVO.java | 16 ++++++++ .../AppBrokerageWithdrawCreateReqVO.java | 29 +++++++++++++++ .../app/config/AppTradeConfigController.java | 37 +++++++++++++++++++ .../app/config/vo/AppTradeConfigRespVO.java | 21 +++++++++++ .../vo/config/AppDeliveryConfigRespVO.java | 2 +- 7 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRespVO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/config/AppTradeConfigController.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/config/vo/AppTradeConfigRespVO.java diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java index 31de03ea1..1b760be05 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java @@ -28,6 +28,17 @@ import static java.util.Arrays.asList; @Slf4j public class AppBrokerageUserController { + // TODO 芋艿:临时 mock => + @GetMapping("/get") + @Operation(summary = "获得个人分销信息") + @PreAuthenticated + public CommonResult getBrokerageUser() { + AppBrokerageUserRespVO respVO = new AppBrokerageUserRespVO() + .setBrokeragePrice(2000) + .setFrozenBrokeragePrice(3000); + return success(respVO); + } + // TODO 芋艿:临时 mock => @GetMapping("/get-summary") @Operation(summary = "获得个人分销统计") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageWithdrawController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageWithdrawController.java index 1f69b3593..1f6d383ea 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageWithdrawController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageWithdrawController.java @@ -3,15 +3,15 @@ package cn.iocoder.yudao.module.trade.controller.app.brokerage; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; +import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawCreateReqVO; import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawRespVO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; +import javax.validation.Valid; import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -36,4 +36,12 @@ public class AppBrokerageWithdrawController { return success(new PageResult<>(asList(vo1, vo2), 10L)); } + // TODO 芋艿:临时 mock => + @PostMapping("/create") + @Operation(summary = "创建分销提现") + @PreAuthenticated + public CommonResult createBrokerageWithdraw(@RequestBody @Valid AppBrokerageWithdrawCreateReqVO createReqVO) { + return success(1L); + } + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRespVO.java new file mode 100644 index 000000000..04f1a7278 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRespVO.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "用户 App - 分销用户信息 Response VO") +@Data +public class AppBrokerageUserRespVO { + + @Schema(description = "可用的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2408") + private Integer brokeragePrice; + + @Schema(description = "冻结的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "234") + private Integer frozenBrokeragePrice; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java new file mode 100644 index 000000000..75aec997b --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.hibernate.validator.constraints.URL; + +import javax.validation.constraints.Min; + +@Schema(description = "用户 App - 分销提现创建 Request VO") +@Data +public class AppBrokerageWithdrawCreateReqVO { + + // TODO @疯狂:参数校验逻辑,需要根据 type 进行不同的校验;感觉可以通过分组? + + @Schema(description = "提现方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer type; + + @Schema(description = "提现账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456789") // 银行卡号/微信账号/支付宝账号 + private String accountNo; + + @Schema(description = "收款码的图片", example = "https://www.iocoder.cn/1.png") + @URL(message = "收款码的图片,必须是一个 URL") + private String accountQrCodeUrl; + + @Schema(description = "提现金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") + @Min(value = 1, message = "提现金额必须大于 1") + private Integer price; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/config/AppTradeConfigController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/config/AppTradeConfigController.java new file mode 100644 index 000000000..65c879a02 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/config/AppTradeConfigController.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.trade.controller.app.config; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.trade.controller.app.config.vo.AppTradeConfigRespVO; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static java.util.Arrays.asList; + +@Tag(name = "用户 App - 交易配置") +@RestController +@RequestMapping("/trade/config") +@RequiredArgsConstructor +@Validated +@Slf4j +public class AppTradeConfigController { + + @GetMapping("/get") + public CommonResult getTradeConfig() { + AppTradeConfigRespVO respVO = new AppTradeConfigRespVO(); + respVO.setBrokeragePosterUrls(asList( + "https://api.java.crmeb.net/crmebimage/product/2020/08/03/755bf516b1ca4b6db3bfeaa4dd5901cdh71kob20re.jpg", + "https://api.java.crmeb.net/crmebimage/maintain/2021/03/01/406d729b84ed4ec9a2171bfcf6fd0634ughzbz9kfi.jpg", + "https://api.java.crmeb.net/crmebimage/maintain/2021/03/01/efb1e4e7fe604fe1988b4213ce08cb11tdsyijtd2r.jpg" + )); + respVO.setBrokerageFrozenDays(10); + respVO.setBrokerageWithdrawMinPrice(100); + return success(respVO); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/config/vo/AppTradeConfigRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/config/vo/AppTradeConfigRespVO.java new file mode 100644 index 000000000..73abf7ab4 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/config/vo/AppTradeConfigRespVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.trade.controller.app.config.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +@Schema(description = "用户 App - 交易配置 Response VO") +@Data +public class AppTradeConfigRespVO { + + @Schema(description = "分销海报地址数组", requiredMode = Schema.RequiredMode.REQUIRED) + private List brokeragePosterUrls; + + @Schema(description = "佣金冻结时间(天)", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Integer brokerageFrozenDays; + + @Schema(description = "佣金提现最小金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Integer brokerageWithdrawMinPrice; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/delivery/vo/config/AppDeliveryConfigRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/delivery/vo/config/AppDeliveryConfigRespVO.java index 44b1326c1..744ae97c8 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/delivery/vo/config/AppDeliveryConfigRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/delivery/vo/config/AppDeliveryConfigRespVO.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.trade.controller.app.delivery.vo.config; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -// TODO 芋艿:后续要实现下,配送配置 +// TODO 芋艿:后续要实现下,配送配置;后续融合到 AppTradeConfigRespVO 中 @Schema(description = "用户 App - 配送配置 Response VO") @Data public class AppDeliveryConfigRespVO { From b8a4d8cab2869e7e4d58b267c101f92c92dde319 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 7 Sep 2023 12:29:50 +0800 Subject: [PATCH 24/50] =?UTF-8?q?=E5=88=86=E9=94=80=EF=BC=9A=E9=81=BF?= =?UTF-8?q?=E5=85=8D=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/member/dal/dataobject/user/MemberUserDO.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java index 8e6c99aac..cfa93c983 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java @@ -141,26 +141,32 @@ public class MemberUserDO extends TenantBaseDO { /** * 推广员编号 */ + @TableField(exist = false) // TODO 芋艿:避免报错 private Long brokerageUserId; /** * 推广员绑定时间 */ + @TableField(exist = false) // TODO 芋艿:避免报错 private LocalDateTime brokerageBindTime; /** * 是否成为推广员 */ + @TableField(exist = false) // TODO 芋艿:避免报错 private Boolean brokerageEnabled; /** * 成为分销员时间 */ + @TableField(exist = false) // TODO 芋艿:避免报错 private LocalDateTime brokerageTime; /** * 可用佣金 */ + @TableField(exist = false) // TODO 芋艿:避免报错 private Integer brokeragePrice; /** * 冻结佣金 */ + @TableField(exist = false) // TODO 芋艿:避免报错 private Integer frozenBrokeragePrice; } From 5808f77ade3c0843c4119ea7e1744c2b638a6f81 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 8 Sep 2023 00:29:25 +0800 Subject: [PATCH 25/50] =?UTF-8?q?code=20review=EF=BC=9A=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E5=88=86=E4=BD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-dependencies/pom.xml | 4 +- .../mybatis/core/mapper/BaseMapperX.java | 8 ++- .../api/sku/dto/ProductSkuRespDTO.java | 1 + .../trade/enums/ErrorCodeConstants.java | 14 +++--- .../brokerage/BrokerageBindModeEnum.java | 2 + .../BrokerageEnabledConditionEnum.java | 1 + .../brokerage/BrokerageRecordBizTypeEnum.java | 1 + .../record/vo/TradeBrokerageRecordBaseVO.java | 5 +- ...kerageUserUpdateBrokerageEnabledReqVO.java | 2 + .../admin/config/vo/TradeConfigBaseVO.java | 1 + .../record/TradeBrokerageRecordConvert.java | 2 +- .../record/TradeBrokerageRecordDO.java | 16 +++--- .../brokerage/user/TradeBrokerageUserDO.java | 7 +++ .../record/TradeBrokerageRecordMapper.java | 2 + .../yudao/module/trade/job/package-info.java | 4 ++ .../record/TradeBrokerageRecordService.java | 4 ++ .../TradeBrokerageRecordServiceImpl.java | 49 ++++++++++--------- .../record/bo/BrokerageAddReqBO.java | 8 +++ .../user/TradeBrokerageUserService.java | 3 ++ .../user/TradeBrokerageUserServiceImpl.java | 20 +++++--- .../service/config/TradeConfigService.java | 1 - .../TradeBrokerageRecordServiceImplTest.java | 1 + .../TradeBrokerageUserServiceImplTest.java | 1 + .../member/enums/ErrorCodeConstants.java | 2 +- .../dal/dataobject/user/MemberUserDO.java | 1 + .../dal/mysql/user/MemberUserMapper.java | 1 + 26 files changed, 108 insertions(+), 53 deletions(-) create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/package-info.java diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index f3273f02a..849be7b87 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -27,7 +27,7 @@ 3.5.3.2 3.5.3.2 3.6.1 - 1.4.5 + 1.4.6 3.18.0 8.1.2.141 @@ -220,7 +220,7 @@ com.github.yulichang mybatis-plus-join-boot-starter - ${mybatis-plus-join-boot-starter.version} + ${mybatis-plus-join.version} diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java index eebe42d11..3383ec879 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java @@ -11,6 +11,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.baomidou.mybatisplus.extension.toolkit.Db; +import com.github.yulichang.base.MPJBaseMapper; import org.apache.ibatis.annotations.Param; import java.util.Collection; @@ -18,8 +19,11 @@ import java.util.List; /** * 在 MyBatis Plus 的 BaseMapper 的基础上拓展,提供更多的能力 + * + * 1. {@link BaseMapper} 为 MyBatis Plus 的基础接口,提供基础的 CRUD 能力 + * 2. {@link MPJBaseMapper} 为 MyBatis Plus Join 的基础接口,提供连表 Join 能力 */ -public interface BaseMapperX extends BaseMapper { +public interface BaseMapperX extends MPJBaseMapper { default PageResult selectPage(PageParam pageParam, @Param("ew") Wrapper queryWrapper) { // MyBatis Plus 查询 @@ -128,4 +132,4 @@ public interface BaseMapperX extends BaseMapper { Db.saveOrUpdateBatch(collection); } -} \ No newline at end of file +} diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java index 2899fc075..c412faf4e 100644 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java +++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java @@ -60,6 +60,7 @@ public class ProductSkuRespDTO { */ private Double volume; + // TODO @puhui:这 2 字段,需要改下;firstBrokerageRecord、secondBrokerageRecord;和分佣保持一致; /** * 一级分销的佣金,单位:分 */ diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java index 3107dbedf..f6c0ca782 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java @@ -11,7 +11,7 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; */ public interface ErrorCodeConstants { - // ========== Order 模块 1011000000 ========== + // ========== Order 模块 1011000000 ========== ErrorCode ORDER_CREATE_SKU_NOT_FOUND = new ErrorCode(1011000001, "商品 SKU 不存在"); ErrorCode ORDER_CREATE_SPU_NOT_SALE = new ErrorCode(1011000002, "商品 SPU 不可售卖"); ErrorCode ORDER_CREATE_SKU_STOCK_NOT_ENOUGH = new ErrorCode(1011000004, "商品 SKU 库存不足"); @@ -35,7 +35,7 @@ public interface ErrorCodeConstants { ErrorCode ORDER_DELIVERY_FAIL_DELIVERY_TYPE_NOT_EXPRESS = new ErrorCode(1011000024, "交易订单发货失败,发货类型不是快递"); ErrorCode ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID = new ErrorCode(1011000025, "交易订单取消失败,订单不是【待支付】状态"); - // ========== After Sale 模块 1011000100 ========== + // ========== After Sale 模块 1011000100 ========== ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1011000100, "售后单不存在"); ErrorCode AFTER_SALE_CREATE_FAIL_REFUND_PRICE_ERROR = new ErrorCode(1011000101, "申请退款金额错误"); ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_CANCELED = new ErrorCode(1011000102, "订单已关闭,无法申请售后"); @@ -50,7 +50,7 @@ public interface ErrorCodeConstants { ErrorCode AFTER_SALE_CANCEL_FAIL_STATUS_NOT_APPLY_OR_AGREE_OR_BUYER_DELIVERY = new ErrorCode(1011000111, "取消售后单失败,售后单状态不是【待审核】或【卖家同意】或【商家待收货】"); - // ========== Cart 模块 1011002000 ========== + // ========== Cart 模块 1011002000 ========== ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1011002000, "购物车项不存在"); // ========== Price 相关 1011003000 ============ @@ -58,7 +58,7 @@ public interface ErrorCodeConstants { ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_USER_ADDR_IS_EMPTY = new ErrorCode(1011003001, "计算快递运费异常,收件人地址编号为空"); ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND = new ErrorCode(1011003002, "计算快递运费异常,找不到对应的运费模板"); - // ========== 物流 Express 模块 1011004000 ========== + // ========== 物流 Express 模块 1011004000 ========== ErrorCode EXPRESS_NOT_EXISTS = new ErrorCode(1011004000, "快递公司不存在"); ErrorCode EXPRESS_CODE_DUPLICATE = new ErrorCode(1011004001, "已经存在该编码的快递公司"); ErrorCode EXPRESS_CLIENT_NOT_PROVIDE = new ErrorCode(1011004002, "需要接入快递服务商,比如【快递100】"); @@ -67,15 +67,15 @@ public interface ErrorCodeConstants { ErrorCode EXPRESS_API_QUERY_ERROR = new ErrorCode(1011004101, "快递查询接口异常"); ErrorCode EXPRESS_API_QUERY_FAILED = new ErrorCode(1011004102, "快递查询返回失败,原因:{}"); - // ========== 物流 Template 模块 1011005000 ========== + // ========== 物流 Template 模块 1011005000 ========== ErrorCode EXPRESS_TEMPLATE_NAME_DUPLICATE = new ErrorCode(1011005000, "已经存在该运费模板名"); ErrorCode EXPRESS_TEMPLATE_NOT_EXISTS = new ErrorCode(1011005001, "运费模板不存在"); - // ========== 物流 PICK_UP 模块 1011006000 ========== + // ========== 物流 PICK_UP 模块 1011006000 ========== ErrorCode PICK_UP_STORE_NOT_EXISTS = new ErrorCode(1011006000, "自提门店不存在"); - // ========== 分销 分销用户 模块 1011007000 ========== + // ========== 分销用户 模块 1011007000 ========== ErrorCode BROKERAGE_USER_NOT_EXISTS = new ErrorCode(1011007000, "分销用户不存在"); } diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageBindModeEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageBindModeEnum.java index 6946167bc..19bb53daa 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageBindModeEnum.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageBindModeEnum.java @@ -15,6 +15,7 @@ import java.util.Arrays; @Getter public enum BrokerageBindModeEnum implements IntArrayValuable { + // TODO @疯狂:要不从 1 开始? /** * 只要用户没有推广人,随时都可以绑定分销关系 */ @@ -23,6 +24,7 @@ public enum BrokerageBindModeEnum implements IntArrayValuable { * 仅新用户注册时才能绑定推广关系 */ REGISTER(1, "新用户"), + // TODO @疯狂:要加个 2,每次扫码都覆盖 ; public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageBindModeEnum::getMode).toArray(); diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageEnabledConditionEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageEnabledConditionEnum.java index 6d984a284..1d1ef0c81 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageEnabledConditionEnum.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageEnabledConditionEnum.java @@ -15,6 +15,7 @@ import java.util.Arrays; @Getter public enum BrokerageEnabledConditionEnum implements IntArrayValuable { + // TODO @疯狂:这个也从 1 开始哇 /** * 所有用户都可以分销 */ diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageRecordBizTypeEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageRecordBizTypeEnum.java index ce449f0b8..50c83c05a 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageRecordBizTypeEnum.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageRecordBizTypeEnum.java @@ -15,6 +15,7 @@ import java.util.Arrays; @Getter public enum BrokerageRecordBizTypeEnum implements IntArrayValuable { + // TODO @疯狂:这个也从 1 开始哇 ORDER(0, "获得推广佣金", "获得推广佣金 {}", true), WITHDRAW(1, "提现申请", "提现申请扣除佣金 {}", false), ; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordBaseVO.java index 1fb87f294..f15d07706 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordBaseVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordBaseVO.java @@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; +import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.time.LocalDateTime; @@ -21,7 +22,7 @@ public class TradeBrokerageRecordBaseVO { private Long userId; @Schema(description = "业务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23353") - @NotNull(message = "业务编号不能为空") + @NotEmpty(message = "业务编号不能为空") private String bizId; @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @@ -29,7 +30,7 @@ public class TradeBrokerageRecordBaseVO { private Integer bizType; @Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "标题不能为空") + @NotEmpty(message = "标题不能为空") private String title; @Schema(description = "金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "28731") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserUpdateBrokerageEnabledReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserUpdateBrokerageEnabledReqVO.java index 002eed371..1fd38b028 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserUpdateBrokerageEnabledReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserUpdateBrokerageEnabledReqVO.java @@ -15,6 +15,8 @@ public class TradeBrokerageUserUpdateBrokerageEnabledReqVO { @NotNull(message = "用户编号不能为空") private Long id; + // TODO @疯狂:是不是这个字段,可以改成 enabled + @Schema(description = "推广资格", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "推广资格不能为空") private Boolean brokerageEnabled; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigBaseVO.java index ee20156f1..55b168582 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigBaseVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigBaseVO.java @@ -54,6 +54,7 @@ public class TradeConfigBaseVO { @PositiveOrZero(message = "用户提现最低金额不能是负数") private Integer brokerageWithdrawMinPrice; + // TODO @疯狂:要不要做成字典?按道理都可以体现对哇?感觉是全局的配置哈; @Schema(description = "提现银行", requiredMode = Schema.RequiredMode.REQUIRED, example = "[0, 1]") @NotEmpty(message = "提现银行不能为空") private List brokerageBankNames; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/TradeBrokerageRecordConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/TradeBrokerageRecordConvert.java index b84e51354..1e8290460 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/TradeBrokerageRecordConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/TradeBrokerageRecordConvert.java @@ -40,7 +40,7 @@ public interface TradeBrokerageRecordConvert { .setBizId(bizId) .setPrice(brokerage) .setTotalPrice(user.getBrokeragePrice()) - .setTitle(BrokerageRecordBizTypeEnum.ORDER.getTitle()) + .setTitle(BrokerageRecordBizTypeEnum.ORDER.getTitle()) // TODO @疯狂:可能 title 不是很固化,会存在类似:沐晴成功购买《XXX JVM 实战》 .setDescription(StrUtil.format(BrokerageRecordBizTypeEnum.ORDER.getDescription(), String.valueOf(brokerage / 100.0))) .setStatus(status) .setFrozenDays(brokerageFrozenDays) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/TradeBrokerageRecordDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/TradeBrokerageRecordDO.java index 0bf7c0cf2..bb3f09c52 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/TradeBrokerageRecordDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/TradeBrokerageRecordDO.java @@ -41,13 +41,19 @@ public class TradeBrokerageRecordDO extends BaseDO { /** * 业务类型 *

- * 枚举 {@link BrokerageRecordBizTypeEnum 对应的类} + * 枚举 {@link BrokerageRecordBizTypeEnum} */ private Integer bizType; + /** * 标题 */ private String title; + /** + * 说明 + */ + private String description; + /** * 金额 */ @@ -56,16 +62,14 @@ public class TradeBrokerageRecordDO extends BaseDO { * 当前总佣金 */ private Integer totalPrice; - /** - * 说明 - */ - private String description; + /** * 状态 *

- * 枚举 {@link BrokerageRecordStatusEnum 对应的类} + * 枚举 {@link BrokerageRecordStatusEnum} */ private Integer status; + /** * 冻结时间(天) */ diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/TradeBrokerageUserDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/TradeBrokerageUserDO.java index 0bc552dca..3f1cc73aa 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/TradeBrokerageUserDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/TradeBrokerageUserDO.java @@ -8,6 +8,7 @@ import lombok.*; import java.time.LocalDateTime; +// TODO @疯狂:因为独立了表,是不是可以把字段的 brokerage 去掉了哈? /** * 分销用户 DO * @@ -28,14 +29,19 @@ public class TradeBrokerageUserDO extends BaseDO { */ @TableId private Long id; + + // TODO @疯狂:貌似改成 bindUserId,更明确? /** * 推广员编号 + * + * 关联 MemberUserDO 的 id 字段 */ private Long brokerageUserId; /** * 推广员绑定时间 */ private LocalDateTime brokerageBindTime; + /** * 推广资格 */ @@ -44,6 +50,7 @@ public class TradeBrokerageUserDO extends BaseDO { * 成为分销员时间 */ private LocalDateTime brokerageTime; + /** * 可用佣金 */ diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/TradeBrokerageRecordMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/TradeBrokerageRecordMapper.java index 78efbc53a..41ed8bad9 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/TradeBrokerageRecordMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/TradeBrokerageRecordMapper.java @@ -40,8 +40,10 @@ public interface TradeBrokerageRecordMapper extends BaseMapperX getBrokerageRecordPage(TradeBrokerageRecordPageReqVO pageReqVO); + // TODO @疯狂:是不是 bizType 得加下?方便未来拓展哈; /** * 增加佣金 * @@ -38,8 +39,10 @@ public interface TradeBrokerageRecordService { */ void addBrokerage(Long userId, List list); + // TODO @疯狂:是不是 bizType 得加下?方便未来拓展哈; /** * 取消佣金:将佣金记录,状态修改为已失效 + * * @param userId 会员编号 * @param bizId 业务编号 */ @@ -51,4 +54,5 @@ public interface TradeBrokerageRecordService { * @return 解冻佣金的数量 */ int unfreezeRecord(); + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImpl.java index 5502bcbf7..8ced49abb 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImpl.java @@ -6,15 +6,15 @@ import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordPageReqVO; import cn.iocoder.yudao.module.trade.convert.brokerage.record.TradeBrokerageRecordConvert; import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.TradeBrokerageRecordDO; -import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.BrokerageAddReqBO; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordPageReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record.TradeBrokerageRecordMapper; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; +import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.BrokerageAddReqBO; import cn.iocoder.yudao.module.trade.service.brokerage.user.TradeBrokerageUserService; import cn.iocoder.yudao.module.trade.service.config.TradeConfigService; import lombok.extern.slf4j.Slf4j; @@ -56,11 +56,13 @@ public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordServ return tradeBrokerageRecordMapper.selectPage(pageReqVO); } + // TODO @疯狂:buyerId 要不要统一改成 userId 哈; @Override @Transactional(rollbackFor = Exception.class) public void addBrokerage(Long buyerId, List list) { TradeConfigDO memberConfig = tradeConfigService.getTradeConfig(); // 0 未启用分销功能 + // TODO @疯狂:BooleanUtil.isFalse();逻辑里,尽量不做 !取反,这样要多思考一层; if (memberConfig == null || !BooleanUtil.isTrue(memberConfig.getBrokerageEnabled())) { log.warn("[addBrokerage][增加佣金失败:brokerageEnabled 未配置,buyerId({})", buyerId); return; @@ -72,11 +74,11 @@ public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordServ return; } - // 1.2 计算一级分佣 + // 1.2 计算一级分佣 // TODO 疯狂:类似 1.1 和 1.2 的空行,可以去掉;一般在代码里的空行,是为了逻辑分块;但是分块如果太多,就会导致代码里都是空行哈; addBrokerage(firstUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageFirstPercent(), BrokerageAddReqBO::getSkuFirstBrokeragePrice); - // 2.1 获得二级推广员 + // TODO @疯狂:这里可以加个 firstUser.getBrokerageUserId() 为空的判断 return TradeBrokerageUserDO secondUser = tradeBrokerageUserService.getBrokerageUser(firstUser.getBrokerageUserId()); if (secondUser == null || !BooleanUtil.isTrue(secondUser.getBrokerageEnabled())) { return; @@ -95,6 +97,7 @@ public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordServ return; } + // 1. 更新佣金记录为已失效 TradeBrokerageRecordDO updateObj = new TradeBrokerageRecordDO().setStatus(BrokerageRecordStatusEnum.CANCEL.getStatus()); int updateRows = tradeBrokerageRecordMapper.updateByIdAndStatus(record.getId(), record.getStatus(), updateObj); if (updateRows == 0) { @@ -102,6 +105,7 @@ public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordServ return; } + // 2. 更新用户的佣金 if (BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus().equals(record.getStatus())) { tradeBrokerageUserService.updateUserFrozenBrokeragePrice(userId, -record.getPrice()); } else if (BrokerageRecordStatusEnum.SETTLEMENT.getStatus().equals(record.getStatus())) { @@ -109,6 +113,7 @@ public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordServ } } + // TODO @疯狂:是不是 calculateBrokeragePrice /** * 计算佣金 * @@ -122,12 +127,11 @@ public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordServ if (skuBrokeragePrice != null && skuBrokeragePrice > 0) { return ObjectUtil.defaultIfNull(skuBrokeragePrice, 0); } - // 2. 根据订单支付金额计算佣金 + // TODO @疯狂:要不要把 MoneyUtils 抽到 common 里,然后这里也使用这个类的方法; if (payPrice != null && payPrice > 0 && percent != null && percent > 0) { return NumberUtil.div(NumberUtil.mul(payPrice, percent), 100, 0, RoundingMode.DOWN).intValue(); } - return 0; } @@ -142,37 +146,35 @@ public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordServ */ private void addBrokerage(TradeBrokerageUserDO user, List list, Integer brokerageFrozenDays, Integer brokeragePercent, Function skuBrokeragePriceFun) { - // 处理冻结时间 + // 1.1 处理冻结时间 + // TODO @疯狂:是不是 brokerageFrozenDays != null && brokerageFrozenDays > 0 ?然后计算;更简洁一点; brokerageFrozenDays = ObjectUtil.defaultIfNull(brokerageFrozenDays, 0); LocalDateTime unfreezeTime = null; if (brokerageFrozenDays > 0) { unfreezeTime = LocalDateTime.now().plusDays(brokerageFrozenDays); } - - // 计算分佣 + // 1.2 计算分佣 int totalBrokerage = 0; List records = new ArrayList<>(); - for (BrokerageAddReqBO dto : list) { - int brokeragePerItem = calculateBrokerage(dto.getPayPrice(), brokeragePercent, skuBrokeragePriceFun.apply(dto)); + for (BrokerageAddReqBO item : list) { + int brokeragePerItem = calculateBrokerage(item.getPayPrice(), brokeragePercent, skuBrokeragePriceFun.apply(item)); + // TODO @疯狂:其实可以 brokeragePerItem <= 0 ,continue;这样 { 层级更少;代码更简洁;} if (brokeragePerItem > 0) { - int brokerage = brokeragePerItem * dto.getCount(); - records.add(TradeBrokerageRecordConvert.INSTANCE.convert(user, dto.getBizId(), brokerageFrozenDays, brokerage, unfreezeTime)); + int brokerage = brokeragePerItem * item.getCount(); + records.add(TradeBrokerageRecordConvert.INSTANCE.convert(user, item.getBizId(), brokerageFrozenDays, brokerage, unfreezeTime)); totalBrokerage += brokerage; } } - - if (records.isEmpty()) { + if (CollUtil.isEmpty(records)) { return; } - - // 保存佣金记录 + // 1.3 保存佣金记录 tradeBrokerageRecordMapper.insertBatch(records); - if (brokerageFrozenDays > 0) { - // 更新用户冻结佣金 + // 2. 更新用户佣金 + if (brokerageFrozenDays > 0) { // 更新用户冻结佣金 tradeBrokerageUserService.updateUserFrozenBrokeragePrice(user.getId(), totalBrokerage); - } else { - // 更新用户可用佣金 + } else { // 更新用户可用佣金 tradeBrokerageUserService.updateUserBrokeragePrice(user.getId(), totalBrokerage); } } @@ -190,8 +192,8 @@ public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordServ int count = 0; for (TradeBrokerageRecordDO record : records) { try { - boolean successful = getSelf().unfreezeRecord(record); - if (successful) { + boolean success = getSelf().unfreezeRecord(record); + if (success) { count++; } } catch (Exception e) { @@ -215,7 +217,6 @@ public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordServ // 更新用户冻结佣金 tradeBrokerageUserService.updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(record.getUserId(), -record.getPrice()); - log.info("[unfreezeRecord][record({}) 更新为已结算成功]", record.getId()); return true; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/BrokerageAddReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/BrokerageAddReqBO.java index a968d14ea..d325118a9 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/BrokerageAddReqBO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/BrokerageAddReqBO.java @@ -4,22 +4,29 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +// TODO @疯狂:要不要 service 还是拍平;就是都放在 brokerage 包下,然后 bo 里面,稍微分分; /** * 佣金 增加 Request BO + * * @author owen */ @Data @NoArgsConstructor @AllArgsConstructor public class BrokerageAddReqBO { + + // TODO @疯狂:bo 的话,也可以考虑加下 @Validated 注解,校验下参数;防御性下哈,虽然不一定用的到 + /** * 业务ID */ private String bizId; + // TODO @疯狂:不需要 payPrice 和 count,计算成 price 就好啦; /** * 商品支付价格 */ private Integer payPrice; + // TODO @疯狂:可以去掉 sku 哈,更抽象一点; /** * SKU 一级佣金 */ @@ -32,4 +39,5 @@ public class BrokerageAddReqBO { * 购买数量 */ private Integer count; + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserService.java index 773342e55..54913b98a 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserService.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerag import java.util.Collection; import java.util.List; +// TODO @疯狂:要不去掉 Trade 前缀哈;交易这块,我准备除了 tradeorder 保持下,类似 aftersale,都要取消前缀了;tradeorder 保持的原因,是避免 payorder 和它重复 /** * 分销用户 Service 接口 * @@ -70,6 +71,7 @@ public interface TradeBrokerageUserService { */ void updateUserBrokeragePrice(Long id, int brokeragePrice); + // TODO @疯狂:int 类型一般不用哈;尽量都用封装类型;不差这点内存哈; /** * 更新用户冻结佣金 * @@ -85,4 +87,5 @@ public interface TradeBrokerageUserService { * @param frozenBrokeragePrice 减少冻结佣金(负数) */ void updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(Long id, int frozenBrokeragePrice); + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImpl.java index 9691a8154..c4300c1ae 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImpl.java @@ -30,12 +30,6 @@ public class TradeBrokerageUserServiceImpl implements TradeBrokerageUserService @Resource private TradeBrokerageUserMapper brokerageUserMapper; - private void validateBrokerageUserExists(Long id) { - if (brokerageUserMapper.selectById(id) == null) { - throw exception(BROKERAGE_USER_NOT_EXISTS); - } - } - @Override public TradeBrokerageUserDO getBrokerageUser(Long id) { return brokerageUserMapper.selectById(id); @@ -55,15 +49,23 @@ public class TradeBrokerageUserServiceImpl implements TradeBrokerageUserService public void updateBrokerageUserId(Long id, Long brokerageUserId) { // 校验存在 validateBrokerageUserExists(id); - + // TODO @疯狂:貌似没实现完 } @Override public void updateBrokerageEnabled(Long id, Boolean brokerageEnabled) { // 校验存在 validateBrokerageUserExists(id); + // TODO @疯狂:貌似没实现完 } + private void validateBrokerageUserExists(Long id) { + if (brokerageUserMapper.selectById(id) == null) { + throw exception(BROKERAGE_USER_NOT_EXISTS); + } + } + + // TODO @疯狂:getBindBrokerageUser 会不会好点,因为统一使用 Bind 替代了 Invite @Override public TradeBrokerageUserDO getInviteBrokerageUser(Long id) { return Optional.ofNullable(id) @@ -73,6 +75,7 @@ public class TradeBrokerageUserServiceImpl implements TradeBrokerageUserService .orElse(null); } + // TODO @疯狂:单个更新,不用事务哈; @Override @Transactional(rollbackFor = Exception.class) public void updateUserBrokeragePrice(Long id, int brokeragePrice) { @@ -83,6 +86,7 @@ public class TradeBrokerageUserServiceImpl implements TradeBrokerageUserService } } + // TODO @疯狂:单个更新,不用事务哈; @Override @Transactional(rollbackFor = Exception.class) public void updateUserFrozenBrokeragePrice(Long id, int frozenBrokeragePrice) { @@ -93,12 +97,14 @@ public class TradeBrokerageUserServiceImpl implements TradeBrokerageUserService } } + // TODO @疯狂:单个更新,不用事务哈; @Override @Transactional(rollbackFor = Exception.class) public void updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(Long id, int frozenBrokeragePrice) { Assert.isTrue(frozenBrokeragePrice < 0); int updateRows = brokerageUserMapper.updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(id, frozenBrokeragePrice); if (updateRows == 0) { + // TODO @疯狂:挪到 trade 这变的错误码哈; throw exception(MEMBER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/config/TradeConfigService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/config/TradeConfigService.java index c00825f2e..1edb4f30b 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/config/TradeConfigService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/config/TradeConfigService.java @@ -12,7 +12,6 @@ import javax.validation.Valid; */ public interface TradeConfigService { - /** * 更新交易中心配置 * diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImplTest.java b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImplTest.java index a6d8dffb1..9daf3cafb 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImplTest.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImplTest.java @@ -25,6 +25,7 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomIntege import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; import static org.junit.jupiter.api.Assertions.assertEquals; +// TODO @芋艿:单测后续看看 /** * {@link TradeBrokerageRecordServiceImpl} 的单元测试类 * diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImplTest.java b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImplTest.java index 49e8aa351..153bbb426 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImplTest.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImplTest.java @@ -17,6 +17,7 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEq import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; import static org.junit.jupiter.api.Assertions.assertEquals; +// TODO @芋艿:单测后续看看 /** * {@link TradeBrokerageUserServiceImpl} 的单元测试类 * diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java index dc6439e74..dc7a58770 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java @@ -9,7 +9,7 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; */ public interface ErrorCodeConstants { - // ========== 用户相关 1004001000============ + // ========== 用户相关 1004001000============ ErrorCode USER_NOT_EXISTS = new ErrorCode(1004001000, "用户不存在"); ErrorCode USER_MOBILE_NOT_EXISTS = new ErrorCode(1004001001, "手机号未注册用户"); ErrorCode USER_MOBILE_USED = new ErrorCode(1004001002, "修改手机失败,该手机号({})已经被使用"); diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java index cfa93c983..242cb7110 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java @@ -136,6 +136,7 @@ public class MemberUserDO extends TenantBaseDO { */ private Long groupId; + // TODO @疯狂:看看要不要删除掉哈 // ========== 分销相关 ========== /** diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java index 7e35cdf2a..902057272 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java @@ -61,4 +61,5 @@ public interface MemberUserMapper extends BaseMapperX { return selectCount(new LambdaQueryWrapperX() .apply("FIND_IN_SET({0}, tag_ids)", tagId)); } + } From 0e8755972c3c97edbd2897f841634fa374566fe4 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Fri, 8 Sep 2023 00:35:54 +0800 Subject: [PATCH 26/50] =?UTF-8?q?=E8=90=A5=E9=94=80=E6=B4=BB=E5=8A=A8+?= =?UTF-8?q?=E8=AE=A2=E5=8D=95=EF=BC=9A=E5=AE=8C=E5=96=84=E5=A4=A7=E9=83=A8?= =?UTF-8?q?=E5=88=86=20TODO=20=E6=8F=90=E5=88=B0=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/bargain/BargainActivityApi.java | 18 +++ .../api/seckill/SeckillActivityApi.java | 20 ++++ .../dto/SeckillActivityUpdateStockReqDTO.java | 46 ++++++++ .../promotion/enums/ErrorCodeConstants.java | 1 + .../api/bargain/BargainActivityApiImpl.java | 39 +++++++ .../api/seckill/SeckillActivityApiImpl.java | 75 +++++++++++++ .../seckill/SeckillActivityService.java | 14 +++ .../seckill/SeckillActivityServiceImpl.java | 18 ++- .../yudao-module-trade-biz/pom.xml | 5 + .../admin/order/TradeOrderController.java | 4 + .../app/order/AppTradeOrderController.java | 4 +- .../vo/AppTradeOrderSettlementReqVO.java | 4 + .../dal/redis/no/TradeOrderNoRedisDAO.java | 35 ++++++ .../order/TradeOrderUpdateServiceImpl.java | 104 ++++++++++++------ .../module/pay/api/order/PayOrderApi.java | 7 ++ .../module/pay/enums/ErrorCodeConstants.java | 1 + .../module/pay/api/order/PayOrderApiImpl.java | 6 + .../pay/service/order/PayOrderService.java | 14 ++- .../service/order/PayOrderServiceImpl.java | 11 ++ 19 files changed, 381 insertions(+), 45 deletions(-) create mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApi.java create mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java create mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApiImpl.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/no/TradeOrderNoRedisDAO.java diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApi.java new file mode 100644 index 000000000..5e62d6e9e --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApi.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.promotion.api.bargain; + +/** + * 砍价活动 Api 接口 + * + * @author HUIHUI + */ +public interface BargainActivityApi { + + /** + * 更新砍价活动库存 + * + * @param activityId 砍价活动编号 + * @param count 购买数量 + */ + void updateBargainActivityStock(Long activityId, Integer count); + +} diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java new file mode 100644 index 000000000..09ec051a3 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.promotion.api.seckill; + +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO; + +/** + * 秒杀活动 API 接口 + * + * @author HUIHUI + */ +public interface SeckillActivityApi { + + + /** + * 更新秒杀库存 + * + * @param updateStockReqDTO 请求 + */ + void updateSeckillStock(SeckillActivityUpdateStockReqDTO updateStockReqDTO); + +} diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java new file mode 100644 index 000000000..476ba8e15 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.promotion.api.seckill.dto; + +import lombok.Data; + +import java.util.List; + +/** + * 更新秒杀库存 request DTO + * + * @author HUIHUI + */ +@Data +public class SeckillActivityUpdateStockReqDTO { + + /** + * 活动编号 + */ + private Long activityId; + /** + * 总购买数量 + */ + private Integer count; + /** + * 活动商品 + */ + private List items; + + @Data + public static class Item { + + /** + * SPU 编号 + */ + private Long spuId; + /** + * SKU 编号 + */ + private Long skuId; + /** + * 购买数量 + */ + private Integer count; + + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java index dd4389d5d..8c873b5ad 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java @@ -55,6 +55,7 @@ public interface ErrorCodeConstants { ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013008003, "秒杀活动已关闭,不能修改"); ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013008004, "秒杀活动未关闭或未结束,不能删除"); ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭"); + ErrorCode SECKILL_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013008006, "更新秒杀活动库存失败,原因秒杀库存不足"); // ========== 秒杀时段 1013009000 ========== ErrorCode SECKILL_CONFIG_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在"); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApiImpl.java new file mode 100644 index 000000000..826b4b2aa --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApiImpl.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.promotion.api.bargain; + +import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityUpdateReqVO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO; +import cn.iocoder.yudao.module.promotion.service.bargain.BargainActivityService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.BARGAIN_ACTIVITY_NOT_EXISTS; + +/** + * 砍价活动 Api 接口实现类 + * + * @author HUIHUI + */ +@Service +public class BargainActivityApiImpl implements BargainActivityApi { + + @Resource + private BargainActivityService bargainActivityService; + + @Override + public void updateBargainActivityStock(Long activityId, Integer count) { + // 查询砍价活动 + BargainActivityDO activity = bargainActivityService.getBargainActivity(activityId); + if (activity == null) { + throw exception(BARGAIN_ACTIVITY_NOT_EXISTS); + } + + // 更新砍价库存 + BargainActivityUpdateReqVO reqVO = new BargainActivityUpdateReqVO(); + reqVO.setId(activityId); + reqVO.setStock(activity.getStock() - count); + bargainActivityService.updateBargainActivity(reqVO); + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java new file mode 100644 index 000000000..299316aa0 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java @@ -0,0 +1,75 @@ +package cn.iocoder.yudao.module.promotion.api.seckill; + +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO; +import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_ACTIVITY_UPDATE_STOCK_FAIL; + +/** + * 秒杀活动接口 Api 接口实现类 + * + * @author HUIHUI + */ +@Service +public class SeckillActivityApiImpl implements SeckillActivityApi { + + @Resource + private SeckillActivityService activityService; + + @Override + public void updateSeckillStock(SeckillActivityUpdateStockReqDTO updateStockReqDTO) { + SeckillActivityDO seckillActivity = activityService.getSeckillActivity(updateStockReqDTO.getActivityId()); + if (seckillActivity.getStock() < updateStockReqDTO.getCount()) { + throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); + } + // 获取活动商品 + List productDOs = activityService.getSeckillProductListByActivityId(updateStockReqDTO.getActivityId()); + List items = updateStockReqDTO.getItems(); + Map> map = new HashMap<>(); + items.forEach(item -> { + if (map.containsKey(item.getSpuId())) { + List skuIds = map.get(item.getSpuId()); + skuIds.add(item.getSkuId()); + map.put(item.getSpuId(), skuIds); + } else { + List list = new ArrayList<>(); + list.add(item.getSkuId()); + map.put(item.getSpuId(), list); + } + }); + // 过滤出购买的商品 + List productDOList = CollectionUtils.filterList(productDOs, item -> map.get(item.getSpuId()).contains(item.getSkuId())); + Map productDOMap = CollectionUtils.convertMap(items, SeckillActivityUpdateStockReqDTO.Item::getSkuId, p -> p); + // 检查活动商品库存是否充足 + boolean b = CollectionUtils.anyMatch(productDOList, item -> { + SeckillActivityUpdateStockReqDTO.Item item1 = productDOMap.get(item.getSkuId()); + return (item.getStock() < item1.getCount()) || (item.getStock() - item1.getCount()) < 0; + }); + if (b) { + throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); + } + List doList = CollectionUtils.convertList(productDOList, item -> { + item.setStock(item.getStock() - productDOMap.get(item.getSkuId()).getCount()); + return item; + }); + + // 更新活动库存 + seckillActivity.setStock(seckillActivity.getStock() + updateStockReqDTO.getCount()); + seckillActivity.setTotalStock(seckillActivity.getTotalStock() - updateStockReqDTO.getCount()); + activityService.updateSeckillActivity(seckillActivity); + // 更新活动商品库存 + activityService.updateSeckillActivityProductByList(doList); + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java index 2e33a944d..052b59561 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java @@ -33,6 +33,20 @@ public interface SeckillActivityService { */ void updateSeckillActivity(@Valid SeckillActivityUpdateReqVO updateReqVO); + /** + * 更新秒杀活动 + * + * @param activityDO 秒杀活动 + */ + void updateSeckillActivity(SeckillActivityDO activityDO); + + /** + * 更新秒杀活动商品 + * + * @param productDOList 活动商品列表 + */ + void updateSeckillActivityProductByList(List productDOList); + /** * 关闭秒杀活动 * diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java index 531c35fcb..17fb9a90f 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java @@ -79,8 +79,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { * 1. 校验秒杀时段是否存在 * 2. 秒杀商品是否参加其它活动 * - * @param configIds 秒杀时段数组 - * @param spuId 商品 SPU 编号 + * @param configIds 秒杀时段数组 + * @param spuId 商品 SPU 编号 * @param activityId 秒杀活动编号 */ private void validateProductConflict(List configIds, Long spuId, Long activityId) { @@ -102,7 +102,7 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { /** * 校验秒杀商品是否都存在 * - * @param spuId 商品 SPU 编号 + * @param spuId 商品 SPU 编号 * @param products 秒杀商品 */ private void validateProductExists(Long spuId, List products) { @@ -144,11 +144,21 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { updateSeckillProduct(updateObj, updateReqVO.getProducts()); } + @Override + public void updateSeckillActivity(SeckillActivityDO activityDO) { + seckillActivityMapper.updateById(activityDO); + } + + @Override + public void updateSeckillActivityProductByList(List productDOList) { + seckillProductMapper.updateBatch(productDOList); + } + /** * 更新秒杀商品 * * @param activity 秒杀活动 - * @param products 该活动的最新商品配置 + * @param products 该活动的最新商品配置 */ private void updateSeckillProduct(SeckillActivityDO activity, List products) { // 第一步,对比新老数据,获得添加、修改、删除的列表 diff --git a/yudao-module-mall/yudao-module-trade-biz/pom.xml b/yudao-module-mall/yudao-module-trade-biz/pom.xml index 810446fa9..fd105e31a 100644 --- a/yudao-module-mall/yudao-module-trade-biz/pom.xml +++ b/yudao-module-mall/yudao-module-trade-biz/pom.xml @@ -82,6 +82,11 @@ yudao-spring-boot-starter-mybatis + + cn.iocoder.boot + yudao-spring-boot-starter-redis + + cn.iocoder.boot diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java index 926c2408c..728c70c67 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java @@ -25,6 +25,7 @@ import java.util.Map; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_NOT_FOUND; @Tag(name = "管理后台 - 交易订单") @RestController @@ -67,6 +68,9 @@ public class TradeOrderController { public CommonResult getOrderDetail(@RequestParam("id") Long id) { // 查询订单 TradeOrderDO order = tradeOrderQueryService.getOrder(id); + if (order == null) { + return success(null, ORDER_NOT_FOUND.getMsg()); + } // 查询订单项 List orderItems = tradeOrderQueryService.getOrderItemListByOrderId(id); // orderLog diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java index 5abb6a98c..a65836c33 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java @@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO; -import cn.iocoder.yudao.module.product.api.property.ProductPropertyValueApi; import cn.iocoder.yudao.module.trade.controller.app.order.vo.*; import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO; @@ -34,6 +33,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_NOT_FOUND; @Tag(name = "用户 App - 交易订单") @RestController @@ -83,7 +83,7 @@ public class AppTradeOrderController { // 查询订单 TradeOrderDO order = tradeOrderQueryService.getOrder(getLoginUserId(), id); if (order == null) { - return success(null); + return success(null, ORDER_NOT_FOUND.getMsg()); } // 查询订单项 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java index 3e322c786..6b8c14725 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java @@ -56,6 +56,10 @@ public class AppTradeOrderSettlementReqVO { @Schema(description = "拼团团长编号", example = "2048") private Long combinationHeadId; + // ========== 砍价活动相关字段 ========== + @Schema(description = "砍价活动编号", example = "123") + private Long bargainActivityId; + @Data @Schema(description = "用户 App - 商品项") @Valid diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/no/TradeOrderNoRedisDAO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/no/TradeOrderNoRedisDAO.java new file mode 100644 index 000000000..781975aca --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/no/TradeOrderNoRedisDAO.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.trade.dal.redis.no; + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Repository; + +import javax.annotation.Resource; +import java.time.LocalDateTime; + +/** + * 订单序号的 Redis DAO + * + * @author HUIHUI + */ +@Repository +public class TradeOrderNoRedisDAO { + public static final String TRADE_ORDER_NO_PREFIX = "O"; + + @Resource + private StringRedisTemplate stringRedisTemplate; + + /** + * 生成序号 + * + * @param prefix 前缀 + * @return 序号 + */ + public String generate(String prefix) { + String noPrefix = prefix + DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_PATTERN); + Long no = stringRedisTemplate.opsForValue().increment(noPrefix); + return noPrefix + no; + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index c4cfaee83..8b8ceef20 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.trade.service.order; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; @@ -25,11 +24,14 @@ import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi; import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; +import cn.iocoder.yudao.module.promotion.api.bargain.BargainActivityApi; import cn.iocoder.yudao.module.promotion.api.bargain.BargainRecordApi; import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO; import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; +import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi; +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO; import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderRemarkReqVO; @@ -45,6 +47,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; +import cn.iocoder.yudao.module.trade.dal.redis.no.TradeOrderNoRedisDAO; import cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants; import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; import cn.iocoder.yudao.module.trade.enums.order.*; @@ -70,7 +73,7 @@ import java.util.Set; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; -import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.ORDER_NOT_FOUND; +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.ORDER_UPDATE_PRICE_FAIL_EQUAL; import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.ORDER_UPDATE_PRICE_FAIL_PAID; import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; @@ -88,6 +91,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { private TradeOrderMapper tradeOrderMapper; @Resource private TradeOrderItemMapper tradeOrderItemMapper; + @Resource + private TradeOrderNoRedisDAO orderNoRedisDAO; @Resource private CartService cartService; @@ -111,6 +116,10 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @Resource private BargainRecordApi bargainRecordApi; @Resource + private SeckillActivityApi seckillActivityApi; + @Resource + private BargainActivityApi bargainActivityApi; + @Resource private MemberUserApi memberUserApi; @Resource private MemberLevelApi memberLevelApi; @@ -189,22 +198,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { // TODO @puhui999:这个逻辑,先抽个小方法;未来要通过设计模式,把这些拼团之类的逻辑,抽象出去 // 拼团 if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { - MemberUserRespDTO user = memberUserApi.getUser(userId); - List recordRespDTOS = combinationRecordApi.getRecordListByUserIdAndActivityId(userId, createReqVO.getCombinationActivityId()); - // TODO 拼团一次应该只能选择一种规格的商品 - TradeOrderItemDO orderItemDO = orderItems.get(0); - if (CollUtil.isNotEmpty(recordRespDTOS)) { - List skuIds = convertList(recordRespDTOS, CombinationRecordRespDTO::getSkuId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())); - List tradeOrderItemDOS = tradeOrderItemMapper.selectListByOrderIdAnSkuId(convertList(recordRespDTOS, - CombinationRecordRespDTO::getOrderId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), skuIds); - combinationRecordApi.validateCombinationLimitCount(createReqVO.getCombinationActivityId(), - CollectionUtils.getSumValue(tradeOrderItemDOS, TradeOrderItemDO::getCount, Integer::sum), orderItemDO.getCount()); - } - - combinationRecordApi.createCombinationRecord(TradeOrderConvert.INSTANCE.convert(order, orderItemDO, createReqVO, user)); + createCombinationRecord(userId, createReqVO, orderItems, order); } // 3.2 秒杀的特殊逻辑 - // TODO 秒杀扣减库存是下单就扣除还是等待订单支付成功再扣除 if (Objects.equals(TradeOrderTypeEnum.SECKILL.getType(), order.getType())) { } @@ -214,6 +210,22 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { return order; } + private void createCombinationRecord(Long userId, AppTradeOrderCreateReqVO createReqVO, List orderItems, TradeOrderDO order) { + MemberUserRespDTO user = memberUserApi.getUser(userId); + List recordRespDTOS = combinationRecordApi.getRecordListByUserIdAndActivityId(userId, createReqVO.getCombinationActivityId()); + // TODO 拼团一次应该只能选择一种规格的商品 + TradeOrderItemDO orderItemDO = orderItems.get(0); + if (CollUtil.isNotEmpty(recordRespDTOS)) { + List skuIds = convertList(recordRespDTOS, CombinationRecordRespDTO::getSkuId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())); + List tradeOrderItemDOS = tradeOrderItemMapper.selectListByOrderIdAnSkuId(convertList(recordRespDTOS, + CombinationRecordRespDTO::getOrderId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), skuIds); + combinationRecordApi.validateCombinationLimitCount(createReqVO.getCombinationActivityId(), + CollectionUtils.getSumValue(tradeOrderItemDOS, TradeOrderItemDO::getCount, Integer::sum), orderItemDO.getCount()); + } + + combinationRecordApi.createCombinationRecord(TradeOrderConvert.INSTANCE.convert(order, orderItemDO, createReqVO, user)); + } + // TODO @puhui999:订单超时,自动取消; /** @@ -240,8 +252,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { address = validateAddress(userId, createReqVO.getAddressId()); } TradeOrderDO order = TradeOrderConvert.INSTANCE.convert(userId, clientIp, createReqVO, calculateRespBO, address); + String no = orderNoRedisDAO.generate(TradeOrderNoRedisDAO.TRADE_ORDER_NO_PREFIX); order.setType(validateActivity(createReqVO)); - order.setNo(IdUtil.getSnowflakeNextId() + ""); // TODO @puhui999: 参考支付订单,的 no 生成哈; + order.setNo(no); order.setStatus(TradeOrderStatusEnum.UNPAID.getStatus()); order.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()); order.setProductCount(getSumValue(calculateRespBO.getItems(), TradePriceCalculateRespBO.OrderItem::getCount, Integer::sum)); @@ -293,19 +306,23 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { private void afterCreateTradeOrder(Long userId, AppTradeOrderCreateReqVO createReqVO, TradeOrderDO tradeOrderDO, List orderItems, TradePriceCalculateRespBO calculateRespBO) { - // 下单时扣减商品库存 - // TODO @puhui999:扣库存,需要前置; + Integer count = getSumValue(orderItems, TradeOrderItemDO::getCount, Integer::sum); // 1)如果是秒杀商品:额外扣减秒杀的库存; - // 2)如果是拼团活动:额外扣减拼团的库存; - // 3)如果是砍价活动:额外扣减砍价的库存; - productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convertNegative(orderItems)); - - // 删除购物车商品 - Set cartIds = convertSet(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId); - if (CollUtil.isNotEmpty(cartIds)) { - cartService.deleteCart(userId, cartIds); + if (Objects.equals(TradeOrderTypeEnum.SECKILL.getType(), tradeOrderDO.getType())) { + SeckillActivityUpdateStockReqDTO updateStockReqDTO = new SeckillActivityUpdateStockReqDTO(); + updateStockReqDTO.setActivityId(createReqVO.getSeckillActivityId()); + updateStockReqDTO.setCount(count); + updateStockReqDTO.setItems(CollectionUtils.convertList(orderItems, item -> { + SeckillActivityUpdateStockReqDTO.Item item1 = new SeckillActivityUpdateStockReqDTO.Item(); + item1.setSpuId(item.getSpuId()); + item1.setSkuId(item.getSkuId()); + item1.setCount(item.getCount()); + return item1; + })); + seckillActivityApi.updateSeckillStock(updateStockReqDTO); } - + // 2)如果是砍价活动:额外扣减砍价的库存; + bargainActivityApi.updateBargainActivityStock(createReqVO.getBargainActivityId(), count); // 扣减积分 TODO 芋艿:待实现,需要前置; // 这个是不是应该放到支付成功之后?如果支付后的话,可能积分可以重复使用哈。资源类,都要预扣 @@ -315,6 +332,15 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { .setOrderId(tradeOrderDO.getId())); } + // 下单时扣减商品库存 + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convertNegative(orderItems)); + + // 删除购物车商品 + Set cartIds = convertSet(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId); + if (CollUtil.isNotEmpty(cartIds)) { + cartService.deleteCart(userId, cartIds); + } + // 生成预支付 createPayOrder(tradeOrderDO, orderItems, calculateRespBO); @@ -464,11 +490,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { */ private TradeOrderDO validateOrderDeliverable(Long id) { TradeOrderDO order = validateOrderExists(id); - // 校验订单是否是待发货状态 - // TODO @puhui999:已经发货,可以重新发货,修改信息; - if (!TradeOrderStatusEnum.isUndelivered(order.getStatus())) { - throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED); - } // 校验订单是否退款 if (ObjectUtil.notEqual(TradeOrderRefundStatusEnum.NONE.getStatus(), order.getRefundStatus())) { throw exception(ORDER_DELIVERY_FAIL_REFUND_STATUS_NOT_NONE); @@ -540,14 +561,25 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { if (order.getPayStatus()) { throw exception(ORDER_UPDATE_PRICE_FAIL_PAID); } - // TODO @puhui999:如果改价,需要校验下是否真的变化; + if (ObjectUtil.equal(order.getAdjustPrice(), reqVO.getAdjustPrice())) { + throw exception(ORDER_UPDATE_PRICE_FAIL_EQUAL); + } - // 更新 - // TODO @puhui999:TradeOrderItemDO 需要做 adjustPrice 的分摊;另外,支付订单那的价格,需要 update 下; + List itemDOs = tradeOrderItemMapper.selectListByOrderId(order.getId()); + // TradeOrderItemDO 需要做 adjustPrice 的分摊 + int price = reqVO.getAdjustPrice() / itemDOs.size(); + itemDOs.forEach(item -> { + item.setAdjustPrice(price); + }); + // 更新 TradeOrderItem + tradeOrderItemMapper.updateBatch(itemDOs); + // 更新订单 TradeOrderDO update = TradeOrderConvert.INSTANCE.convert(reqVO); update.setPayPrice(update.getPayPrice() + update.getAdjustPrice()); // TODO @芋艿:改价时,赠送的积分,要不要做改动??? tradeOrderMapper.updateById(update); + // 更新支付订单 + payOrderApi.updatePayOrderPriceById(order.getPayOrderId(), update.getPayPrice()); } @Override diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java index 5c1905ebe..94a79ea3d 100644 --- a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java @@ -29,4 +29,11 @@ public interface PayOrderApi { */ PayOrderRespDTO getOrder(Long id); + /** + * 更新支付订单价格 + * + * @param payOrderId 支付单编号 + * @param payPrice 支付单价格 + */ + void updatePayOrderPriceById(Long payOrderId, Integer payPrice); } diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java index ee8947286..2ee11f1be 100644 --- a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java @@ -28,6 +28,7 @@ public interface ErrorCodeConstants { ErrorCode ORDER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1007002004, "发起支付报错,错误码:{},错误提示:{}"); ErrorCode ORDER_REFUND_FAIL_STATUS_ERROR = new ErrorCode(1007002005, "支付订单退款失败,原因:状态不是已支付或已退款"); ErrorCode ORDER_UPDATE_PRICE_FAIL_PAID = new ErrorCode(1007002006, "支付订单调价失败,原因:支付订单已付款,不能调价"); + ErrorCode ORDER_UPDATE_PRICE_FAIL_EQUAL = new ErrorCode(1007002007, "支付订单调价失败,原因:价格没有变化"); // ========== ORDER 模块(拓展单) 1007003000 ========== ErrorCode ORDER_EXTENSION_NOT_FOUND = new ErrorCode(1007003000, "支付交易拓展单不存在"); diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java index a245880ba..18c9ff3ef 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java @@ -31,4 +31,10 @@ public class PayOrderApiImpl implements PayOrderApi { return PayOrderConvert.INSTANCE.convert2(order); } + @Override + public void updatePayOrderPriceById(Long payOrderId, Integer payPrice) { + payOrderService.updatePayOrderPriceById(payOrderId, payPrice); + } + + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java index 3d66ae9b1..e03bda117 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java @@ -33,7 +33,7 @@ public interface PayOrderService { /** * 获得支付订单 * - * @param appId 应用编号 + * @param appId 应用编号 * @param merchantOrderId 商户订单编号 * @return 支付订单 */ @@ -75,7 +75,7 @@ public interface PayOrderService { * 提交支付 * 此时,会发起支付渠道的调用 * - * @param reqVO 提交请求 + * @param reqVO 提交请求 * @param userIp 提交 IP * @return 提交结果 */ @@ -93,11 +93,19 @@ public interface PayOrderService { /** * 更新支付订单的退款金额 * - * @param id 编号 + * @param id 编号 * @param incrRefundPrice 增加的退款金额 */ void updateOrderRefundPrice(Long id, Integer incrRefundPrice); + /** + * 更新支付订单价格 + * + * @param payOrderId 支付单编号 + * @param payPrice 支付单价格 + */ + void updatePayOrderPriceById(Long payOrderId, Integer payPrice); + /** * 获得支付订单 * diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java index d56035187..bb43295c2 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java @@ -410,6 +410,17 @@ public class PayOrderServiceImpl implements PayOrderService { } } + @Override + public void updatePayOrderPriceById(Long payOrderId, Integer payPrice) { + PayOrderDO order = orderMapper.selectById(payOrderId); + if (order == null) { + throw exception(ORDER_NOT_FOUND); + } + + order.setPrice(payPrice); + orderMapper.updateById(order); + } + @Override public PayOrderExtensionDO getOrderExtension(Long id) { return orderExtensionMapper.selectById(id); From 166b1b31c0b20c3016fa2bebce376fdef96ea142 Mon Sep 17 00:00:00 2001 From: owen Date: Fri, 8 Sep 2023 10:59:06 +0800 Subject: [PATCH 27/50] =?UTF-8?q?trade:=20=E5=88=86=E9=94=80=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/mysql/brokerage.sql | 11 +++--- .../user/TradeBrokerageUserController.java | 35 ++++++++++++++++++- .../user/vo/TradeBrokerageUserRespVO.java | 26 ++++++++++++++ .../user/TradeBrokerageUserConvert.java | 34 ++++++++++++++++++ .../record/TradeBrokerageRecordMapper.java | 7 ++++ .../record/TradeBrokerageRecordService.java | 14 ++++++-- .../TradeBrokerageRecordServiceImpl.java | 7 ++++ .../record/bo/UserBrokerageSummaryBO.java | 24 +++++++++++++ .../user/TradeBrokerageUserService.java | 7 ++++ .../user/TradeBrokerageUserServiceImpl.java | 5 +++ .../dal/dataobject/user/MemberUserDO.java | 34 ------------------ 11 files changed, 163 insertions(+), 41 deletions(-) create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/UserBrokerageSummaryBO.java diff --git a/sql/mysql/brokerage.sql b/sql/mysql/brokerage.sql index 127fcb728..48adc14e8 100644 --- a/sql/mysql/brokerage.sql +++ b/sql/mysql/brokerage.sql @@ -24,7 +24,7 @@ create table trade_config create table trade_brokerage_user ( id bigint auto_increment comment '用户编号' primary key, - brokerage_user_id bigint not null comment '推广员编号', + brokerage_user_id bigint null comment '推广员编号', brokerage_bind_time datetime null comment '推广员绑定时间', brokerage_enabled bit default 1 not null comment '是否成为推广员', brokerage_time datetime null comment '成为分销员时间', @@ -185,12 +185,15 @@ SELECT @parentId := LAST_INSERT_ID(); INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) VALUES ('分销用户查询', 'trade:brokerage-user:query', 3, 1, @parentId, '', '', '', 0); INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) -VALUES ('分销用户修改推广员', 'trade:brokerage-user:update-brokerage-user', 3, 2, @parentId, '', '', '', 0); +VALUES ('分销用户推广人查询', 'trade:brokerage-user:user-query', 3, 2, @parentId, '', '', '', 0); INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) -VALUES ('分销用户清除推广员', 'trade:brokerage-user:clear-brokerage-user', 3, 3, @parentId, '', '', '', 0); +VALUES ('分销用户推广订单查询', 'trade:brokerage-user:order-query', 3, 3, @parentId, '', '', '', 0); INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) VALUES ('分销用户修改推广资格', 'trade:brokerage-user:update-brokerage-enable', 3, 4, @parentId, '', '', '', 0); - +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES ('分销用户修改推广员', 'trade:brokerage-user:update-brokerage-user', 3, 5, @parentId, '', '', '', 0); +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES ('分销用户清除推广员', 'trade:brokerage-user:clear-brokerage-user', 3, 6, @parentId, '', '', '', 0); -- 增加菜单:佣金记录 INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/TradeBrokerageUserController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/TradeBrokerageUserController.java index e4cc63fb9..5da3acb5b 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/TradeBrokerageUserController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/TradeBrokerageUserController.java @@ -2,9 +2,15 @@ package cn.iocoder.yudao.module.trade.controller.admin.brokerage.user; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.api.user.MemberUserApi; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.*; import cn.iocoder.yudao.module.trade.convert.brokerage.user.TradeBrokerageUserConvert; import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; +import cn.iocoder.yudao.module.trade.service.brokerage.record.TradeBrokerageRecordService; +import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.UserBrokerageSummaryBO; import cn.iocoder.yudao.module.trade.service.brokerage.user.TradeBrokerageUserService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -15,8 +21,12 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.Valid; +import java.util.Map; +import java.util.Set; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; @Tag(name = "管理后台 - 分销用户") @RestController @@ -26,6 +36,11 @@ public class TradeBrokerageUserController { @Resource private TradeBrokerageUserService brokerageUserService; + @Resource + private TradeBrokerageRecordService brokerageRecordService; + + @Resource + private MemberUserApi memberUserApi; @PutMapping("/update-brokerage-user") @Operation(summary = "修改推广员") @@ -64,8 +79,26 @@ public class TradeBrokerageUserController { @Operation(summary = "获得分销用户分页") @PreAuthorize("@ss.hasPermission('trade:brokerage-user:query')") public CommonResult> getBrokerageUserPage(@Valid TradeBrokerageUserPageReqVO pageVO) { + // 分页查询 PageResult pageResult = brokerageUserService.getBrokerageUserPage(pageVO); - return success(TradeBrokerageUserConvert.INSTANCE.convertPage(pageResult)); + + // 涉及到的用户 + Set userIds = convertSet(pageResult.getList(), TradeBrokerageUserDO::getId); + // 查询用户信息 + Map userMap = memberUserApi.getUserMap(userIds); + // 合计分佣订单 + Map userOrderSummaryMap = convertMap(userIds, + userId -> userId, + userId -> brokerageRecordService.summaryByUserIdAndBizTypeAndStatus(userId, + BrokerageRecordBizTypeEnum.ORDER.getType(), BrokerageRecordStatusEnum.SETTLEMENT.getStatus())); + // 合计推广用户数量 + Map brokerageUserCountMap = convertMap(userIds, + userId -> userId, + userId -> brokerageUserService.getCountByBrokerageUserId(userId)); + + // todo 合计提现 + + return success(TradeBrokerageUserConvert.INSTANCE.convertPage(pageResult, userMap, brokerageUserCountMap, userOrderSummaryMap)); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserRespVO.java index 090eb04b5..ee82efa0d 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserRespVO.java @@ -19,4 +19,30 @@ public class TradeBrokerageUserRespVO extends TradeBrokerageUserBaseVO { @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; + + // ========== 用户信息 ========== + + @Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png") + private String avatar; + @Schema(description = "用户昵称", example = "李四") + private String nickname; + + + // ========== 推广信息 ========== + + @Schema(description = "推广用户数量(一级)", example = "20019") + private Integer brokerageUserCount; + @Schema(description = "推广订单数量", example = "20019") + private Integer brokerageOrderCount; + @Schema(description = "推广订单金额", example = "20019") + private Integer brokerageOrderPrice; + + + // ========== 提现信息 ========== + + @Schema(description = "已提现金额", example = "20019") + private Integer withdrawPrice; + @Schema(description = "已提现次数", example = "20019") + private Integer withdrawCount; + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/TradeBrokerageUserConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/TradeBrokerageUserConvert.java index 1a62bded0..b5800efed 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/TradeBrokerageUserConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/TradeBrokerageUserConvert.java @@ -1,12 +1,17 @@ package cn.iocoder.yudao.module.trade.convert.brokerage.user; +import cn.hutool.core.map.MapUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.TradeBrokerageUserRespVO; import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; +import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.UserBrokerageSummaryBO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; import java.util.List; +import java.util.Map; +import java.util.Optional; /** * 分销用户 Convert @@ -24,4 +29,33 @@ public interface TradeBrokerageUserConvert { PageResult convertPage(PageResult page); + default PageResult convertPage(PageResult pageResult, + Map userMap, + Map brokerageUserCountMap, + Map userOrderSummaryMap) { + PageResult result = convertPage(pageResult); + for (TradeBrokerageUserRespVO vo : result.getList()) { + // 用户信息 + Optional.ofNullable(userMap.get(vo.getId())) + .ifPresent(user -> { + vo.setNickname(user.getNickname()); + vo.setAvatar(user.getAvatar()); + }); + + // 推广用户数量(一级) + vo.setBrokerageUserCount(MapUtil.getInt(brokerageUserCountMap, vo.getId(), 0)); + + Optional orderSummaryOptional = Optional.ofNullable(userOrderSummaryMap.get(vo.getId())); + // 推广订单数量 + vo.setBrokerageOrderCount(orderSummaryOptional.map(UserBrokerageSummaryBO::getCount).orElse(0)); + // 推广订单金额 + vo.setBrokerageOrderPrice(orderSummaryOptional.map(UserBrokerageSummaryBO::getPrice).orElse(0)); + + // todo 已提现次数 + vo.setWithdrawCount(0); + // todo 已提现金额 + vo.setWithdrawPrice(0); + } + return result; + } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/TradeBrokerageRecordMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/TradeBrokerageRecordMapper.java index 41ed8bad9..2adb488eb 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/TradeBrokerageRecordMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/TradeBrokerageRecordMapper.java @@ -5,8 +5,11 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordPageReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.TradeBrokerageRecordDO; +import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.UserBrokerageSummaryBO; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; import java.time.LocalDateTime; import java.util.List; @@ -46,4 +49,8 @@ public interface TradeBrokerageRecordMapper extends BaseMapperX Date: Fri, 8 Sep 2023 12:29:38 +0800 Subject: [PATCH 28/50] =?UTF-8?q?trade:=20=E5=88=86=E9=94=80Review?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/mysql/brokerage.sql | 17 ++-- .../trade/enums/ErrorCodeConstants.java | 1 + .../brokerage/BrokerageBindModeEnum.java | 10 ++- .../BrokerageEnabledConditionEnum.java | 5 +- .../brokerage/BrokerageRecordBizTypeEnum.java | 5 +- .../user/TradeBrokerageUserController.java | 2 +- .../admin/config/vo/TradeConfigBaseVO.java | 1 - .../record/TradeBrokerageRecordConvert.java | 12 ++- .../user/TradeBrokerageUserConvert.java | 2 +- .../convert/order/TradeOrderConvert.java | 8 +- .../record/TradeBrokerageRecordMapper.java | 5 +- .../user/TradeBrokerageUserMapper.java | 10 +-- .../brokerage/bo/BrokerageAddReqBO.java | 36 +++++++++ .../bo/UserBrokerageSummaryBO.java | 2 +- .../record/TradeBrokerageRecordService.java | 21 ++--- .../TradeBrokerageRecordServiceImpl.java | 81 +++++++++---------- .../record/bo/BrokerageAddReqBO.java | 43 ---------- .../user/TradeBrokerageUserService.java | 9 +-- .../user/TradeBrokerageUserServiceImpl.java | 21 ++--- .../order/TradeOrderUpdateServiceImpl.java | 17 ++-- .../TradeBrokerageRecordServiceImplTest.java | 16 ++-- .../member/enums/ErrorCodeConstants.java | 1 - 22 files changed, 155 insertions(+), 170 deletions(-) create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/{record => }/bo/UserBrokerageSummaryBO.java (84%) delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/BrokerageAddReqBO.java diff --git a/sql/mysql/brokerage.sql b/sql/mysql/brokerage.sql index 48adc14e8..53b9dc04e 100644 --- a/sql/mysql/brokerage.sql +++ b/sql/mysql/brokerage.sql @@ -3,8 +3,8 @@ create table trade_config ( id bigint auto_increment comment '自增主键' primary key, brokerage_enabled bit default 1 not null comment '是否启用分佣', - brokerage_enabled_condition tinyint default 0 not null comment '分佣模式:0-人人分销 1-指定分销', - brokerage_bind_mode tinyint default 0 not null comment '分销关系绑定模式: 0-没有推广人,1-新用户', + brokerage_enabled_condition tinyint default 0 not null comment '分佣模式:1-人人分销 2-指定分销', + brokerage_bind_mode tinyint default 0 not null comment '分销关系绑定模式: 1-没有推广人,2-新用户, 3-扫码覆盖', brokerage_post_urls varchar(2000) default '' null comment '分销海报图地址数组', brokerage_first_percent int default 0 not null comment '一级返佣比例', brokerage_second_percent int default 0 not null comment '二级返佣比例', @@ -104,14 +104,15 @@ create index idx_audit_status on trade_brokerage_withdraw (status) comment '状 insert into system_dict_type(type, name) values ('brokerage_enabled_condition', '分佣模式'); insert into system_dict_data(dict_type, label, value, sort, remark) -values ('brokerage_enabled_condition', '人人分销', 0, 0, '所有用户都可以分销'), - ('brokerage_enabled_condition', '指定分销', 1, 1, '仅可后台手动设置推广员'); +values ('brokerage_enabled_condition', '人人分销', 1, 1, '所有用户都可以分销'), + ('brokerage_enabled_condition', '指定分销', 2, 2, '仅可后台手动设置推广员'); insert into system_dict_type(type, name) values ('brokerage_bind_mode', '分销关系绑定模式'); insert into system_dict_data(dict_type, label, value, sort, remark) -values ('brokerage_bind_mode', '没有推广人', 0, 0, '只要用户没有推广人,随时都可以绑定推广关系'), - ('brokerage_bind_mode', '新用户', 1, 1, '仅新用户注册时才能绑定推广关系'); +values ('brokerage_bind_mode', '没有推广人', 1, 1, '只要用户没有推广人,随时都可以绑定推广关系'), + ('brokerage_bind_mode', '新用户', 2, 2, '仅新用户注册时才能绑定推广关系'), + ('brokerage_bind_mode', '扫码覆盖', 3, 3, '如果用户已经有推广人,推广人会被变更'); insert into system_dict_type(type, name) values ('brokerage_withdraw_type', '佣金提现类型'); @@ -124,8 +125,8 @@ values ('brokerage_withdraw_type', '钱包', 1, 1), insert into system_dict_type(type, name) values ('brokerage_record_biz_type', '佣金记录业务类型'); insert into system_dict_data(dict_type, label, value, sort) -values ('brokerage_record_biz_type', '订单返佣', 0, 0), - ('brokerage_record_biz_type', '申请提现', 1, 1); +values ('brokerage_record_biz_type', '订单返佣', 1, 1), + ('brokerage_record_biz_type', '申请提现', 2, 2); insert into system_dict_type(type, name) values ('brokerage_record_status', '佣金记录状态'); diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java index f6c0ca782..5ddff9b11 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java @@ -77,5 +77,6 @@ public interface ErrorCodeConstants { // ========== 分销用户 模块 1011007000 ========== ErrorCode BROKERAGE_USER_NOT_EXISTS = new ErrorCode(1011007000, "分销用户不存在"); + ErrorCode USER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH = new ErrorCode(1011007001, "用户冻结佣金({})数量不足"); } diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageBindModeEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageBindModeEnum.java index 19bb53daa..3b6610ac9 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageBindModeEnum.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageBindModeEnum.java @@ -15,16 +15,18 @@ import java.util.Arrays; @Getter public enum BrokerageBindModeEnum implements IntArrayValuable { - // TODO @疯狂:要不从 1 开始? /** * 只要用户没有推广人,随时都可以绑定分销关系 */ - ANYTIME(0, "没有推广人"), + ANYTIME(1, "没有推广人"), /** * 仅新用户注册时才能绑定推广关系 */ - REGISTER(1, "新用户"), - // TODO @疯狂:要加个 2,每次扫码都覆盖 + REGISTER(2, "新用户"), + /** + * 每次扫码都覆盖 + */ + OVERRIDE(3, "扫码覆盖"), ; public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageBindModeEnum::getMode).toArray(); diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageEnabledConditionEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageEnabledConditionEnum.java index 1d1ef0c81..990d10e16 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageEnabledConditionEnum.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageEnabledConditionEnum.java @@ -15,15 +15,14 @@ import java.util.Arrays; @Getter public enum BrokerageEnabledConditionEnum implements IntArrayValuable { - // TODO @疯狂:这个也从 1 开始哇 /** * 所有用户都可以分销 */ - ALL(0, "人人分销"), + ALL(1, "人人分销"), /** * 仅可后台手动设置推广员 */ - ADMIN(1, "指定分销"), + ADMIN(2, "指定分销"), ; public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageEnabledConditionEnum::getCondition).toArray(); diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageRecordBizTypeEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageRecordBizTypeEnum.java index 50c83c05a..ae798a6ac 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageRecordBizTypeEnum.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageRecordBizTypeEnum.java @@ -15,9 +15,8 @@ import java.util.Arrays; @Getter public enum BrokerageRecordBizTypeEnum implements IntArrayValuable { - // TODO @疯狂:这个也从 1 开始哇 - ORDER(0, "获得推广佣金", "获得推广佣金 {}", true), - WITHDRAW(1, "提现申请", "提现申请扣除佣金 {}", false), + ORDER(1, "获得推广佣金", "获得推广佣金 {}", true), + WITHDRAW(2, "提现申请", "提现申请扣除佣金 {}", false), ; public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageRecordBizTypeEnum::getType).toArray(); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/TradeBrokerageUserController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/TradeBrokerageUserController.java index 5da3acb5b..38a27d8c8 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/TradeBrokerageUserController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/TradeBrokerageUserController.java @@ -10,7 +10,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerag import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; import cn.iocoder.yudao.module.trade.service.brokerage.record.TradeBrokerageRecordService; -import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.UserBrokerageSummaryBO; +import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO; import cn.iocoder.yudao.module.trade.service.brokerage.user.TradeBrokerageUserService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigBaseVO.java index 55b168582..ee20156f1 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigBaseVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigBaseVO.java @@ -54,7 +54,6 @@ public class TradeConfigBaseVO { @PositiveOrZero(message = "用户提现最低金额不能是负数") private Integer brokerageWithdrawMinPrice; - // TODO @疯狂:要不要做成字典?按道理都可以体现对哇?感觉是全局的配置哈; @Schema(description = "提现银行", requiredMode = Schema.RequiredMode.REQUIRED, example = "[0, 1]") @NotEmpty(message = "提现银行不能为空") private List brokerageBankNames; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/TradeBrokerageRecordConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/TradeBrokerageRecordConvert.java index 1e8290460..2d67f5f2e 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/TradeBrokerageRecordConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/TradeBrokerageRecordConvert.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.trade.convert.brokerage.record; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordRespVO; @@ -29,19 +30,22 @@ public interface TradeBrokerageRecordConvert { PageResult convertPage(PageResult page); - default TradeBrokerageRecordDO convert(TradeBrokerageUserDO user, String bizId, int brokerageFrozenDays, int brokerage, LocalDateTime unfreezeTime) { + default TradeBrokerageRecordDO convert(TradeBrokerageUserDO user, BrokerageRecordBizTypeEnum bizType, String bizId, + Integer brokerageFrozenDays, int brokerage, LocalDateTime unfreezeTime, + String title) { + brokerageFrozenDays = ObjectUtil.defaultIfNull(brokerageFrozenDays, 0); // 不冻结时,佣金直接就是结算状态 Integer status = brokerageFrozenDays > 0 ? BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus() : BrokerageRecordStatusEnum.SETTLEMENT.getStatus(); return new TradeBrokerageRecordDO() .setUserId(user.getId()) - .setBizType(BrokerageRecordBizTypeEnum.ORDER.getType()) + .setBizType(bizType.getType()) .setBizId(bizId) .setPrice(brokerage) .setTotalPrice(user.getBrokeragePrice()) - .setTitle(BrokerageRecordBizTypeEnum.ORDER.getTitle()) // TODO @疯狂:可能 title 不是很固化,会存在类似:沐晴成功购买《XXX JVM 实战》 - .setDescription(StrUtil.format(BrokerageRecordBizTypeEnum.ORDER.getDescription(), String.valueOf(brokerage / 100.0))) + .setTitle(title) + .setDescription(StrUtil.format(bizType.getDescription(), String.valueOf(brokerage / 100.0))) .setStatus(status) .setFrozenDays(brokerageFrozenDays) .setUnfreezeTime(unfreezeTime); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/TradeBrokerageUserConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/TradeBrokerageUserConvert.java index b5800efed..beda1571c 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/TradeBrokerageUserConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/TradeBrokerageUserConvert.java @@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.TradeBrokerageUserRespVO; import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; -import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.UserBrokerageSummaryBO; +import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java index f42af2d73..27854def6 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java @@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.common.util.string.StrUtils; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; -import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.BrokerageAddReqBO; +import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; import cn.iocoder.yudao.module.pay.enums.DictTypeConstants; @@ -277,8 +277,8 @@ public interface TradeOrderConvert { default BrokerageAddReqBO convert(TradeOrderItemDO item, ProductSkuRespDTO sku) { return new BrokerageAddReqBO().setBizId(String.valueOf(item.getId())) - .setPayPrice(item.getPayPrice()).setCount(item.getCount()) - .setSkuFirstBrokeragePrice(sku.getSubCommissionFirstPrice()) - .setSkuSecondBrokeragePrice(sku.getSubCommissionSecondPrice()); + .setBasePrice(item.getPayPrice() * item.getCount()) + .setFirstBrokeragePrice(sku.getSubCommissionFirstPrice()) + .setSecondBrokeragePrice(sku.getSubCommissionSecondPrice()); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/TradeBrokerageRecordMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/TradeBrokerageRecordMapper.java index 2adb488eb..9a8c6df76 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/TradeBrokerageRecordMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/TradeBrokerageRecordMapper.java @@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordPageReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.TradeBrokerageRecordDO; -import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.UserBrokerageSummaryBO; +import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -43,8 +43,7 @@ public interface TradeBrokerageRecordMapper extends BaseMapperX 0); LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() .setSql(" brokerage_price = brokerage_price + " + incrCount) @@ -46,7 +46,7 @@ public interface TradeBrokerageUserMapper extends BaseMapperX lambdaUpdateWrapper = new LambdaUpdateWrapper() .setSql(" brokerage_price = brokerage_price + " + incrCount) // 负数,所以使用 + 号 @@ -60,7 +60,7 @@ public interface TradeBrokerageUserMapper extends BaseMapperX 0); LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() .setSql(" frozen_brokerage_price = frozen_brokerage_price + " + incrCount) @@ -75,7 +75,7 @@ public interface TradeBrokerageUserMapper extends BaseMapperX lambdaUpdateWrapper = new LambdaUpdateWrapper() .setSql(" frozen_brokerage_price = frozen_brokerage_price + " + incrCount) // 负数,所以使用 + 号 @@ -90,7 +90,7 @@ public interface TradeBrokerageUserMapper extends BaseMapperX lambdaUpdateWrapper = new LambdaUpdateWrapper() .setSql(" frozen_brokerage_price = frozen_brokerage_price + " + incrCount + // 负数,所以使用 + 号 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java new file mode 100644 index 000000000..7e17d9bda --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.trade.service.brokerage.bo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 佣金 增加 Request BO + * + * @author owen + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class BrokerageAddReqBO { + + // TODO @疯狂:bo 的话,也可以考虑加下 @Validated 注解,校验下参数;防御性下哈,虽然不一定用的到 + + /** + * 业务ID + */ + private String bizId; + /** + * 佣金基数 + */ + private Integer basePrice; + /** + * 一级佣金(固定) + */ + private Integer firstBrokeragePrice; + /** + * 二级佣金(固定) + */ + private Integer secondBrokeragePrice; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/UserBrokerageSummaryBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/UserBrokerageSummaryBO.java similarity index 84% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/UserBrokerageSummaryBO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/UserBrokerageSummaryBO.java index 15f3e73fe..ffbb3ed9a 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/UserBrokerageSummaryBO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/UserBrokerageSummaryBO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.trade.service.brokerage.record.bo; +package cn.iocoder.yudao.module.trade.service.brokerage.bo; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordService.java index 477e2c76e..d02745e3b 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordService.java @@ -3,8 +3,9 @@ package cn.iocoder.yudao.module.trade.service.brokerage.record; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordPageReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.TradeBrokerageRecordDO; -import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.BrokerageAddReqBO; -import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.UserBrokerageSummaryBO; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; +import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; +import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO; import java.util.List; @@ -31,23 +32,23 @@ public interface TradeBrokerageRecordService { */ PageResult getBrokerageRecordPage(TradeBrokerageRecordPageReqVO pageReqVO); - // TODO @疯狂:是不是 bizType 得加下?方便未来拓展哈; /** * 增加佣金 * - * @param userId 会员编号 - * @param list 请求参数列表 + * @param userId 会员编号 + * @param bizType 业务类型 + * @param list 请求参数列表 */ - void addBrokerage(Long userId, List list); + void addBrokerage(Long userId, BrokerageRecordBizTypeEnum bizType, List list); - // TODO @疯狂:是不是 bizType 得加下?方便未来拓展哈; /** * 取消佣金:将佣金记录,状态修改为已失效 * - * @param userId 会员编号 - * @param bizId 业务编号 + * @param userId 会员编号 + * @param bizType 业务类型 + * @param bizId 业务编号 */ - void cancelBrokerage(Long userId, String bizId); + void cancelBrokerage(Long userId, BrokerageRecordBizTypeEnum bizType, String bizId); /** * 解冻佣金:将待结算的佣金记录,状态修改为已结算 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImpl.java index 72e85124a..01946a060 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImpl.java @@ -14,8 +14,8 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record.TradeBrokerageRecordMapper; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; -import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.BrokerageAddReqBO; -import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.UserBrokerageSummaryBO; +import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; +import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO; import cn.iocoder.yudao.module.trade.service.brokerage.user.TradeBrokerageUserService; import cn.iocoder.yudao.module.trade.service.config.TradeConfigService; import lombok.extern.slf4j.Slf4j; @@ -57,42 +57,40 @@ public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordServ return tradeBrokerageRecordMapper.selectPage(pageReqVO); } - // TODO @疯狂:buyerId 要不要统一改成 userId 哈; @Override @Transactional(rollbackFor = Exception.class) - public void addBrokerage(Long buyerId, List list) { + public void addBrokerage(Long userId, BrokerageRecordBizTypeEnum bizType, List list) { TradeConfigDO memberConfig = tradeConfigService.getTradeConfig(); // 0 未启用分销功能 - // TODO @疯狂:BooleanUtil.isFalse();逻辑里,尽量不做 !取反,这样要多思考一层; if (memberConfig == null || !BooleanUtil.isTrue(memberConfig.getBrokerageEnabled())) { - log.warn("[addBrokerage][增加佣金失败:brokerageEnabled 未配置,buyerId({})", buyerId); + log.warn("[addBrokerage][增加佣金失败:brokerageEnabled 未配置,userId({})", userId); return; } // 1.1 获得一级推广人 - TradeBrokerageUserDO firstUser = tradeBrokerageUserService.getInviteBrokerageUser(buyerId); + TradeBrokerageUserDO firstUser = tradeBrokerageUserService.getBindBrokerageUser(userId); if (firstUser == null || !BooleanUtil.isTrue(firstUser.getBrokerageEnabled())) { return; } - - // 1.2 计算一级分佣 // TODO 疯狂:类似 1.1 和 1.2 的空行,可以去掉;一般在代码里的空行,是为了逻辑分块;但是分块如果太多,就会导致代码里都是空行哈; - addBrokerage(firstUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageFirstPercent(), BrokerageAddReqBO::getSkuFirstBrokeragePrice); + // 1.2 计算一级分佣 + addBrokerage(firstUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageFirstPercent(), BrokerageAddReqBO::getFirstBrokeragePrice, bizType); // 2.1 获得二级推广员 - // TODO @疯狂:这里可以加个 firstUser.getBrokerageUserId() 为空的判断 return + if (firstUser.getBrokerageUserId() == null) { + return; + } TradeBrokerageUserDO secondUser = tradeBrokerageUserService.getBrokerageUser(firstUser.getBrokerageUserId()); if (secondUser == null || !BooleanUtil.isTrue(secondUser.getBrokerageEnabled())) { return; } - // 2.2 计算二级分佣 - addBrokerage(secondUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageSecondPercent(), BrokerageAddReqBO::getSkuSecondBrokeragePrice); + addBrokerage(secondUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageSecondPercent(), BrokerageAddReqBO::getSecondBrokeragePrice, bizType); } @Override @Transactional(rollbackFor = Exception.class) - public void cancelBrokerage(Long userId, String bizId) { - TradeBrokerageRecordDO record = tradeBrokerageRecordMapper.selectByUserIdAndBizTypeAndBizId(BrokerageRecordBizTypeEnum.ORDER.getType(), bizId); + public void cancelBrokerage(Long userId, BrokerageRecordBizTypeEnum bizType, String bizId) { + TradeBrokerageRecordDO record = tradeBrokerageRecordMapper.selectByBizTypeAndBizId(bizType.getType(), bizId); if (record == null || ObjectUtil.notEqual(record.getUserId(), userId)) { log.error("[cancelBrokerage][userId({})][bizId({}) 更新为已失效失败:记录不存在]", userId, bizId); return; @@ -114,24 +112,23 @@ public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordServ } } - // TODO @疯狂:是不是 calculateBrokeragePrice /** * 计算佣金 * - * @param payPrice 订单支付金额 - * @param percent 商品 SKU 设置的佣金 - * @param skuBrokeragePrice 商品的佣金 + * @param basePrice 佣金基数 + * @param percent 佣金比例 + * @param fixedBrokeragePrice 固定佣金 * @return 佣金 */ - int calculateBrokerage(Integer payPrice, Integer percent, Integer skuBrokeragePrice) { - // 1. 优先使用商品 SKU 设置的佣金 - if (skuBrokeragePrice != null && skuBrokeragePrice > 0) { - return ObjectUtil.defaultIfNull(skuBrokeragePrice, 0); + int calculateBrokeragePrice(Integer basePrice, Integer percent, Integer fixedBrokeragePrice) { + // 1. 优先使用固定佣金 + if (fixedBrokeragePrice != null && fixedBrokeragePrice > 0) { + return ObjectUtil.defaultIfNull(fixedBrokeragePrice, 0); } - // 2. 根据订单支付金额计算佣金 + // 2. 根据比例计算佣金 // TODO @疯狂:要不要把 MoneyUtils 抽到 common 里,然后这里也使用这个类的方法; - if (payPrice != null && payPrice > 0 && percent != null && percent > 0) { - return NumberUtil.div(NumberUtil.mul(payPrice, percent), 100, 0, RoundingMode.DOWN).intValue(); + if (basePrice != null && basePrice > 0 && percent != null && percent > 0) { + return NumberUtil.div(NumberUtil.mul(basePrice, percent), 100, 0, RoundingMode.DOWN).intValue(); } return 0; } @@ -139,32 +136,32 @@ public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordServ /** * 增加用户佣金 * - * @param user 用户 - * @param list 佣金增加参数列表 - * @param brokerageFrozenDays 冻结天数 - * @param brokeragePercent 佣金比例 - * @param skuBrokeragePriceFun 商品 SKU 设置的佣金 + * @param user 用户 + * @param list 佣金增加参数列表 + * @param brokerageFrozenDays 冻结天数 + * @param brokeragePercent 佣金比例 + * @param FixedBrokeragePriceFun 固定佣金 + * @param bizType 业务类型 */ private void addBrokerage(TradeBrokerageUserDO user, List list, Integer brokerageFrozenDays, - Integer brokeragePercent, Function skuBrokeragePriceFun) { + Integer brokeragePercent, Function FixedBrokeragePriceFun, + BrokerageRecordBizTypeEnum bizType) { // 1.1 处理冻结时间 - // TODO @疯狂:是不是 brokerageFrozenDays != null && brokerageFrozenDays > 0 ?然后计算;更简洁一点; - brokerageFrozenDays = ObjectUtil.defaultIfNull(brokerageFrozenDays, 0); LocalDateTime unfreezeTime = null; - if (brokerageFrozenDays > 0) { + if (brokerageFrozenDays != null && brokerageFrozenDays > 0) { unfreezeTime = LocalDateTime.now().plusDays(brokerageFrozenDays); } // 1.2 计算分佣 int totalBrokerage = 0; List records = new ArrayList<>(); for (BrokerageAddReqBO item : list) { - int brokeragePerItem = calculateBrokerage(item.getPayPrice(), brokeragePercent, skuBrokeragePriceFun.apply(item)); - // TODO @疯狂:其实可以 brokeragePerItem <= 0 ,continue;这样 { 层级更少;代码更简洁;} - if (brokeragePerItem > 0) { - int brokerage = brokeragePerItem * item.getCount(); - records.add(TradeBrokerageRecordConvert.INSTANCE.convert(user, item.getBizId(), brokerageFrozenDays, brokerage, unfreezeTime)); - totalBrokerage += brokerage; + int brokeragePerItem = calculateBrokeragePrice(item.getBasePrice(), brokeragePercent, FixedBrokeragePriceFun.apply(item)); + if (brokeragePerItem <= 0) { + continue; } + records.add(TradeBrokerageRecordConvert.INSTANCE.convert(user, bizType, item.getBizId(), + brokerageFrozenDays, brokeragePerItem, unfreezeTime, bizType.getTitle())); + totalBrokerage += brokeragePerItem; } if (CollUtil.isEmpty(records)) { return; @@ -173,7 +170,7 @@ public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordServ tradeBrokerageRecordMapper.insertBatch(records); // 2. 更新用户佣金 - if (brokerageFrozenDays > 0) { // 更新用户冻结佣金 + if (brokerageFrozenDays != null && brokerageFrozenDays > 0) { // 更新用户冻结佣金 tradeBrokerageUserService.updateUserFrozenBrokeragePrice(user.getId(), totalBrokerage); } else { // 更新用户可用佣金 tradeBrokerageUserService.updateUserBrokeragePrice(user.getId(), totalBrokerage); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/BrokerageAddReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/BrokerageAddReqBO.java deleted file mode 100644 index d325118a9..000000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/BrokerageAddReqBO.java +++ /dev/null @@ -1,43 +0,0 @@ -package cn.iocoder.yudao.module.trade.service.brokerage.record.bo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -// TODO @疯狂:要不要 service 还是拍平;就是都放在 brokerage 包下,然后 bo 里面,稍微分分; -/** - * 佣金 增加 Request BO - * - * @author owen - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -public class BrokerageAddReqBO { - - // TODO @疯狂:bo 的话,也可以考虑加下 @Validated 注解,校验下参数;防御性下哈,虽然不一定用的到 - - /** - * 业务ID - */ - private String bizId; - // TODO @疯狂:不需要 payPrice 和 count,计算成 price 就好啦; - /** - * 商品支付价格 - */ - private Integer payPrice; - // TODO @疯狂:可以去掉 sku 哈,更抽象一点; - /** - * SKU 一级佣金 - */ - private Integer skuFirstBrokeragePrice; - /** - * SKU 二级佣金 - */ - private Integer skuSecondBrokeragePrice; - /** - * 购买数量 - */ - private Integer count; - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserService.java index f817890e1..c62fc1947 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserService.java @@ -61,7 +61,7 @@ public interface TradeBrokerageUserService { * @param id 用户编号 * @return 用户的推广人 */ - TradeBrokerageUserDO getInviteBrokerageUser(Long id); + TradeBrokerageUserDO getBindBrokerageUser(Long id); /** * 更新用户佣金 @@ -69,16 +69,15 @@ public interface TradeBrokerageUserService { * @param id 用户编号 * @param brokeragePrice 用户可用佣金 */ - void updateUserBrokeragePrice(Long id, int brokeragePrice); + void updateUserBrokeragePrice(Long id, Integer brokeragePrice); - // TODO @疯狂:int 类型一般不用哈;尽量都用封装类型;不差这点内存哈; /** * 更新用户冻结佣金 * * @param id 用户编号 * @param frozenBrokeragePrice 用户冻结佣金 */ - void updateUserFrozenBrokeragePrice(Long id, int frozenBrokeragePrice); + void updateUserFrozenBrokeragePrice(Long id, Integer frozenBrokeragePrice); /** * 更新用户冻结佣金(减少), 更新用户佣金(增加) @@ -86,7 +85,7 @@ public interface TradeBrokerageUserService { * @param id 用户编号 * @param frozenBrokeragePrice 减少冻结佣金(负数) */ - void updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(Long id, int frozenBrokeragePrice); + void updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(Long id, Integer frozenBrokeragePrice); /** * 获得推广用户数量(一级) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImpl.java index c6ec31b93..6851e522c 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImpl.java @@ -6,7 +6,6 @@ import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.TradeBro import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user.TradeBrokerageUserMapper; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; @@ -15,8 +14,8 @@ import java.util.List; import java.util.Optional; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.MEMBER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH; import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.BROKERAGE_USER_NOT_EXISTS; +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.USER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH; /** * 分销用户 Service 实现类 @@ -65,9 +64,8 @@ public class TradeBrokerageUserServiceImpl implements TradeBrokerageUserService } } - // TODO @疯狂:getBindBrokerageUser 会不会好点,因为统一使用 Bind 替代了 Invite @Override - public TradeBrokerageUserDO getInviteBrokerageUser(Long id) { + public TradeBrokerageUserDO getBindBrokerageUser(Long id) { return Optional.ofNullable(id) .map(this::getBrokerageUser) .map(TradeBrokerageUserDO::getBrokerageUserId) @@ -75,10 +73,8 @@ public class TradeBrokerageUserServiceImpl implements TradeBrokerageUserService .orElse(null); } - // TODO @疯狂:单个更新,不用事务哈; @Override - @Transactional(rollbackFor = Exception.class) - public void updateUserBrokeragePrice(Long id, int brokeragePrice) { + public void updateUserBrokeragePrice(Long id, Integer brokeragePrice) { if (brokeragePrice > 0) { brokerageUserMapper.updateBrokeragePriceIncr(id, brokeragePrice); } else if (brokeragePrice < 0) { @@ -86,10 +82,8 @@ public class TradeBrokerageUserServiceImpl implements TradeBrokerageUserService } } - // TODO @疯狂:单个更新,不用事务哈; @Override - @Transactional(rollbackFor = Exception.class) - public void updateUserFrozenBrokeragePrice(Long id, int frozenBrokeragePrice) { + public void updateUserFrozenBrokeragePrice(Long id, Integer frozenBrokeragePrice) { if (frozenBrokeragePrice > 0) { brokerageUserMapper.updateFrozenBrokeragePriceIncr(id, frozenBrokeragePrice); } else if (frozenBrokeragePrice < 0) { @@ -97,15 +91,12 @@ public class TradeBrokerageUserServiceImpl implements TradeBrokerageUserService } } - // TODO @疯狂:单个更新,不用事务哈; @Override - @Transactional(rollbackFor = Exception.class) - public void updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(Long id, int frozenBrokeragePrice) { + public void updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(Long id, Integer frozenBrokeragePrice) { Assert.isTrue(frozenBrokeragePrice < 0); int updateRows = brokerageUserMapper.updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(id, frozenBrokeragePrice); if (updateRows == 0) { - // TODO @疯狂:挪到 trade 这变的错误码哈; - throw exception(MEMBER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH); + throw exception(USER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index b75b7ac7c..199cfcbfd 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -12,8 +12,6 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.module.member.api.address.AddressApi; import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; -import cn.iocoder.yudao.module.trade.service.brokerage.record.TradeBrokerageRecordService; -import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.BrokerageAddReqBO; import cn.iocoder.yudao.module.member.api.level.MemberLevelApi; import cn.iocoder.yudao.module.member.api.point.MemberPointApi; import cn.iocoder.yudao.module.member.api.user.MemberUserApi; @@ -49,9 +47,12 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; import cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; import cn.iocoder.yudao.module.trade.enums.order.*; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; +import cn.iocoder.yudao.module.trade.service.brokerage.record.TradeBrokerageRecordService; +import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; import cn.iocoder.yudao.module.trade.service.cart.CartService; import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; import cn.iocoder.yudao.module.trade.service.message.TradeMessageService; @@ -370,7 +371,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { // 增加用户经验 getSelf().addUserExperienceAsync(order.getUserId(), order.getPayPrice(), order.getId()); // 增加用户佣金 - getSelf().addBrokerageAsync(order.getUserId(), order.getId()); + getSelf().addBrokerageAsync(order.getUserId(), BrokerageRecordBizTypeEnum.ORDER, order.getId()); } /** @@ -640,7 +641,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { // 扣减用户经验 getSelf().reduceUserExperienceAsync(order.getUserId(), orderRefundPrice, afterSaleId); // 更新分佣记录为已失效 - getSelf().cancelBrokerageAsync(order.getUserId(), id); + getSelf().cancelBrokerageAsync(order.getUserId(), BrokerageRecordBizTypeEnum.ORDER, id); } @Override @@ -750,16 +751,16 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @Async - protected void addBrokerageAsync(Long userId, Long orderId) { + protected void addBrokerageAsync(Long userId, BrokerageRecordBizTypeEnum bizType, Long orderId) { List orderItems = tradeOrderItemMapper.selectListByOrderId(orderId); List list = convertList(orderItems, item -> TradeOrderConvert.INSTANCE.convert(item, productSkuApi.getSku(item.getSkuId()))); - tradeBrokerageRecordService.addBrokerage(userId, list); + tradeBrokerageRecordService.addBrokerage(userId, bizType, list); } @Async - protected void cancelBrokerageAsync(Long userId, Long orderItemId) { - tradeBrokerageRecordService.cancelBrokerage(userId, String.valueOf(orderItemId)); + protected void cancelBrokerageAsync(Long userId, BrokerageRecordBizTypeEnum bizType, Long orderItemId) { + tradeBrokerageRecordService.cancelBrokerage(userId, bizType, String.valueOf(orderItemId)); } /** diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImplTest.java b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImplTest.java index 9daf3cafb..eb51279d5 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImplTest.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImplTest.java @@ -79,38 +79,38 @@ public class TradeBrokerageRecordServiceImplTest extends BaseDbUnitTest { } @Test - public void testCalculateBrokerage_useSkuBrokeragePrice() { + public void testCalculateBrokeragePrice_useFixedBrokeragePrice() { // mock 数据 Integer payPrice = randomInteger(); Integer percent = randomInt(1, 101); - Integer skuBrokeragePrice = randomInt(); + Integer fixedBrokeragePrice = randomInt(); // 调用 - int brokerage = tradeBrokerageRecordService.calculateBrokerage(payPrice, percent, skuBrokeragePrice); + int brokerage = tradeBrokerageRecordService.calculateBrokeragePrice(payPrice, percent, fixedBrokeragePrice); // 断言 - assertEquals(brokerage, skuBrokeragePrice); + assertEquals(brokerage, fixedBrokeragePrice); } @Test - public void testCalculateBrokerage_usePercent() { + public void testCalculateBrokeragePrice_usePercent() { // mock 数据 Integer payPrice = randomInteger(); Integer percent = randomInt(1, 101); Integer skuBrokeragePrice = randomEle(new Integer[]{0, null}); System.out.println("skuBrokeragePrice=" + skuBrokeragePrice); // 调用 - int brokerage = tradeBrokerageRecordService.calculateBrokerage(payPrice, percent, skuBrokeragePrice); + int brokerage = tradeBrokerageRecordService.calculateBrokeragePrice(payPrice, percent, skuBrokeragePrice); // 断言 assertEquals(brokerage, NumberUtil.div(NumberUtil.mul(payPrice, percent), 100, 0, RoundingMode.DOWN).intValue()); } @Test - public void testCalculateBrokerage_equalsZero() { + public void testCalculateBrokeragePrice_equalsZero() { // mock 数据 Integer payPrice = null; Integer percent = null; Integer skuBrokeragePrice = null; // 调用 - int brokerage = tradeBrokerageRecordService.calculateBrokerage(payPrice, percent, skuBrokeragePrice); + int brokerage = tradeBrokerageRecordService.calculateBrokeragePrice(payPrice, percent, skuBrokeragePrice); // 断言 assertEquals(brokerage, 0); } diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java index dc7a58770..cf375f4e4 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java @@ -13,7 +13,6 @@ public interface ErrorCodeConstants { ErrorCode USER_NOT_EXISTS = new ErrorCode(1004001000, "用户不存在"); ErrorCode USER_MOBILE_NOT_EXISTS = new ErrorCode(1004001001, "手机号未注册用户"); ErrorCode USER_MOBILE_USED = new ErrorCode(1004001002, "修改手机失败,该手机号({})已经被使用"); - ErrorCode MEMBER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH = new ErrorCode(1004001003, "用户冻结佣金({})数量不足"); // ========== AUTH 模块 1004003000 ========== ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1004003000, "登录失败,账号密码不正确"); From ddcebb1986c7c11457fb7f93fd142e4af3495e13 Mon Sep 17 00:00:00 2001 From: owen Date: Fri, 8 Sep 2023 12:46:43 +0800 Subject: [PATCH 29/50] =?UTF-8?q?common:=20MoneyUtils=20=E7=A7=BB=E5=88=B0?= =?UTF-8?q?=20common=20=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/common/util/number}/MoneyUtils.java | 13 ++++++++++++- .../record/TradeBrokerageRecordServiceImpl.java | 6 ++---- .../pay/service/order/PayOrderServiceImpl.java | 2 +- 3 files changed, 15 insertions(+), 6 deletions(-) rename {yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/util => yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number}/MoneyUtils.java (71%) diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/util/MoneyUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/MoneyUtils.java similarity index 71% rename from yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/util/MoneyUtils.java rename to yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/MoneyUtils.java index 5e5d859e6..e2fd3fa6e 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/util/MoneyUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/MoneyUtils.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.pay.util; +package cn.iocoder.yudao.framework.common.util.number; import cn.hutool.core.util.NumberUtil; @@ -23,6 +23,17 @@ public class MoneyUtils { return calculateRatePrice(price, rate, 0, RoundingMode.HALF_UP).intValue(); } + /** + * 计算百分比金额,向下传入 + * + * @param price 金额 + * @param rate 百分比,例如说 56.77% 则传入 56.77 + * @return 百分比金额 + */ + public static Integer calculateRatePriceFloor(Integer price, Double rate) { + return calculateRatePrice(price, rate, 0, RoundingMode.FLOOR).intValue(); + } + /** * 计算百分比金额 * diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImpl.java index 01946a060..ad1a5c8ff 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImpl.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.trade.service.brokerage.record; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.BooleanUtil; -import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordPageReqVO; import cn.iocoder.yudao.module.trade.convert.brokerage.record.TradeBrokerageRecordConvert; import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.TradeBrokerageRecordDO; @@ -24,7 +24,6 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import java.math.RoundingMode; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -126,9 +125,8 @@ public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordServ return ObjectUtil.defaultIfNull(fixedBrokeragePrice, 0); } // 2. 根据比例计算佣金 - // TODO @疯狂:要不要把 MoneyUtils 抽到 common 里,然后这里也使用这个类的方法; if (basePrice != null && basePrice > 0 && percent != null && percent > 0) { - return NumberUtil.div(NumberUtil.mul(basePrice, percent), 100, 0, RoundingMode.DOWN).intValue(); + return MoneyUtils.calculateRatePriceFloor(basePrice, Double.valueOf(percent)); } return 0; } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java index 944df1a10..0445df8a6 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java @@ -6,6 +6,7 @@ import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; import cn.iocoder.yudao.framework.pay.core.client.PayClient; import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; @@ -31,7 +32,6 @@ import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties; import cn.iocoder.yudao.module.pay.service.app.PayAppService; import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; -import cn.iocoder.yudao.module.pay.util.MoneyUtils; import com.google.common.annotations.VisibleForTesting; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; From 0a0c3c0ede6eec2266507684759784d8ad803a31 Mon Sep 17 00:00:00 2001 From: owen Date: Fri, 8 Sep 2023 12:56:34 +0800 Subject: [PATCH 30/50] =?UTF-8?q?trade:=20=E5=88=86=E9=94=80=E4=B8=9A?= =?UTF-8?q?=E5=8A=A1=E7=9B=B8=E5=85=B3=E7=B1=BB=E5=9E=8B=E7=A7=BB=E9=99=A4?= =?UTF-8?q?Trade=E5=89=8D=E7=BC=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...er.java => BrokerageRecordController.java} | 26 +++---- ...BaseVO.java => BrokerageRecordBaseVO.java} | 2 +- ...qVO.java => BrokerageRecordPageReqVO.java} | 2 +- ...RespVO.java => BrokerageRecordRespVO.java} | 2 +- ...ller.java => BrokerageUserController.java} | 34 +++++----- ...erBaseVO.java => BrokerageUserBaseVO.java} | 2 +- ...BrokerageUserClearBrokerageUserReqVO.java} | 2 +- ...ReqVO.java => BrokerageUserPageReqVO.java} | 2 +- ...erRespVO.java => BrokerageUserRespVO.java} | 2 +- ...erageUserUpdateBrokerageEnabledReqVO.java} | 2 +- ...rokerageUserUpdateBrokerageUserReqVO.java} | 2 +- ...nvert.java => BrokerageRecordConvert.java} | 24 +++---- ...Convert.java => BrokerageUserConvert.java} | 26 +++---- ...geRecordDO.java => BrokerageRecordDO.java} | 2 +- ...kerageUserDO.java => BrokerageUserDO.java} | 2 +- .../record/BrokerageRecordMapper.java | 55 +++++++++++++++ .../record/TradeBrokerageRecordMapper.java | 55 --------------- ...erMapper.java => BrokerageUserMapper.java} | 40 +++++------ ...b.java => BrokerageRecordUnfreezeJob.java} | 8 +-- ...rvice.java => BrokerageRecordService.java} | 10 +-- ...l.java => BrokerageRecordServiceImpl.java} | 68 +++++++++---------- ...Service.java => BrokerageUserService.java} | 15 ++-- ...mpl.java => BrokerageUserServiceImpl.java} | 22 +++--- .../order/TradeOrderUpdateServiceImpl.java | 8 +-- ...va => BrokerageRecordServiceImplTest.java} | 42 ++++++------ ...java => BrokerageUserServiceImplTest.java} | 22 +++--- 26 files changed, 238 insertions(+), 239 deletions(-) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/{TradeBrokerageRecordController.java => BrokerageRecordController.java} (59%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/{TradeBrokerageRecordBaseVO.java => BrokerageRecordBaseVO.java} (98%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/{TradeBrokerageRecordPageReqVO.java => BrokerageRecordPageReqVO.java} (94%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/{TradeBrokerageRecordRespVO.java => BrokerageRecordRespVO.java} (89%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/{TradeBrokerageUserController.java => BrokerageUserController.java} (73%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/{TradeBrokerageUserBaseVO.java => BrokerageUserBaseVO.java} (97%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/{TradeBrokerageUserClearBrokerageUserReqVO.java => BrokerageUserClearBrokerageUserReqVO.java} (90%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/{TradeBrokerageUserPageReqVO.java => BrokerageUserPageReqVO.java} (93%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/{TradeBrokerageUserRespVO.java => BrokerageUserRespVO.java} (95%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/{TradeBrokerageUserUpdateBrokerageEnabledReqVO.java => BrokerageUserUpdateBrokerageEnabledReqVO.java} (92%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/{TradeBrokerageUserUpdateBrokerageUserReqVO.java => BrokerageUserUpdateBrokerageUserReqVO.java} (92%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/{TradeBrokerageRecordConvert.java => BrokerageRecordConvert.java} (65%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/{TradeBrokerageUserConvert.java => BrokerageUserConvert.java} (62%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/{TradeBrokerageRecordDO.java => BrokerageRecordDO.java} (97%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/{TradeBrokerageUserDO.java => BrokerageUserDO.java} (96%) create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/BrokerageRecordMapper.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/TradeBrokerageRecordMapper.java rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/{TradeBrokerageUserMapper.java => BrokerageUserMapper.java} (65%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/brokerage/{TradeBrokerageRecordUnfreezeJob.java => BrokerageRecordUnfreezeJob.java} (63%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/{TradeBrokerageRecordService.java => BrokerageRecordService.java} (86%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/{TradeBrokerageRecordServiceImpl.java => BrokerageRecordServiceImpl.java} (72%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/{TradeBrokerageUserService.java => BrokerageUserService.java} (78%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/{TradeBrokerageUserServiceImpl.java => BrokerageUserServiceImpl.java} (80%) rename yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/{TradeBrokerageRecordServiceImplTest.java => BrokerageRecordServiceImplTest.java} (67%) rename yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/{TradeBrokerageUserServiceImplTest.java => BrokerageUserServiceImplTest.java} (74%) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/TradeBrokerageRecordController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/BrokerageRecordController.java similarity index 59% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/TradeBrokerageRecordController.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/BrokerageRecordController.java index 38b2f4d71..81034124b 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/TradeBrokerageRecordController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/BrokerageRecordController.java @@ -2,11 +2,11 @@ package cn.iocoder.yudao.module.trade.controller.admin.brokerage.record; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordPageReqVO; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordRespVO; -import cn.iocoder.yudao.module.trade.convert.brokerage.record.TradeBrokerageRecordConvert; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.TradeBrokerageRecordDO; -import cn.iocoder.yudao.module.trade.service.brokerage.record.TradeBrokerageRecordService; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordPageReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordRespVO; +import cn.iocoder.yudao.module.trade.convert.brokerage.record.BrokerageRecordConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.BrokerageRecordDO; +import cn.iocoder.yudao.module.trade.service.brokerage.record.BrokerageRecordService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -26,26 +26,26 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @RestController @RequestMapping("/trade/brokerage-record") @Validated -public class TradeBrokerageRecordController { +public class BrokerageRecordController { @Resource - private TradeBrokerageRecordService tradeBrokerageRecordService; + private BrokerageRecordService brokerageRecordService; @GetMapping("/get") @Operation(summary = "获得佣金记录") @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('trade:brokerage-record:query')") - public CommonResult getBrokerageRecord(@RequestParam("id") Integer id) { - TradeBrokerageRecordDO tradeBrokerageRecord = tradeBrokerageRecordService.getBrokerageRecord(id); - return success(TradeBrokerageRecordConvert.INSTANCE.convert(tradeBrokerageRecord)); + public CommonResult getBrokerageRecord(@RequestParam("id") Integer id) { + BrokerageRecordDO brokerageRecord = brokerageRecordService.getBrokerageRecord(id); + return success(BrokerageRecordConvert.INSTANCE.convert(brokerageRecord)); } @GetMapping("/page") @Operation(summary = "获得佣金记录分页") @PreAuthorize("@ss.hasPermission('trade:brokerage-record:query')") - public CommonResult> getBrokerageRecordPage(@Valid TradeBrokerageRecordPageReqVO pageVO) { - PageResult pageResult = tradeBrokerageRecordService.getBrokerageRecordPage(pageVO); - return success(TradeBrokerageRecordConvert.INSTANCE.convertPage(pageResult)); + public CommonResult> getBrokerageRecordPage(@Valid BrokerageRecordPageReqVO pageVO) { + PageResult pageResult = brokerageRecordService.getBrokerageRecordPage(pageVO); + return success(BrokerageRecordConvert.INSTANCE.convertPage(pageResult)); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordBaseVO.java similarity index 98% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordBaseVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordBaseVO.java index f15d07706..cce84a804 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordBaseVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordBaseVO.java @@ -15,7 +15,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class TradeBrokerageRecordBaseVO { +public class BrokerageRecordBaseVO { @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25973") @NotNull(message = "用户编号不能为空") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordPageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordPageReqVO.java similarity index 94% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordPageReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordPageReqVO.java index abd948f09..533fbd2ca 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordPageReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordPageReqVO.java @@ -15,7 +15,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class TradeBrokerageRecordPageReqVO extends PageParam { +public class BrokerageRecordPageReqVO extends PageParam { @Schema(description = "用户编号", example = "25973") private Long userId; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordRespVO.java similarity index 89% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordRespVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordRespVO.java index 724d7d3e5..aead00a08 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordRespVO.java @@ -11,7 +11,7 @@ import java.time.LocalDateTime; @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class TradeBrokerageRecordRespVO extends TradeBrokerageRecordBaseVO { +public class BrokerageRecordRespVO extends BrokerageRecordBaseVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28896") private Integer id; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/TradeBrokerageUserController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java similarity index 73% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/TradeBrokerageUserController.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java index 38a27d8c8..b6c9a1c84 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/TradeBrokerageUserController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java @@ -5,13 +5,13 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.member.api.user.MemberUserApi; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.*; -import cn.iocoder.yudao.module.trade.convert.brokerage.user.TradeBrokerageUserConvert; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; +import cn.iocoder.yudao.module.trade.convert.brokerage.user.BrokerageUserConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; -import cn.iocoder.yudao.module.trade.service.brokerage.record.TradeBrokerageRecordService; +import cn.iocoder.yudao.module.trade.service.brokerage.record.BrokerageRecordService; import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO; -import cn.iocoder.yudao.module.trade.service.brokerage.user.TradeBrokerageUserService; +import cn.iocoder.yudao.module.trade.service.brokerage.user.BrokerageUserService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -32,12 +32,12 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. @RestController @RequestMapping("/trade/brokerage-user") @Validated -public class TradeBrokerageUserController { +public class BrokerageUserController { @Resource - private TradeBrokerageUserService brokerageUserService; + private BrokerageUserService brokerageUserService; @Resource - private TradeBrokerageRecordService brokerageRecordService; + private BrokerageRecordService brokerageRecordService; @Resource private MemberUserApi memberUserApi; @@ -45,7 +45,7 @@ public class TradeBrokerageUserController { @PutMapping("/update-brokerage-user") @Operation(summary = "修改推广员") @PreAuthorize("@ss.hasPermission('trade:brokerage-user:update-brokerage-user')") - public CommonResult updateBrokerageUser(@Valid @RequestBody TradeBrokerageUserUpdateBrokerageUserReqVO updateReqVO) { + public CommonResult updateBrokerageUser(@Valid @RequestBody BrokerageUserUpdateBrokerageUserReqVO updateReqVO) { brokerageUserService.updateBrokerageUserId(updateReqVO.getId(), updateReqVO.getBrokerageUserId()); return success(true); } @@ -53,7 +53,7 @@ public class TradeBrokerageUserController { @PutMapping("/clear-brokerage-user") @Operation(summary = "清除推广员") @PreAuthorize("@ss.hasPermission('trade:brokerage-user:clear-brokerage-user')") - public CommonResult clearBrokerageUser(@Valid @RequestBody TradeBrokerageUserClearBrokerageUserReqVO updateReqVO) { + public CommonResult clearBrokerageUser(@Valid @RequestBody BrokerageUserClearBrokerageUserReqVO updateReqVO) { brokerageUserService.updateBrokerageUserId(updateReqVO.getId(), null); return success(true); } @@ -61,7 +61,7 @@ public class TradeBrokerageUserController { @PutMapping("/update-brokerage-enable") @Operation(summary = "修改推广资格") @PreAuthorize("@ss.hasPermission('trade:brokerage-user:update-brokerage-enable')") - public CommonResult updateBrokerageEnabled(@Valid @RequestBody TradeBrokerageUserUpdateBrokerageEnabledReqVO updateReqVO) { + public CommonResult updateBrokerageEnabled(@Valid @RequestBody BrokerageUserUpdateBrokerageEnabledReqVO updateReqVO) { brokerageUserService.updateBrokerageEnabled(updateReqVO.getId(), updateReqVO.getBrokerageEnabled()); return success(true); } @@ -70,20 +70,20 @@ public class TradeBrokerageUserController { @Operation(summary = "获得分销用户") @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('trade:brokerage-user:query')") - public CommonResult getBrokerageUser(@RequestParam("id") Long id) { - TradeBrokerageUserDO brokerageUser = brokerageUserService.getBrokerageUser(id); - return success(TradeBrokerageUserConvert.INSTANCE.convert(brokerageUser)); + public CommonResult getBrokerageUser(@RequestParam("id") Long id) { + BrokerageUserDO brokerageUser = brokerageUserService.getBrokerageUser(id); + return success(BrokerageUserConvert.INSTANCE.convert(brokerageUser)); } @GetMapping("/page") @Operation(summary = "获得分销用户分页") @PreAuthorize("@ss.hasPermission('trade:brokerage-user:query')") - public CommonResult> getBrokerageUserPage(@Valid TradeBrokerageUserPageReqVO pageVO) { + public CommonResult> getBrokerageUserPage(@Valid BrokerageUserPageReqVO pageVO) { // 分页查询 - PageResult pageResult = brokerageUserService.getBrokerageUserPage(pageVO); + PageResult pageResult = brokerageUserService.getBrokerageUserPage(pageVO); // 涉及到的用户 - Set userIds = convertSet(pageResult.getList(), TradeBrokerageUserDO::getId); + Set userIds = convertSet(pageResult.getList(), BrokerageUserDO::getId); // 查询用户信息 Map userMap = memberUserApi.getUserMap(userIds); // 合计分佣订单 @@ -98,7 +98,7 @@ public class TradeBrokerageUserController { // todo 合计提现 - return success(TradeBrokerageUserConvert.INSTANCE.convertPage(pageResult, userMap, brokerageUserCountMap, userOrderSummaryMap)); + return success(BrokerageUserConvert.INSTANCE.convertPage(pageResult, userMap, brokerageUserCountMap, userOrderSummaryMap)); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserBaseVO.java similarity index 97% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserBaseVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserBaseVO.java index d75e6a1b1..41ddd454c 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserBaseVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserBaseVO.java @@ -14,7 +14,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class TradeBrokerageUserBaseVO { +public class BrokerageUserBaseVO { @Schema(description = "推广员编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4587") @NotNull(message = "推广员编号不能为空") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserClearBrokerageUserReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserClearBrokerageUserReqVO.java similarity index 90% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserClearBrokerageUserReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserClearBrokerageUserReqVO.java index 18a5a5e85..edb0102a0 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserClearBrokerageUserReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserClearBrokerageUserReqVO.java @@ -9,7 +9,7 @@ import javax.validation.constraints.NotNull; @Schema(description = "管理后台 - 分销用户 - 清除推广员 Request VO") @Data @ToString(callSuper = true) -public class TradeBrokerageUserClearBrokerageUserReqVO { +public class BrokerageUserClearBrokerageUserReqVO { @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019") @NotNull(message = "用户编号不能为空") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserPageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserPageReqVO.java similarity index 93% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserPageReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserPageReqVO.java index ec63775d3..2b99d686e 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserPageReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserPageReqVO.java @@ -15,7 +15,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class TradeBrokerageUserPageReqVO extends PageParam { +public class BrokerageUserPageReqVO extends PageParam { @Schema(description = "推广员编号", example = "4587") private Long brokerageUserId; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserRespVO.java similarity index 95% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserRespVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserRespVO.java index ee82efa0d..c353b4614 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserRespVO.java @@ -11,7 +11,7 @@ import java.time.LocalDateTime; @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class TradeBrokerageUserRespVO extends TradeBrokerageUserBaseVO { +public class BrokerageUserRespVO extends BrokerageUserBaseVO { @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019") private Long id; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserUpdateBrokerageEnabledReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserUpdateBrokerageEnabledReqVO.java similarity index 92% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserUpdateBrokerageEnabledReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserUpdateBrokerageEnabledReqVO.java index 1fd38b028..5e6d920be 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserUpdateBrokerageEnabledReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserUpdateBrokerageEnabledReqVO.java @@ -9,7 +9,7 @@ import javax.validation.constraints.NotNull; @Schema(description = "管理后台 - 分销用户 - 修改推广员 Request VO") @Data @ToString(callSuper = true) -public class TradeBrokerageUserUpdateBrokerageEnabledReqVO { +public class BrokerageUserUpdateBrokerageEnabledReqVO { @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019") @NotNull(message = "用户编号不能为空") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserUpdateBrokerageUserReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserUpdateBrokerageUserReqVO.java similarity index 92% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserUpdateBrokerageUserReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserUpdateBrokerageUserReqVO.java index 28ea301c1..c6c72999d 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserUpdateBrokerageUserReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserUpdateBrokerageUserReqVO.java @@ -9,7 +9,7 @@ import javax.validation.constraints.NotNull; @Schema(description = "管理后台 - 分销用户 - 修改推广员 Request VO") @Data @ToString(callSuper = true) -public class TradeBrokerageUserUpdateBrokerageUserReqVO { +public class BrokerageUserUpdateBrokerageUserReqVO { @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019") @NotNull(message = "用户编号不能为空") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/TradeBrokerageRecordConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java similarity index 65% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/TradeBrokerageRecordConvert.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java index 2d67f5f2e..d619c6926 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/TradeBrokerageRecordConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java @@ -3,9 +3,9 @@ package cn.iocoder.yudao.module.trade.convert.brokerage.record; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordRespVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.TradeBrokerageRecordDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordRespVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.BrokerageRecordDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; import org.mapstruct.Mapper; @@ -20,25 +20,25 @@ import java.util.List; * @author owen */ @Mapper -public interface TradeBrokerageRecordConvert { +public interface BrokerageRecordConvert { - TradeBrokerageRecordConvert INSTANCE = Mappers.getMapper(TradeBrokerageRecordConvert.class); + BrokerageRecordConvert INSTANCE = Mappers.getMapper(BrokerageRecordConvert.class); - TradeBrokerageRecordRespVO convert(TradeBrokerageRecordDO bean); + BrokerageRecordRespVO convert(BrokerageRecordDO bean); - List convertList(List list); + List convertList(List list); - PageResult convertPage(PageResult page); + PageResult convertPage(PageResult page); - default TradeBrokerageRecordDO convert(TradeBrokerageUserDO user, BrokerageRecordBizTypeEnum bizType, String bizId, - Integer brokerageFrozenDays, int brokerage, LocalDateTime unfreezeTime, - String title) { + default BrokerageRecordDO convert(BrokerageUserDO user, BrokerageRecordBizTypeEnum bizType, String bizId, + Integer brokerageFrozenDays, int brokerage, LocalDateTime unfreezeTime, + String title) { brokerageFrozenDays = ObjectUtil.defaultIfNull(brokerageFrozenDays, 0); // 不冻结时,佣金直接就是结算状态 Integer status = brokerageFrozenDays > 0 ? BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus() : BrokerageRecordStatusEnum.SETTLEMENT.getStatus(); - return new TradeBrokerageRecordDO() + return new BrokerageRecordDO() .setUserId(user.getId()) .setBizType(bizType.getType()) .setBizId(bizId) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/TradeBrokerageUserConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/BrokerageUserConvert.java similarity index 62% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/TradeBrokerageUserConvert.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/BrokerageUserConvert.java index beda1571c..c4a31cc98 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/TradeBrokerageUserConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/BrokerageUserConvert.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.trade.convert.brokerage.user; import cn.hutool.core.map.MapUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.TradeBrokerageUserRespVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.BrokerageUserRespVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO; import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -19,22 +19,22 @@ import java.util.Optional; * @author owen */ @Mapper -public interface TradeBrokerageUserConvert { +public interface BrokerageUserConvert { - TradeBrokerageUserConvert INSTANCE = Mappers.getMapper(TradeBrokerageUserConvert.class); + BrokerageUserConvert INSTANCE = Mappers.getMapper(BrokerageUserConvert.class); - TradeBrokerageUserRespVO convert(TradeBrokerageUserDO bean); + BrokerageUserRespVO convert(BrokerageUserDO bean); - List convertList(List list); + List convertList(List list); - PageResult convertPage(PageResult page); + PageResult convertPage(PageResult page); - default PageResult convertPage(PageResult pageResult, - Map userMap, - Map brokerageUserCountMap, - Map userOrderSummaryMap) { - PageResult result = convertPage(pageResult); - for (TradeBrokerageUserRespVO vo : result.getList()) { + default PageResult convertPage(PageResult pageResult, + Map userMap, + Map brokerageUserCountMap, + Map userOrderSummaryMap) { + PageResult result = convertPage(pageResult); + for (BrokerageUserRespVO vo : result.getList()) { // 用户信息 Optional.ofNullable(userMap.get(vo.getId())) .ifPresent(user -> { diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/TradeBrokerageRecordDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/BrokerageRecordDO.java similarity index 97% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/TradeBrokerageRecordDO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/BrokerageRecordDO.java index bb3f09c52..be69c6075 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/TradeBrokerageRecordDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/BrokerageRecordDO.java @@ -23,7 +23,7 @@ import java.time.LocalDateTime; @Builder @NoArgsConstructor @AllArgsConstructor -public class TradeBrokerageRecordDO extends BaseDO { +public class BrokerageRecordDO extends BaseDO { /** * 编号 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/TradeBrokerageUserDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/BrokerageUserDO.java similarity index 96% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/TradeBrokerageUserDO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/BrokerageUserDO.java index 3f1cc73aa..4b85dc3d0 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/TradeBrokerageUserDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/BrokerageUserDO.java @@ -22,7 +22,7 @@ import java.time.LocalDateTime; @Builder @NoArgsConstructor @AllArgsConstructor -public class TradeBrokerageUserDO extends BaseDO { +public class BrokerageUserDO extends BaseDO { /** * 用户编号 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/BrokerageRecordMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/BrokerageRecordMapper.java new file mode 100644 index 000000000..9f9aae824 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/BrokerageRecordMapper.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.BrokerageRecordDO; +import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 佣金记录 Mapper + * + * @author owen + */ +@Mapper +public interface BrokerageRecordMapper extends BaseMapperX { + + default PageResult selectPage(BrokerageRecordPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(BrokerageRecordDO::getUserId, reqVO.getUserId()) + .eqIfPresent(BrokerageRecordDO::getBizType, reqVO.getBizType()) + .eqIfPresent(BrokerageRecordDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(BrokerageRecordDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(BrokerageRecordDO::getId)); + } + + default List selectListByStatusAndUnfreezeTimeLt(Integer status, LocalDateTime unfreezeTime) { + return selectList(new LambdaQueryWrapper() + .eq(BrokerageRecordDO::getStatus, status) + .lt(BrokerageRecordDO::getUnfreezeTime, unfreezeTime)); + } + + default int updateByIdAndStatus(Integer id, Integer status, BrokerageRecordDO updateObj) { + return update(updateObj, new LambdaQueryWrapper() + .eq(BrokerageRecordDO::getId, id) + .eq(BrokerageRecordDO::getStatus, status)); + } + + default BrokerageRecordDO selectByBizTypeAndBizId(Integer bizType, String bizId) { + return selectOne(BrokerageRecordDO::getBizType, bizType, + BrokerageRecordDO::getBizId, bizId); + } + + @Select("select count(1), sum(price) from trade_brokerage_record where user_id = #{userId} and biz_type = #{bizType} and status = #{status}") + UserBrokerageSummaryBO selectCountAndSumPriceByUserIdAndBizTypeAndStatus(@Param("userId") Long userId, + @Param("bizType") Integer bizType, + @Param("status") Integer status); +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/TradeBrokerageRecordMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/TradeBrokerageRecordMapper.java deleted file mode 100644 index 9a8c6df76..000000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/TradeBrokerageRecordMapper.java +++ /dev/null @@ -1,55 +0,0 @@ -package cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordPageReqVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.TradeBrokerageRecordDO; -import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * 佣金记录 Mapper - * - * @author owen - */ -@Mapper -public interface TradeBrokerageRecordMapper extends BaseMapperX { - - default PageResult selectPage(TradeBrokerageRecordPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(TradeBrokerageRecordDO::getUserId, reqVO.getUserId()) - .eqIfPresent(TradeBrokerageRecordDO::getBizType, reqVO.getBizType()) - .eqIfPresent(TradeBrokerageRecordDO::getStatus, reqVO.getStatus()) - .betweenIfPresent(TradeBrokerageRecordDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(TradeBrokerageRecordDO::getId)); - } - - default List selectListByStatusAndUnfreezeTimeLt(Integer status, LocalDateTime unfreezeTime) { - return selectList(new LambdaQueryWrapper() - .eq(TradeBrokerageRecordDO::getStatus, status) - .lt(TradeBrokerageRecordDO::getUnfreezeTime, unfreezeTime)); - } - - default int updateByIdAndStatus(Integer id, Integer status, TradeBrokerageRecordDO updateObj) { - return update(updateObj, new LambdaQueryWrapper() - .eq(TradeBrokerageRecordDO::getId, id) - .eq(TradeBrokerageRecordDO::getStatus, status)); - } - - default TradeBrokerageRecordDO selectByBizTypeAndBizId(Integer bizType, String bizId) { - return selectOne(TradeBrokerageRecordDO::getBizType, bizType, - TradeBrokerageRecordDO::getBizId, bizId); - } - - @Select("select count(1), sum(price) from trade_brokerage_record where user_id = #{userId} and biz_type = #{bizType} and status = #{status}") - UserBrokerageSummaryBO selectCountAndSumPriceByUserIdAndBizTypeAndStatus(@Param("userId") Long userId, - @Param("bizType") Integer bizType, - @Param("status") Integer status); -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/TradeBrokerageUserMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java similarity index 65% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/TradeBrokerageUserMapper.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java index de163eb59..d5cc39523 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/TradeBrokerageUserMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java @@ -4,8 +4,8 @@ import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.TradeBrokerageUserPageReqVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.BrokerageUserPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; @@ -15,14 +15,14 @@ import org.apache.ibatis.annotations.Mapper; * @author owen */ @Mapper -public interface TradeBrokerageUserMapper extends BaseMapperX { +public interface BrokerageUserMapper extends BaseMapperX { - default PageResult selectPage(TradeBrokerageUserPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(TradeBrokerageUserDO::getBrokerageUserId, reqVO.getBrokerageUserId()) - .eqIfPresent(TradeBrokerageUserDO::getBrokerageEnabled, reqVO.getBrokerageEnabled()) - .betweenIfPresent(TradeBrokerageUserDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(TradeBrokerageUserDO::getId)); + default PageResult selectPage(BrokerageUserPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(BrokerageUserDO::getBrokerageUserId, reqVO.getBrokerageUserId()) + .eqIfPresent(BrokerageUserDO::getBrokerageEnabled, reqVO.getBrokerageEnabled()) + .betweenIfPresent(BrokerageUserDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(BrokerageUserDO::getId)); } /** @@ -33,9 +33,9 @@ public interface TradeBrokerageUserMapper extends BaseMapperX 0); - LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() .setSql(" brokerage_price = brokerage_price + " + incrCount) - .eq(TradeBrokerageUserDO::getId, id); + .eq(BrokerageUserDO::getId, id); update(null, lambdaUpdateWrapper); } @@ -48,9 +48,9 @@ public interface TradeBrokerageUserMapper extends BaseMapperX lambdaUpdateWrapper = new LambdaUpdateWrapper() + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() .setSql(" brokerage_price = brokerage_price + " + incrCount) // 负数,所以使用 + 号 - .eq(TradeBrokerageUserDO::getId, id); + .eq(BrokerageUserDO::getId, id); update(null, lambdaUpdateWrapper); } @@ -62,9 +62,9 @@ public interface TradeBrokerageUserMapper extends BaseMapperX 0); - LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() .setSql(" frozen_brokerage_price = frozen_brokerage_price + " + incrCount) - .eq(TradeBrokerageUserDO::getId, id); + .eq(BrokerageUserDO::getId, id); update(null, lambdaUpdateWrapper); } @@ -77,9 +77,9 @@ public interface TradeBrokerageUserMapper extends BaseMapperX lambdaUpdateWrapper = new LambdaUpdateWrapper() + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() .setSql(" frozen_brokerage_price = frozen_brokerage_price + " + incrCount) // 负数,所以使用 + 号 - .eq(TradeBrokerageUserDO::getId, id); + .eq(BrokerageUserDO::getId, id); update(null, lambdaUpdateWrapper); } @@ -92,11 +92,11 @@ public interface TradeBrokerageUserMapper extends BaseMapperX lambdaUpdateWrapper = new LambdaUpdateWrapper() + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() .setSql(" frozen_brokerage_price = frozen_brokerage_price + " + incrCount + // 负数,所以使用 + 号 ", brokerage_price = brokerage_price + " + -incrCount) // 负数,所以使用 - 号 - .eq(TradeBrokerageUserDO::getId, id) - .ge(TradeBrokerageUserDO::getFrozenBrokeragePrice, -incrCount); // cas 逻辑 + .eq(BrokerageUserDO::getId, id) + .ge(BrokerageUserDO::getFrozenBrokeragePrice, -incrCount); // cas 逻辑 return update(null, lambdaUpdateWrapper); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/brokerage/TradeBrokerageRecordUnfreezeJob.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/brokerage/BrokerageRecordUnfreezeJob.java similarity index 63% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/brokerage/TradeBrokerageRecordUnfreezeJob.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/brokerage/BrokerageRecordUnfreezeJob.java index 94218d47e..c221408e5 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/brokerage/TradeBrokerageRecordUnfreezeJob.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/brokerage/BrokerageRecordUnfreezeJob.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.trade.job.brokerage; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; -import cn.iocoder.yudao.module.trade.service.brokerage.record.TradeBrokerageRecordService; +import cn.iocoder.yudao.module.trade.service.brokerage.record.BrokerageRecordService; import org.springframework.stereotype.Component; import javax.annotation.Resource; @@ -15,14 +15,14 @@ import javax.annotation.Resource; */ @Component @TenantJob -public class TradeBrokerageRecordUnfreezeJob implements JobHandler { +public class BrokerageRecordUnfreezeJob implements JobHandler { @Resource - private TradeBrokerageRecordService tradeBrokerageRecordService; + private BrokerageRecordService brokerageRecordService; @Override public String execute(String param) { - int count = tradeBrokerageRecordService.unfreezeRecord(); + int count = brokerageRecordService.unfreezeRecord(); return StrUtil.format("解冻佣金 {} 个", count); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordService.java similarity index 86% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordService.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordService.java index d02745e3b..f0cadd761 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordService.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.trade.service.brokerage.record; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordPageReqVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.TradeBrokerageRecordDO; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.BrokerageRecordDO; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO; @@ -14,7 +14,7 @@ import java.util.List; * * @author owen */ -public interface TradeBrokerageRecordService { +public interface BrokerageRecordService { /** * 获得佣金记录 @@ -22,7 +22,7 @@ public interface TradeBrokerageRecordService { * @param id 编号 * @return 佣金记录 */ - TradeBrokerageRecordDO getBrokerageRecord(Integer id); + BrokerageRecordDO getBrokerageRecord(Integer id); /** * 获得佣金记录分页 @@ -30,7 +30,7 @@ public interface TradeBrokerageRecordService { * @param pageReqVO 分页查询 * @return 佣金记录分页 */ - PageResult getBrokerageRecordPage(TradeBrokerageRecordPageReqVO pageReqVO); + PageResult getBrokerageRecordPage(BrokerageRecordPageReqVO pageReqVO); /** * 增加佣金 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java similarity index 72% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImpl.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java index ad1a5c8ff..ae9f1ff88 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java @@ -6,17 +6,17 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordPageReqVO; -import cn.iocoder.yudao.module.trade.convert.brokerage.record.TradeBrokerageRecordConvert; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.TradeBrokerageRecordDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordPageReqVO; +import cn.iocoder.yudao.module.trade.convert.brokerage.record.BrokerageRecordConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.BrokerageRecordDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO; import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; -import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record.TradeBrokerageRecordMapper; +import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record.BrokerageRecordMapper; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO; -import cn.iocoder.yudao.module.trade.service.brokerage.user.TradeBrokerageUserService; +import cn.iocoder.yudao.module.trade.service.brokerage.user.BrokerageUserService; import cn.iocoder.yudao.module.trade.service.config.TradeConfigService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -37,23 +37,23 @@ import java.util.function.Function; @Slf4j @Service @Validated -public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordService { +public class BrokerageRecordServiceImpl implements BrokerageRecordService { @Resource - private TradeBrokerageRecordMapper tradeBrokerageRecordMapper; + private BrokerageRecordMapper brokerageRecordMapper; @Resource private TradeConfigService tradeConfigService; @Resource - private TradeBrokerageUserService tradeBrokerageUserService; + private BrokerageUserService brokerageUserService; @Override - public TradeBrokerageRecordDO getBrokerageRecord(Integer id) { - return tradeBrokerageRecordMapper.selectById(id); + public BrokerageRecordDO getBrokerageRecord(Integer id) { + return brokerageRecordMapper.selectById(id); } @Override - public PageResult getBrokerageRecordPage(TradeBrokerageRecordPageReqVO pageReqVO) { - return tradeBrokerageRecordMapper.selectPage(pageReqVO); + public PageResult getBrokerageRecordPage(BrokerageRecordPageReqVO pageReqVO) { + return brokerageRecordMapper.selectPage(pageReqVO); } @Override @@ -67,7 +67,7 @@ public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordServ } // 1.1 获得一级推广人 - TradeBrokerageUserDO firstUser = tradeBrokerageUserService.getBindBrokerageUser(userId); + BrokerageUserDO firstUser = brokerageUserService.getBindBrokerageUser(userId); if (firstUser == null || !BooleanUtil.isTrue(firstUser.getBrokerageEnabled())) { return; } @@ -78,7 +78,7 @@ public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordServ if (firstUser.getBrokerageUserId() == null) { return; } - TradeBrokerageUserDO secondUser = tradeBrokerageUserService.getBrokerageUser(firstUser.getBrokerageUserId()); + BrokerageUserDO secondUser = brokerageUserService.getBrokerageUser(firstUser.getBrokerageUserId()); if (secondUser == null || !BooleanUtil.isTrue(secondUser.getBrokerageEnabled())) { return; } @@ -89,15 +89,15 @@ public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordServ @Override @Transactional(rollbackFor = Exception.class) public void cancelBrokerage(Long userId, BrokerageRecordBizTypeEnum bizType, String bizId) { - TradeBrokerageRecordDO record = tradeBrokerageRecordMapper.selectByBizTypeAndBizId(bizType.getType(), bizId); + BrokerageRecordDO record = brokerageRecordMapper.selectByBizTypeAndBizId(bizType.getType(), bizId); if (record == null || ObjectUtil.notEqual(record.getUserId(), userId)) { log.error("[cancelBrokerage][userId({})][bizId({}) 更新为已失效失败:记录不存在]", userId, bizId); return; } // 1. 更新佣金记录为已失效 - TradeBrokerageRecordDO updateObj = new TradeBrokerageRecordDO().setStatus(BrokerageRecordStatusEnum.CANCEL.getStatus()); - int updateRows = tradeBrokerageRecordMapper.updateByIdAndStatus(record.getId(), record.getStatus(), updateObj); + BrokerageRecordDO updateObj = new BrokerageRecordDO().setStatus(BrokerageRecordStatusEnum.CANCEL.getStatus()); + int updateRows = brokerageRecordMapper.updateByIdAndStatus(record.getId(), record.getStatus(), updateObj); if (updateRows == 0) { log.error("[cancelBrokerage][record({}) 更新为已失效失败]", record.getId()); return; @@ -105,9 +105,9 @@ public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordServ // 2. 更新用户的佣金 if (BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus().equals(record.getStatus())) { - tradeBrokerageUserService.updateUserFrozenBrokeragePrice(userId, -record.getPrice()); + brokerageUserService.updateUserFrozenBrokeragePrice(userId, -record.getPrice()); } else if (BrokerageRecordStatusEnum.SETTLEMENT.getStatus().equals(record.getStatus())) { - tradeBrokerageUserService.updateUserBrokeragePrice(userId, -record.getPrice()); + brokerageUserService.updateUserBrokeragePrice(userId, -record.getPrice()); } } @@ -141,7 +141,7 @@ public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordServ * @param FixedBrokeragePriceFun 固定佣金 * @param bizType 业务类型 */ - private void addBrokerage(TradeBrokerageUserDO user, List list, Integer brokerageFrozenDays, + private void addBrokerage(BrokerageUserDO user, List list, Integer brokerageFrozenDays, Integer brokeragePercent, Function FixedBrokeragePriceFun, BrokerageRecordBizTypeEnum bizType) { // 1.1 处理冻结时间 @@ -151,13 +151,13 @@ public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordServ } // 1.2 计算分佣 int totalBrokerage = 0; - List records = new ArrayList<>(); + List records = new ArrayList<>(); for (BrokerageAddReqBO item : list) { int brokeragePerItem = calculateBrokeragePrice(item.getBasePrice(), brokeragePercent, FixedBrokeragePriceFun.apply(item)); if (brokeragePerItem <= 0) { continue; } - records.add(TradeBrokerageRecordConvert.INSTANCE.convert(user, bizType, item.getBizId(), + records.add(BrokerageRecordConvert.INSTANCE.convert(user, bizType, item.getBizId(), brokerageFrozenDays, brokeragePerItem, unfreezeTime, bizType.getTitle())); totalBrokerage += brokeragePerItem; } @@ -165,20 +165,20 @@ public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordServ return; } // 1.3 保存佣金记录 - tradeBrokerageRecordMapper.insertBatch(records); + brokerageRecordMapper.insertBatch(records); // 2. 更新用户佣金 if (brokerageFrozenDays != null && brokerageFrozenDays > 0) { // 更新用户冻结佣金 - tradeBrokerageUserService.updateUserFrozenBrokeragePrice(user.getId(), totalBrokerage); + brokerageUserService.updateUserFrozenBrokeragePrice(user.getId(), totalBrokerage); } else { // 更新用户可用佣金 - tradeBrokerageUserService.updateUserBrokeragePrice(user.getId(), totalBrokerage); + brokerageUserService.updateUserBrokeragePrice(user.getId(), totalBrokerage); } } @Override public int unfreezeRecord() { // 1. 查询待结算的佣金记录 - List records = tradeBrokerageRecordMapper.selectListByStatusAndUnfreezeTimeLt( + List records = brokerageRecordMapper.selectListByStatusAndUnfreezeTimeLt( BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus(), LocalDateTime.now()); if (CollUtil.isEmpty(records)) { return 0; @@ -186,7 +186,7 @@ public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordServ // 2. 遍历执行 int count = 0; - for (TradeBrokerageRecordDO record : records) { + for (BrokerageRecordDO record : records) { try { boolean success = getSelf().unfreezeRecord(record); if (success) { @@ -201,24 +201,24 @@ public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordServ @Override public UserBrokerageSummaryBO summaryByUserIdAndBizTypeAndStatus(Long userId, Integer bizType, Integer status) { - UserBrokerageSummaryBO summaryBO = tradeBrokerageRecordMapper.selectCountAndSumPriceByUserIdAndBizTypeAndStatus(userId, bizType, status); + UserBrokerageSummaryBO summaryBO = brokerageRecordMapper.selectCountAndSumPriceByUserIdAndBizTypeAndStatus(userId, bizType, status); return summaryBO == null ? new UserBrokerageSummaryBO(0, 0) : summaryBO; } @Transactional(rollbackFor = Exception.class) - public boolean unfreezeRecord(TradeBrokerageRecordDO record) { + public boolean unfreezeRecord(BrokerageRecordDO record) { // 更新记录状态 - TradeBrokerageRecordDO updateObj = new TradeBrokerageRecordDO() + BrokerageRecordDO updateObj = new BrokerageRecordDO() .setStatus(BrokerageRecordStatusEnum.SETTLEMENT.getStatus()) .setUnfreezeTime(LocalDateTime.now()); - int updateRows = tradeBrokerageRecordMapper.updateByIdAndStatus(record.getId(), record.getStatus(), updateObj); + int updateRows = brokerageRecordMapper.updateByIdAndStatus(record.getId(), record.getStatus(), updateObj); if (updateRows == 0) { log.error("[unfreezeRecord][record({}) 更新为已结算失败]", record.getId()); return false; } // 更新用户冻结佣金 - tradeBrokerageUserService.updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(record.getUserId(), -record.getPrice()); + brokerageUserService.updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(record.getUserId(), -record.getPrice()); log.info("[unfreezeRecord][record({}) 更新为已结算成功]", record.getId()); return true; } @@ -228,7 +228,7 @@ public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordServ * * @return 自己 */ - private TradeBrokerageRecordServiceImpl getSelf() { + private BrokerageRecordServiceImpl getSelf() { return SpringUtil.getBean(getClass()); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java similarity index 78% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserService.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java index c62fc1947..d1ed8865c 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java @@ -1,19 +1,18 @@ package cn.iocoder.yudao.module.trade.service.brokerage.user; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.TradeBrokerageUserPageReqVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.BrokerageUserPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO; import java.util.Collection; import java.util.List; -// TODO @疯狂:要不去掉 Trade 前缀哈;交易这块,我准备除了 tradeorder 保持下,类似 aftersale,都要取消前缀了;tradeorder 保持的原因,是避免 payorder 和它重复 /** * 分销用户 Service 接口 * * @author owen */ -public interface TradeBrokerageUserService { +public interface BrokerageUserService { /** * 获得分销用户 @@ -21,7 +20,7 @@ public interface TradeBrokerageUserService { * @param id 编号 * @return 分销用户 */ - TradeBrokerageUserDO getBrokerageUser(Long id); + BrokerageUserDO getBrokerageUser(Long id); /** * 获得分销用户列表 @@ -29,7 +28,7 @@ public interface TradeBrokerageUserService { * @param ids 编号 * @return 分销用户列表 */ - List getBrokerageUserList(Collection ids); + List getBrokerageUserList(Collection ids); /** * 获得分销用户分页 @@ -37,7 +36,7 @@ public interface TradeBrokerageUserService { * @param pageReqVO 分页查询 * @return 分销用户分页 */ - PageResult getBrokerageUserPage(TradeBrokerageUserPageReqVO pageReqVO); + PageResult getBrokerageUserPage(BrokerageUserPageReqVO pageReqVO); /** * 修改推广员编号 @@ -61,7 +60,7 @@ public interface TradeBrokerageUserService { * @param id 用户编号 * @return 用户的推广人 */ - TradeBrokerageUserDO getBindBrokerageUser(Long id); + BrokerageUserDO getBindBrokerageUser(Long id); /** * 更新用户佣金 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java similarity index 80% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImpl.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java index 6851e522c..8f840bb7d 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java @@ -2,9 +2,9 @@ package cn.iocoder.yudao.module.trade.service.brokerage.user; import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.TradeBrokerageUserPageReqVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; -import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user.TradeBrokerageUserMapper; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.BrokerageUserPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO; +import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user.BrokerageUserMapper; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -24,23 +24,23 @@ import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.USER_FROZEN */ @Service @Validated -public class TradeBrokerageUserServiceImpl implements TradeBrokerageUserService { +public class BrokerageUserServiceImpl implements BrokerageUserService { @Resource - private TradeBrokerageUserMapper brokerageUserMapper; + private BrokerageUserMapper brokerageUserMapper; @Override - public TradeBrokerageUserDO getBrokerageUser(Long id) { + public BrokerageUserDO getBrokerageUser(Long id) { return brokerageUserMapper.selectById(id); } @Override - public List getBrokerageUserList(Collection ids) { + public List getBrokerageUserList(Collection ids) { return brokerageUserMapper.selectBatchIds(ids); } @Override - public PageResult getBrokerageUserPage(TradeBrokerageUserPageReqVO pageReqVO) { + public PageResult getBrokerageUserPage(BrokerageUserPageReqVO pageReqVO) { return brokerageUserMapper.selectPage(pageReqVO); } @@ -65,10 +65,10 @@ public class TradeBrokerageUserServiceImpl implements TradeBrokerageUserService } @Override - public TradeBrokerageUserDO getBindBrokerageUser(Long id) { + public BrokerageUserDO getBindBrokerageUser(Long id) { return Optional.ofNullable(id) .map(this::getBrokerageUser) - .map(TradeBrokerageUserDO::getBrokerageUserId) + .map(BrokerageUserDO::getBrokerageUserId) .map(this::getBrokerageUser) .orElse(null); } @@ -102,7 +102,7 @@ public class TradeBrokerageUserServiceImpl implements TradeBrokerageUserService @Override public Long getCountByBrokerageUserId(Long brokerageUserId) { - return brokerageUserMapper.selectCount(TradeBrokerageUserDO::getBrokerageUserId, brokerageUserId); + return brokerageUserMapper.selectCount(BrokerageUserDO::getBrokerageUserId, brokerageUserId); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index 199cfcbfd..1cda4b3a5 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -51,7 +51,7 @@ import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; import cn.iocoder.yudao.module.trade.enums.order.*; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; -import cn.iocoder.yudao.module.trade.service.brokerage.record.TradeBrokerageRecordService; +import cn.iocoder.yudao.module.trade.service.brokerage.record.BrokerageRecordService; import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; import cn.iocoder.yudao.module.trade.service.cart.CartService; import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; @@ -121,7 +121,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @Resource private MemberPointApi memberPointApi; @Resource - private TradeBrokerageRecordService tradeBrokerageRecordService; + private BrokerageRecordService brokerageRecordService; @Resource private ProductCommentApi productCommentApi; @@ -755,12 +755,12 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { List orderItems = tradeOrderItemMapper.selectListByOrderId(orderId); List list = convertList(orderItems, item -> TradeOrderConvert.INSTANCE.convert(item, productSkuApi.getSku(item.getSkuId()))); - tradeBrokerageRecordService.addBrokerage(userId, bizType, list); + brokerageRecordService.addBrokerage(userId, bizType, list); } @Async protected void cancelBrokerageAsync(Long userId, BrokerageRecordBizTypeEnum bizType, Long orderItemId) { - tradeBrokerageRecordService.cancelBrokerage(userId, bizType, String.valueOf(orderItemId)); + brokerageRecordService.cancelBrokerage(userId, bizType, String.valueOf(orderItemId)); } /** diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImplTest.java b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImplTest.java similarity index 67% rename from yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImplTest.java rename to yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImplTest.java index eb51279d5..00ff04d6d 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImplTest.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImplTest.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.trade.service.brokerage.record; import cn.hutool.core.util.NumberUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordPageReqVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.TradeBrokerageRecordDO; -import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record.TradeBrokerageRecordMapper; -import cn.iocoder.yudao.module.trade.service.brokerage.user.TradeBrokerageUserService; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.BrokerageRecordDO; +import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record.BrokerageRecordMapper; +import cn.iocoder.yudao.module.trade.service.brokerage.user.BrokerageUserService; import cn.iocoder.yudao.module.trade.service.config.TradeConfigService; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -27,51 +27,51 @@ import static org.junit.jupiter.api.Assertions.assertEquals; // TODO @芋艿:单测后续看看 /** - * {@link TradeBrokerageRecordServiceImpl} 的单元测试类 + * {@link BrokerageRecordServiceImpl} 的单元测试类 * * @author owen */ -@Import(TradeBrokerageRecordServiceImpl.class) -public class TradeBrokerageRecordServiceImplTest extends BaseDbUnitTest { +@Import(BrokerageRecordServiceImpl.class) +public class BrokerageRecordServiceImplTest extends BaseDbUnitTest { @Resource - private TradeBrokerageRecordServiceImpl tradeBrokerageRecordService; + private BrokerageRecordServiceImpl brokerageRecordService; @Resource - private TradeBrokerageRecordMapper tradeBrokerageRecordMapper; + private BrokerageRecordMapper brokerageRecordMapper; @MockBean private TradeConfigService tradeConfigService; @MockBean - private TradeBrokerageUserService tradeBrokerageUserService; + private BrokerageUserService brokerageUserService; @Test @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 public void testGetBrokerageRecordPage() { // mock 数据 - TradeBrokerageRecordDO dbBrokerageRecord = randomPojo(TradeBrokerageRecordDO.class, o -> { // 等会查询到 + BrokerageRecordDO dbBrokerageRecord = randomPojo(BrokerageRecordDO.class, o -> { // 等会查询到 o.setUserId(null); o.setBizType(null); o.setStatus(null); o.setCreateTime(null); }); - tradeBrokerageRecordMapper.insert(dbBrokerageRecord); + brokerageRecordMapper.insert(dbBrokerageRecord); // 测试 userId 不匹配 - tradeBrokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setUserId(null))); + brokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setUserId(null))); // 测试 bizType 不匹配 - tradeBrokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setBizType(null))); + brokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setBizType(null))); // 测试 status 不匹配 - tradeBrokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setStatus(null))); + brokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setStatus(null))); // 测试 createTime 不匹配 - tradeBrokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setCreateTime(null))); + brokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setCreateTime(null))); // 准备参数 - TradeBrokerageRecordPageReqVO reqVO = new TradeBrokerageRecordPageReqVO(); + BrokerageRecordPageReqVO reqVO = new BrokerageRecordPageReqVO(); reqVO.setUserId(null); reqVO.setBizType(null); reqVO.setStatus(null); reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); // 调用 - PageResult pageResult = tradeBrokerageRecordService.getBrokerageRecordPage(reqVO); + PageResult pageResult = brokerageRecordService.getBrokerageRecordPage(reqVO); // 断言 assertEquals(1, pageResult.getTotal()); assertEquals(1, pageResult.getList().size()); @@ -85,7 +85,7 @@ public class TradeBrokerageRecordServiceImplTest extends BaseDbUnitTest { Integer percent = randomInt(1, 101); Integer fixedBrokeragePrice = randomInt(); // 调用 - int brokerage = tradeBrokerageRecordService.calculateBrokeragePrice(payPrice, percent, fixedBrokeragePrice); + int brokerage = brokerageRecordService.calculateBrokeragePrice(payPrice, percent, fixedBrokeragePrice); // 断言 assertEquals(brokerage, fixedBrokeragePrice); } @@ -98,7 +98,7 @@ public class TradeBrokerageRecordServiceImplTest extends BaseDbUnitTest { Integer skuBrokeragePrice = randomEle(new Integer[]{0, null}); System.out.println("skuBrokeragePrice=" + skuBrokeragePrice); // 调用 - int brokerage = tradeBrokerageRecordService.calculateBrokeragePrice(payPrice, percent, skuBrokeragePrice); + int brokerage = brokerageRecordService.calculateBrokeragePrice(payPrice, percent, skuBrokeragePrice); // 断言 assertEquals(brokerage, NumberUtil.div(NumberUtil.mul(payPrice, percent), 100, 0, RoundingMode.DOWN).intValue()); } @@ -110,7 +110,7 @@ public class TradeBrokerageRecordServiceImplTest extends BaseDbUnitTest { Integer percent = null; Integer skuBrokeragePrice = null; // 调用 - int brokerage = tradeBrokerageRecordService.calculateBrokeragePrice(payPrice, percent, skuBrokeragePrice); + int brokerage = brokerageRecordService.calculateBrokeragePrice(payPrice, percent, skuBrokeragePrice); // 断言 assertEquals(brokerage, 0); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImplTest.java b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImplTest.java similarity index 74% rename from yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImplTest.java rename to yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImplTest.java index 153bbb426..6950f84e4 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImplTest.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImplTest.java @@ -2,9 +2,9 @@ package cn.iocoder.yudao.module.trade.service.brokerage.user; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.TradeBrokerageUserPageReqVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; -import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user.TradeBrokerageUserMapper; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.BrokerageUserPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO; +import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user.BrokerageUserMapper; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; @@ -19,24 +19,24 @@ import static org.junit.jupiter.api.Assertions.assertEquals; // TODO @芋艿:单测后续看看 /** - * {@link TradeBrokerageUserServiceImpl} 的单元测试类 + * {@link BrokerageUserServiceImpl} 的单元测试类 * * @author owen */ -@Import(TradeBrokerageUserServiceImpl.class) -public class TradeBrokerageUserServiceImplTest extends BaseDbUnitTest { +@Import(BrokerageUserServiceImpl.class) +public class BrokerageUserServiceImplTest extends BaseDbUnitTest { @Resource - private TradeBrokerageUserServiceImpl brokerageUserService; + private BrokerageUserServiceImpl brokerageUserService; @Resource - private TradeBrokerageUserMapper brokerageUserMapper; + private BrokerageUserMapper brokerageUserMapper; @Test @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 public void testGetBrokerageUserPage() { // mock 数据 - TradeBrokerageUserDO dbBrokerageUser = randomPojo(TradeBrokerageUserDO.class, o -> { // 等会查询到 + BrokerageUserDO dbBrokerageUser = randomPojo(BrokerageUserDO.class, o -> { // 等会查询到 o.setBrokerageUserId(null); o.setBrokerageEnabled(null); o.setCreateTime(null); @@ -49,13 +49,13 @@ public class TradeBrokerageUserServiceImplTest extends BaseDbUnitTest { // 测试 createTime 不匹配 brokerageUserMapper.insert(cloneIgnoreId(dbBrokerageUser, o -> o.setCreateTime(null))); // 准备参数 - TradeBrokerageUserPageReqVO reqVO = new TradeBrokerageUserPageReqVO(); + BrokerageUserPageReqVO reqVO = new BrokerageUserPageReqVO(); reqVO.setBrokerageUserId(null); reqVO.setBrokerageEnabled(null); reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); // 调用 - PageResult pageResult = brokerageUserService.getBrokerageUserPage(reqVO); + PageResult pageResult = brokerageUserService.getBrokerageUserPage(reqVO); // 断言 assertEquals(1, pageResult.getTotal()); assertEquals(1, pageResult.getList().size()); From b85d660a5cc375bccb9c200fd0ac4a813c62c00d Mon Sep 17 00:00:00 2001 From: owen Date: Fri, 8 Sep 2023 22:33:44 +0800 Subject: [PATCH 31/50] =?UTF-8?q?trade:=20=E5=88=86=E9=94=80=E4=B8=9A?= =?UTF-8?q?=E5=8A=A1=E5=AE=8C=E5=96=84=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../record/AppBrokerageRecordPageReqVO.java | 7 ++- .../AppBrokerageWithdrawCreateReqVO.java | 59 +++++++++++++++++-- .../brokerage/bo/BrokerageAddReqBO.java | 7 ++- .../record/BrokerageRecordService.java | 3 +- 4 files changed, 64 insertions(+), 12 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java index b7675e6ec..e2df6dae6 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java @@ -1,6 +1,9 @@ package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record; import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -8,12 +11,12 @@ import lombok.Data; @Data public class AppBrokerageRecordPageReqVO extends PageParam { - // TODO @疯狂:要加下枚举校验 - @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @InEnum(value = BrokerageRecordBizTypeEnum.class, message = "业务类型必须是 {value}") private Integer bizType; @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @InEnum(value = BrokerageRecordStatusEnum.class, message = "状态必须是 {value}") private Integer status; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java index 75aec997b..752818130 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java @@ -1,29 +1,76 @@ package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw; +import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.hibernate.validator.constraints.URL; +import javax.validation.Validator; import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; @Schema(description = "用户 App - 分销提现创建 Request VO") @Data public class AppBrokerageWithdrawCreateReqVO { - // TODO @疯狂:参数校验逻辑,需要根据 type 进行不同的校验;感觉可以通过分组? - @Schema(description = "提现方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @InEnum(value = BrokerageWithdrawTypeEnum.class, message = "提现方式必须是 {value}") private Integer type; - @Schema(description = "提现账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456789") // 银行卡号/微信账号/支付宝账号 + @Schema(description = "提现金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") + @Min(value = 1, message = "提现金额不能小于 1") + private Integer price; + + + // ========== 银行卡、微信、支付宝 提现相关字段 ========== + + @Schema(description = "提现账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456789") + @NotBlank(message = "提现账号不能为空", groups = {Bank.class, Wechat.class, Alipay.class}) private String accountNo; + + // ========== 微信、支付宝 提现相关字段 ========== + @Schema(description = "收款码的图片", example = "https://www.iocoder.cn/1.png") @URL(message = "收款码的图片,必须是一个 URL") private String accountQrCodeUrl; - @Schema(description = "提现金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") - @Min(value = 1, message = "提现金额必须大于 1") - private Integer price; + + // ========== 银行卡 提现相关字段 ========== + + @Schema(description = "持卡人姓名", example = "张三") + @NotBlank(message = "持卡人姓名不能为空", groups = {Bank.class}) + private String name; + @Schema(description = "提现银行", example = "1") + @NotBlank(message = "提现银行不能为空", groups = {Bank.class}) + private Integer bankName; + @Schema(description = "开户地址", example = "海淀支行") + private String bankAddress; + + public interface Wallet { + } + + public interface Bank { + } + + public interface Wechat { + } + + public interface Alipay { + } + + public void validate(Validator validator) { + if (BrokerageWithdrawTypeEnum.WALLET.getType().equals(type)) { + ValidationUtils.validate(validator, this, Wallet.class); + } else if (BrokerageWithdrawTypeEnum.BANK.getType().equals(type)) { + ValidationUtils.validate(validator, this, Bank.class); + } else if (BrokerageWithdrawTypeEnum.WECHAT.getType().equals(type)) { + ValidationUtils.validate(validator, this, Wechat.class); + } else if (BrokerageWithdrawTypeEnum.ALIPAY.getType().equals(type)) { + ValidationUtils.validate(validator, this, Alipay.class); + } + } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java index 7e17d9bda..510960beb 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java @@ -4,6 +4,8 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import javax.validation.constraints.NotBlank; + /** * 佣金 增加 Request BO * @@ -14,11 +16,10 @@ import lombok.NoArgsConstructor; @AllArgsConstructor public class BrokerageAddReqBO { - // TODO @疯狂:bo 的话,也可以考虑加下 @Validated 注解,校验下参数;防御性下哈,虽然不一定用的到 - /** - * 业务ID + * 业务编号 */ + @NotBlank(message = "业务编号不能为空") private String bizId; /** * 佣金基数 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordService.java index f0cadd761..64e5fe52f 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordService.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO; +import javax.validation.Valid; import java.util.List; /** @@ -39,7 +40,7 @@ public interface BrokerageRecordService { * @param bizType 业务类型 * @param list 请求参数列表 */ - void addBrokerage(Long userId, BrokerageRecordBizTypeEnum bizType, List list); + void addBrokerage(Long userId, BrokerageRecordBizTypeEnum bizType, @Valid List list); /** * 取消佣金:将佣金记录,状态修改为已失效 From f36a6c5d6ca554962315d625df29fb0a6619aad5 Mon Sep 17 00:00:00 2001 From: owen Date: Fri, 8 Sep 2023 22:40:49 +0800 Subject: [PATCH 32/50] =?UTF-8?q?trade:=20=E4=BC=98=E5=8C=96=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E6=8E=A8=E5=B9=BF=E5=91=98=E6=8E=A5=E5=8F=A3=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/brokerage/user/BrokerageUserController.java | 2 +- .../user/vo/BrokerageUserUpdateBrokerageEnabledReqVO.java | 4 +--- .../trade/service/brokerage/user/BrokerageUserService.java | 6 +++--- .../service/brokerage/user/BrokerageUserServiceImpl.java | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java index b6c9a1c84..1e1ad3acd 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java @@ -62,7 +62,7 @@ public class BrokerageUserController { @Operation(summary = "修改推广资格") @PreAuthorize("@ss.hasPermission('trade:brokerage-user:update-brokerage-enable')") public CommonResult updateBrokerageEnabled(@Valid @RequestBody BrokerageUserUpdateBrokerageEnabledReqVO updateReqVO) { - brokerageUserService.updateBrokerageEnabled(updateReqVO.getId(), updateReqVO.getBrokerageEnabled()); + brokerageUserService.updateBrokerageEnabled(updateReqVO.getId(), updateReqVO.getEnabled()); return success(true); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserUpdateBrokerageEnabledReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserUpdateBrokerageEnabledReqVO.java index 5e6d920be..92001e698 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserUpdateBrokerageEnabledReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserUpdateBrokerageEnabledReqVO.java @@ -15,10 +15,8 @@ public class BrokerageUserUpdateBrokerageEnabledReqVO { @NotNull(message = "用户编号不能为空") private Long id; - // TODO @疯狂:是不是这个字段,可以改成 enabled - @Schema(description = "推广资格", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "推广资格不能为空") - private Boolean brokerageEnabled; + private Boolean enabled; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java index d1ed8865c..362743b65 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java @@ -49,10 +49,10 @@ public interface BrokerageUserService { /** * 修改推广资格 * - * @param id 用户编号 - * @param brokerageEnabled 推广资格 + * @param id 用户编号 + * @param enabled 推广资格 */ - void updateBrokerageEnabled(Long id, Boolean brokerageEnabled); + void updateBrokerageEnabled(Long id, Boolean enabled); /** * 获得用户的推广人 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java index 8f840bb7d..3a4fb475f 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java @@ -52,7 +52,7 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { } @Override - public void updateBrokerageEnabled(Long id, Boolean brokerageEnabled) { + public void updateBrokerageEnabled(Long id, Boolean enabled) { // 校验存在 validateBrokerageUserExists(id); // TODO @疯狂:貌似没实现完 From 3e09da012849bd45438344fe6a65eee78415dd92 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 8 Sep 2023 22:47:00 +0800 Subject: [PATCH 33/50] =?UTF-8?q?code=20review=EF=BC=9A=E6=94=AF=E4=BB=98?= =?UTF-8?q?=E9=92=B1=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/order/PayOrderController.java | 21 ++- .../app/wallet/AppPayWalletController.java | 2 +- .../dal/dataobject/wallet/PayWalletDO.java | 2 + .../pay/dal/mysql/wallet/PayWalletMapper.java | 3 + .../framework/pay/wallet/WalletPayClient.java | 27 ++-- .../pay/service/wallet/PayWalletService.java | 24 +-- .../service/wallet/PayWalletServiceImpl.java | 145 +++++++++--------- .../PayWalletTransactionServiceImpl.java | 2 +- 8 files changed, 122 insertions(+), 104 deletions(-) diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java index a47031a2a..896742636 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java @@ -6,14 +6,15 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; -import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import cn.iocoder.yudao.module.pay.controller.admin.order.vo.*; import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert; import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; +import cn.iocoder.yudao.module.pay.framework.pay.wallet.WalletPayClient; import cn.iocoder.yudao.module.pay.service.app.PayAppService; import cn.iocoder.yudao.module.pay.service.order.PayOrderService; +import com.google.common.collect.Maps; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -25,12 +26,17 @@ import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import java.io.IOException; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId; +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserType; @Tag(name = "管理后台 - 支付订单") @RestController @@ -70,13 +76,16 @@ public class PayOrderController { @PostMapping("/submit") @Operation(summary = "提交支付订单") public CommonResult submitPayOrder(@RequestBody PayOrderSubmitReqVO reqVO) { - // 钱包支付需要 额外传 user_id 和 user_type + // 1. 钱包支付事,需要额外传 user_id 和 user_type if (Objects.equals(reqVO.getChannelCode(), PayChannelEnum.WALLET.getCode())) { - Map channelExtras = reqVO.getChannelExtras() == null ? new HashMap<>(8) : reqVO.getChannelExtras(); - channelExtras.put("user_id", String.valueOf(WebFrameworkUtils.getLoginUserId())); - channelExtras.put("user_type", String.valueOf(WebFrameworkUtils.getLoginUserType())); + Map channelExtras = reqVO.getChannelExtras() == null ? + Maps.newHashMapWithExpectedSize(2) : reqVO.getChannelExtras(); + channelExtras.put(WalletPayClient.USER_ID_KEY, String.valueOf(getLoginUserId())); + channelExtras.put(WalletPayClient.USER_TYPE_KEY, String.valueOf(getLoginUserType())); reqVO.setChannelExtras(channelExtras); } + + // 2. 提交支付 PayOrderSubmitRespVO respVO = orderService.submitOrder(reqVO, getClientIP()); return success(respVO); } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletController.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletController.java index 2c5f2d5f4..95c085cbc 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletController.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletController.java @@ -37,7 +37,7 @@ public class AppPayWalletController { @Operation(summary = "获取钱包") @PreAuthenticated public CommonResult getPayWallet() { - PayWalletDO wallet = payWalletService.getOrCreatePayWallet(getLoginUserId(), UserTypeEnum.MEMBER.getValue()); + PayWalletDO wallet = payWalletService.getOrCreateWallet(getLoginUserId(), UserTypeEnum.MEMBER.getValue()); return success(PayWalletConvert.INSTANCE.convert(wallet)); } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletDO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletDO.java index 92eb620da..4bf8e6151 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletDO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletDO.java @@ -37,6 +37,8 @@ public class PayWalletDO extends BaseDO { */ private Integer userType; + // TODO @jason:三个都搞 integer?应该要统一哈 + /** * 余额,单位分 */ diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java index ccacdd376..47717d04a 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java @@ -15,6 +15,7 @@ public interface PayWalletMapper extends BaseMapperX { PayWalletDO::getUserType, userType); } + // TODO @jason:减少时,需要 update price -= ? where price >= ?,避免并发问题。现在基于 price 来过滤,虽然也能解决并发问题,但是冲突概率会高一点;可以看到 TradeBrokerageUserMapper 的做法; /** * 当余额减少时候更新 * @@ -27,6 +28,7 @@ public interface PayWalletMapper extends BaseMapperX { */ default int updateWhenDecBalance(PayWalletBizTypeEnum bizType, Integer balance, Long totalRecharge, Long totalExpense, Integer price, Long id) { + // TODO @jason:这种偏判断的,最红放在 service 层;mapper 可以写多个方法; PayWalletDO updateDO = new PayWalletDO().setBalance(balance - price); if(bizType == PayWalletBizTypeEnum.PAYMENT){ updateDO.setTotalExpense(totalExpense + price); @@ -40,6 +42,7 @@ public interface PayWalletMapper extends BaseMapperX { .ge(PayWalletDO::getBalance, price)); } + // TODO @jason:类似上面的修改建议哈; /** * 当余额增加时候更新 * diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java index 42da490d2..47e8217d3 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java @@ -37,13 +37,13 @@ import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.REFUND_NOT_FO @Slf4j public class WalletPayClient extends AbstractPayClient { + public static final String USER_ID_KEY = "user_id"; + public static final String USER_TYPE_KEY = "user_type"; + private PayWalletService wallService; - private PayWalletTransactionService walletTransactionService; - - private PayOrderService payOrderService; - - private PayRefundService payRefundService; + private PayOrderService orderService; + private PayRefundService refundService; public WalletPayClient(Long channelId, NonePayClientConfig config) { super(channelId, PayChannelEnum.WALLET.getCode(), config); @@ -62,8 +62,9 @@ public class WalletPayClient extends AbstractPayClient { @Override protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) { try { - String userId = MapUtil.getStr(reqDTO.getChannelExtras(), "user_id"); - String userType = MapUtil.getStr(reqDTO.getChannelExtras(), "user_type"); + // TODO @jason:直接 getLong 和 getInt 会不会更简洁哈 + String userId = MapUtil.getStr(reqDTO.getChannelExtras(), USER_ID_KEY); + String userType = MapUtil.getStr(reqDTO.getChannelExtras(), USER_TYPE_KEY); Assert.notEmpty(userId, "用户 id 不能为空"); Assert.notEmpty(userType, "用户类型不能为空"); PayWalletTransactionDO transaction = wallService.orderPay(Long.valueOf(userId), Integer.valueOf(userType), @@ -92,10 +93,10 @@ public class WalletPayClient extends AbstractPayClient { @Override protected PayOrderRespDTO doGetOrder(String outTradeNo) { - if (payOrderService == null) { - payOrderService = SpringUtil.getBean(PayOrderService.class); + if (orderService == null) { + orderService = SpringUtil.getBean(PayOrderService.class); } - PayOrderExtensionDO orderExtension = payOrderService.getOrderExtensionByNo(outTradeNo); + PayOrderExtensionDO orderExtension = orderService.getOrderExtensionByNo(outTradeNo); // 支付交易拓展单不存在, 返回关闭状态 if (orderExtension == null) { return PayOrderRespDTO.closedOf(String.valueOf(ORDER_EXTENSION_NOT_FOUND.getCode()), @@ -147,10 +148,10 @@ public class WalletPayClient extends AbstractPayClient { @Override protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) { - if (payRefundService == null) { - payRefundService = SpringUtil.getBean(PayRefundService.class); + if (refundService == null) { + refundService = SpringUtil.getBean(PayRefundService.class); } - PayRefundDO payRefund = payRefundService.getRefundByNo(outRefundNo); + PayRefundDO payRefund = refundService.getRefundByNo(outRefundNo); // 支付退款单不存在, 返回退款失败状态 if (payRefund == null) { return PayRefundRespDTO.failureOf(String.valueOf(REFUND_NOT_FOUND), REFUND_NOT_FOUND.getMsg(), diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java index 3ea75ad09..28f9849b5 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java @@ -12,12 +12,14 @@ import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; public interface PayWalletService { /** - * 获取钱包信息,如果不存在创建钱包。由于用户注册时候不会创建钱包 + * 获取钱包信息 + * + * 如果不存在,则创建钱包。由于用户注册时候不会创建钱包 * * @param userId 用户编号 * @param userType 用户类型 */ - PayWalletDO getOrCreatePayWallet(Long userId, Integer userType); + PayWalletDO getOrCreateWallet(Long userId, Integer userType); /** * 钱包订单支付 @@ -29,6 +31,14 @@ public interface PayWalletService { */ PayWalletTransactionDO orderPay(Long userId, Integer userType, String outTradeNo, Integer price); + /** + * 钱包订单支付退款 + * + * @param outRefundNo 外部退款号 + * @param refundPrice 退款金额 + * @param reason 退款原因 + */ + PayWalletTransactionDO orderRefund(String outRefundNo, Integer refundPrice, String reason); /** * 扣减钱包余额 @@ -43,7 +53,6 @@ public interface PayWalletService { PayWalletTransactionDO reduceWalletBalance(Long userId, Integer userType, Long bizId, PayWalletBizTypeEnum bizType, Integer price); - /** * 增加钱包余额 * @@ -57,13 +66,4 @@ public interface PayWalletService { PayWalletTransactionDO addWalletBalance(Long userId, Integer userType, Long bizId, PayWalletBizTypeEnum bizType, Integer price); - /** - * 钱包订单支付退款 - * - * @param outRefundNo 外部退款号 - * @param refundPrice 退款金额 - * @param reason 退款原因 - */ - PayWalletTransactionDO orderRefund(String outRefundNo, Integer refundPrice, String reason); - } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java index ea607c0e8..d017e5332 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java @@ -43,81 +43,124 @@ public class PayWalletServiceImpl implements PayWalletService { private static final String WALLET_REFUND_NO_PREFIX = "WR"; @Resource - private PayWalletMapper payWalletMapper; + private PayWalletMapper walletMapper; @Resource private PayNoRedisDAO noRedisDAO; @Resource - private PayWalletTransactionService payWalletTransactionService; + private PayWalletTransactionService walletTransactionService; @Resource @Lazy - private PayOrderService payOrderService; + private PayOrderService orderService; @Resource @Lazy - private PayRefundService payRefundService; + private PayRefundService refundService; @Override - public PayWalletDO getOrCreatePayWallet(Long userId, Integer userType) { - PayWalletDO payWalletDO = payWalletMapper.selectByUserIdAndType(userId, userType); - if (payWalletDO == null) { - payWalletDO = new PayWalletDO(); - payWalletDO.setUserId(userId); - payWalletDO.setUserType(userType); - payWalletDO.setBalance(0); - payWalletDO.setTotalExpense(0L); - payWalletDO.setTotalRecharge(0L); - payWalletDO.setCreateTime(LocalDateTime.now()); - payWalletMapper.insert(payWalletDO); + public PayWalletDO getOrCreateWallet(Long userId, Integer userType) { + PayWalletDO wallet = walletMapper.selectByUserIdAndType(userId, userType); + if (wallet == null) { + wallet = new PayWalletDO().setUserId(userId).setUserType(userType) + .setBalance(0).setTotalExpense(0L).setTotalRecharge(0L); + wallet.setCreateTime(LocalDateTime.now()); + walletMapper.insert(wallet); } - return payWalletDO; + return wallet; } - @Override @Transactional(rollbackFor = Exception.class) public PayWalletTransactionDO orderPay(Long userId, Integer userType, String outTradeNo, Integer price) { - // 判断支付交易拓展单是否存 - PayOrderExtensionDO orderExtension = payOrderService.getOrderExtensionByNo(outTradeNo); + // 1. 判断支付交易拓展单是否存 + PayOrderExtensionDO orderExtension = orderService.getOrderExtensionByNo(outTradeNo); if (orderExtension == null) { throw exception(ORDER_EXTENSION_NOT_FOUND); } + // 2. 扣减余额 return reduceWalletBalance(userId, userType, orderExtension.getOrderId(), PAYMENT, price); } + @Override + @Transactional(rollbackFor = Exception.class) + public PayWalletTransactionDO orderRefund(String outRefundNo, Integer refundPrice, String reason) { + // 1.1 判断退款单是否存在 + PayRefundDO payRefund = refundService.getRefundByNo(outRefundNo); + if (payRefund == null) { + throw exception(REFUND_NOT_FOUND); + } + // 1.2 校验是否可以退款 + Long walletId = validateWalletCanRefund(payRefund.getId(), payRefund.getChannelOrderNo(), refundPrice); + PayWalletDO wallet = walletMapper.selectById(walletId); + Assert.notNull(wallet, "钱包 {} 不存在", walletId); + // 2. 增加余额 + return addWalletBalance(wallet.getUserId(), wallet.getUserType(), payRefund.getId(), PAYMENT_REFUND, refundPrice); + } + + /** + * 校验是否能退款 + * + * @param refundId 支付退款单 id + * @param walletPayNo 钱包支付 no + */ + private Long validateWalletCanRefund(Long refundId, String walletPayNo, Integer refundPrice) { + // 1. 校验钱包支付交易存在 + PayWalletTransactionDO walletTransaction = walletTransactionService.getWalletTransactionByNo(walletPayNo); + if (walletTransaction == null) { + throw exception(WALLET_TRANSACTION_NOT_FOUND); + } + // 原来的支付金额 + // TODO @jason:应该允许多次退款哈; + int amount = - walletTransaction.getPrice(); + if (refundPrice != amount) { + throw exception(WALLET_REFUND_AMOUNT_ERROR); + } + PayWalletTransactionDO refundTransaction = walletTransactionService.getWalletTransaction( + String.valueOf(refundId), PAYMENT_REFUND); + if (refundTransaction != null) { + throw exception(WALLET_REFUND_EXIST); + } + return walletTransaction.getWalletId(); + } + @Override public PayWalletTransactionDO reduceWalletBalance(Long userId, Integer userType, Long bizId, PayWalletBizTypeEnum bizType, Integer price) { // 1.1 获取钱包 - PayWalletDO payWallet = getOrCreatePayWallet(userId, userType); + PayWalletDO payWallet = getOrCreateWallet(userId, userType); // 1.2 判断余额是否足够 int afterBalance = payWallet.getBalance() - price; if (afterBalance < 0) { throw exception(WALLET_BALANCE_NOT_ENOUGH); } + // TODO jason:建议基于 where price >= 来做哈;然后抛出 WALLET_BALANCE_NOT_ENOUGH // 2.1 扣除余额 - int number = payWalletMapper.updateWhenDecBalance(bizType,payWallet.getBalance(), payWallet.getTotalRecharge(), - payWallet.getTotalExpense(), price, payWallet.getId()); + int number = walletMapper.updateWhenDecBalance(bizType, payWallet.getBalance(), + payWallet.getTotalRecharge(), payWallet.getTotalExpense(), price, payWallet.getId()); if (number == 0) { throw exception(TOO_MANY_REQUESTS); } + // 2.2 生成钱包流水 + // TODO @jason:walletNo 交给 payWalletTransactionService 自己生成哈; String walletNo = generateWalletNo(bizType); PayWalletTransactionDO walletTransaction = new PayWalletTransactionDO().setWalletId(payWallet.getId()) .setNo(walletNo).setPrice(-price).setBalance(afterBalance) .setBizId(String.valueOf(bizId)).setBizType(bizType.getType()).setTitle(bizType.getDescription()); - payWalletTransactionService.createWalletTransaction(walletTransaction); + // TODO @jason:是不是可以 createWalletTransaction 搞个 bo 参数,然后 PayWalletTransactionDO 交回给 walletTransactionService 更好;然后把参数简化下 + walletTransactionService.createWalletTransaction(walletTransaction); return walletTransaction; } @Override - public PayWalletTransactionDO addWalletBalance(Long userId, Integer userType, Long bizId, - PayWalletBizTypeEnum bizType, Integer price) { + public PayWalletTransactionDO addWalletBalance(Long userId, Integer userType, + Long bizId, PayWalletBizTypeEnum bizType, Integer price) { // 1.1 获取钱包 - PayWalletDO payWallet = getOrCreatePayWallet(userId, userType); + PayWalletDO payWallet = getOrCreateWallet(userId, userType); // 2.1 增加余额 - int number = payWalletMapper.updateWhenIncBalance(bizType, payWallet.getBalance(), payWallet.getTotalRecharge(), + // TODO @jason:类似上面的思路哈; + int number = walletMapper.updateWhenIncBalance(bizType, payWallet.getBalance(), payWallet.getTotalRecharge(), payWallet.getTotalExpense(), price, payWallet.getId()); if (number == 0) { throw exception(TOO_MANY_REQUESTS); @@ -129,63 +172,23 @@ public class PayWalletServiceImpl implements PayWalletService { .setNo(walletNo).setPrice(price).setBalance(payWallet.getBalance()+price) .setBizId(String.valueOf(bizId)).setBizType(bizType.getType()) .setTitle(bizType.getDescription()); - payWalletTransactionService.createWalletTransaction(newWalletTransaction); + walletTransactionService.createWalletTransaction(newWalletTransaction); return newWalletTransaction; } private String generateWalletNo(PayWalletBizTypeEnum bizType) { + // TODO @jason:对于余额来说,是不是直接 W+序号就行了,它其实不关注业务;;;不然就耦合啦 String no = ""; switch(bizType){ - case PAYMENT : + case PAYMENT: no = noRedisDAO.generate(WALLET_PAY_NO_PREFIX); break; - case PAYMENT_REFUND : + case PAYMENT_REFUND: no = noRedisDAO.generate(WALLET_REFUND_NO_PREFIX); break; default : - // TODO 待增加 } return no; } - @Override - @Transactional(rollbackFor = Exception.class) - public PayWalletTransactionDO orderRefund(String outRefundNo, Integer refundPrice, String reason) { - // 1.1 判断退款单是否存在 - PayRefundDO payRefund = payRefundService.getRefundByNo(outRefundNo); - if (payRefund == null) { - throw exception(REFUND_NOT_FOUND); - } - // 1.2 校验是否可以退款 - Long walletId = validateWalletCanRefund(payRefund.getId(), payRefund.getChannelOrderNo(), refundPrice); - - PayWalletDO payWallet = payWalletMapper.selectById(walletId); - Assert.notNull(payWallet, "钱包 {} 不存在", walletId); - return addWalletBalance(payWallet.getUserId(), payWallet.getUserType(),payRefund.getId(), PAYMENT_REFUND, refundPrice); - } - - /** - * 校验是否能退款 - * - * @param refundId 支付退款单 id - * @param walletPayNo 钱包支付 no - */ - private Long validateWalletCanRefund(Long refundId, String walletPayNo, Integer refundPrice) { - // 查询钱包支付交易 - PayWalletTransactionDO payWalletTransaction = payWalletTransactionService.getWalletTransactionByNo(walletPayNo); - if (payWalletTransaction == null) { - throw exception(WALLET_TRANSACTION_NOT_FOUND); - } - // 原来的支付金额 - int amount = - payWalletTransaction.getPrice(); - if (refundPrice != amount) { - throw exception(WALLET_REFUND_AMOUNT_ERROR); - } - PayWalletTransactionDO refundTransaction = payWalletTransactionService.getWalletTransaction( - String.valueOf(refundId), PAYMENT_REFUND); - if (refundTransaction != null) { - throw exception(WALLET_REFUND_EXIST); - } - return payWalletTransaction.getWalletId(); - } } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java index 971f59416..05a2a4800 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java @@ -28,7 +28,7 @@ public class PayWalletTransactionServiceImpl implements PayWalletTransactionServ @Override public PageResult getWalletTransactionPage(Long userId, Integer userType, AppPayWalletTransactionPageReqVO pageVO) { - PayWalletDO wallet = payWalletService.getOrCreatePayWallet(userId, userType); + PayWalletDO wallet = payWalletService.getOrCreateWallet(userId, userType); return payWalletTransactionMapper.selectPage(wallet.getId(), pageVO); } From 4b43304c765190a0cae4fc6285e3ec5b69abb8c3 Mon Sep 17 00:00:00 2001 From: owen Date: Fri, 8 Sep 2023 22:51:05 +0800 Subject: [PATCH 34/50] =?UTF-8?q?trade:=20=E4=BC=98=E5=8C=96=E5=88=86?= =?UTF-8?q?=E9=94=80=E7=94=A8=E6=88=B7=E7=BB=91=E5=AE=9A=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E7=BC=96=E5=8F=B7=E3=80=81=E7=BB=91=E5=AE=9A=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/mysql/brokerage.sql | 6 +++--- .../admin/brokerage/user/BrokerageUserController.java | 2 +- .../admin/brokerage/user/vo/BrokerageUserBaseVO.java | 4 ++-- .../admin/brokerage/user/vo/BrokerageUserPageReqVO.java | 2 +- .../dal/dataobject/brokerage/user/BrokerageUserDO.java | 9 +++++---- .../dal/mysql/brokerage/user/BrokerageUserMapper.java | 2 +- .../brokerage/record/BrokerageRecordServiceImpl.java | 4 ++-- .../service/brokerage/user/BrokerageUserService.java | 4 ++-- .../service/brokerage/user/BrokerageUserServiceImpl.java | 6 +++--- .../brokerage/user/BrokerageUserServiceImplTest.java | 6 +++--- .../src/test/resources/sql/create_tables.sql | 4 ++-- 11 files changed, 25 insertions(+), 24 deletions(-) diff --git a/sql/mysql/brokerage.sql b/sql/mysql/brokerage.sql index 53b9dc04e..08b05da14 100644 --- a/sql/mysql/brokerage.sql +++ b/sql/mysql/brokerage.sql @@ -24,8 +24,8 @@ create table trade_config create table trade_brokerage_user ( id bigint auto_increment comment '用户编号' primary key, - brokerage_user_id bigint null comment '推广员编号', - brokerage_bind_time datetime null comment '推广员绑定时间', + bind_user_id bigint null comment '推广员编号', + bind_user_time datetime null comment '推广员绑定时间', brokerage_enabled bit default 1 not null comment '是否成为推广员', brokerage_time datetime null comment '成为分销员时间', brokerage_price int default 0 not null comment '可用佣金', @@ -38,7 +38,7 @@ create table trade_brokerage_user tenant_id bigint default 0 not null comment '租户编号' ) comment '分销用户'; -create index idx_invite_user_id on trade_brokerage_user (brokerage_user_id) comment '推广员编号'; +create index idx_invite_user_id on trade_brokerage_user (bind_user_id) comment '推广员编号'; create index idx_agent on trade_brokerage_user (brokerage_enabled) comment '是否成为推广员'; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java index 1e1ad3acd..0992f52e0 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java @@ -94,7 +94,7 @@ public class BrokerageUserController { // 合计推广用户数量 Map brokerageUserCountMap = convertMap(userIds, userId -> userId, - userId -> brokerageUserService.getCountByBrokerageUserId(userId)); + userId -> brokerageUserService.getCountByBindUserId(userId)); // todo 合计提现 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserBaseVO.java index 41ddd454c..5da0b5d6b 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserBaseVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserBaseVO.java @@ -18,11 +18,11 @@ public class BrokerageUserBaseVO { @Schema(description = "推广员编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4587") @NotNull(message = "推广员编号不能为空") - private Long brokerageUserId; + private Long bindUserId; @Schema(description = "推广员绑定时间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime brokerageBindTime; + private LocalDateTime bindUserTime; @Schema(description = "推广资格", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "推广资格不能为空") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserPageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserPageReqVO.java index 2b99d686e..e6908e8aa 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserPageReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserPageReqVO.java @@ -18,7 +18,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ public class BrokerageUserPageReqVO extends PageParam { @Schema(description = "推广员编号", example = "4587") - private Long brokerageUserId; + private Long bindUserId; @Schema(description = "推广资格") private Boolean brokerageEnabled; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/BrokerageUserDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/BrokerageUserDO.java index 4b85dc3d0..09ad6d72d 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/BrokerageUserDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/BrokerageUserDO.java @@ -26,21 +26,22 @@ public class BrokerageUserDO extends BaseDO { /** * 用户编号 + *

+ * 对应 MemberUserDO 的 id 字段 */ @TableId private Long id; - // TODO @疯狂:貌似改成 bindUserId,更明确? /** * 推广员编号 - * + *

* 关联 MemberUserDO 的 id 字段 */ - private Long brokerageUserId; + private Long bindUserId; /** * 推广员绑定时间 */ - private LocalDateTime brokerageBindTime; + private LocalDateTime bindUserTime; /** * 推广资格 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java index d5cc39523..2d536bb88 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java @@ -19,7 +19,7 @@ public interface BrokerageUserMapper extends BaseMapperX { default PageResult selectPage(BrokerageUserPageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(BrokerageUserDO::getBrokerageUserId, reqVO.getBrokerageUserId()) + .eqIfPresent(BrokerageUserDO::getBindUserId, reqVO.getBindUserId()) .eqIfPresent(BrokerageUserDO::getBrokerageEnabled, reqVO.getBrokerageEnabled()) .betweenIfPresent(BrokerageUserDO::getCreateTime, reqVO.getCreateTime()) .orderByDesc(BrokerageUserDO::getId)); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java index ae9f1ff88..1a0cf4fe7 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java @@ -75,10 +75,10 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { addBrokerage(firstUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageFirstPercent(), BrokerageAddReqBO::getFirstBrokeragePrice, bizType); // 2.1 获得二级推广员 - if (firstUser.getBrokerageUserId() == null) { + if (firstUser.getBindUserId() == null) { return; } - BrokerageUserDO secondUser = brokerageUserService.getBrokerageUser(firstUser.getBrokerageUserId()); + BrokerageUserDO secondUser = brokerageUserService.getBrokerageUser(firstUser.getBindUserId()); if (secondUser == null || !BooleanUtil.isTrue(secondUser.getBrokerageEnabled())) { return; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java index 362743b65..5ba7eb4c1 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java @@ -89,8 +89,8 @@ public interface BrokerageUserService { /** * 获得推广用户数量(一级) * - * @param brokerageUserId 推广员编号 + * @param bindUserId 绑定的推广员编号 * @return 推广用户数量 */ - Long getCountByBrokerageUserId(Long brokerageUserId); + Long getCountByBindUserId(Long bindUserId); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java index 3a4fb475f..a09192ed6 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java @@ -68,7 +68,7 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { public BrokerageUserDO getBindBrokerageUser(Long id) { return Optional.ofNullable(id) .map(this::getBrokerageUser) - .map(BrokerageUserDO::getBrokerageUserId) + .map(BrokerageUserDO::getBindUserId) .map(this::getBrokerageUser) .orElse(null); } @@ -101,8 +101,8 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { } @Override - public Long getCountByBrokerageUserId(Long brokerageUserId) { - return brokerageUserMapper.selectCount(BrokerageUserDO::getBrokerageUserId, brokerageUserId); + public Long getCountByBindUserId(Long bindUserId) { + return brokerageUserMapper.selectCount(BrokerageUserDO::getBindUserId, bindUserId); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImplTest.java b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImplTest.java index 6950f84e4..1c505e1b4 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImplTest.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImplTest.java @@ -37,20 +37,20 @@ public class BrokerageUserServiceImplTest extends BaseDbUnitTest { public void testGetBrokerageUserPage() { // mock 数据 BrokerageUserDO dbBrokerageUser = randomPojo(BrokerageUserDO.class, o -> { // 等会查询到 - o.setBrokerageUserId(null); + o.setBindUserId(null); o.setBrokerageEnabled(null); o.setCreateTime(null); }); brokerageUserMapper.insert(dbBrokerageUser); // 测试 brokerageUserId 不匹配 - brokerageUserMapper.insert(cloneIgnoreId(dbBrokerageUser, o -> o.setBrokerageUserId(null))); + brokerageUserMapper.insert(cloneIgnoreId(dbBrokerageUser, o -> o.setBindUserId(null))); // 测试 brokerageEnabled 不匹配 brokerageUserMapper.insert(cloneIgnoreId(dbBrokerageUser, o -> o.setBrokerageEnabled(null))); // 测试 createTime 不匹配 brokerageUserMapper.insert(cloneIgnoreId(dbBrokerageUser, o -> o.setCreateTime(null))); // 准备参数 BrokerageUserPageReqVO reqVO = new BrokerageUserPageReqVO(); - reqVO.setBrokerageUserId(null); + reqVO.setBindUserId(null); reqVO.setBrokerageEnabled(null); reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql b/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql index 02045d2c2..eafad666f 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql @@ -129,8 +129,8 @@ CREATE TABLE IF NOT EXISTS "trade_after_sale_log" ( CREATE TABLE IF NOT EXISTS "trade_brokerage_user" ( "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "brokerage_user_id" bigint NOT NULL, - "brokerage_bind_time" varchar, + "bind_user_id" bigint NOT NULL, + "bind_user_time" varchar, "brokerage_enabled" bit NOT NULL, "brokerage_time" varchar, "brokerage_price" int NOT NULL, From 1ead3685958846d86afe620f547932bececdc094 Mon Sep 17 00:00:00 2001 From: owen Date: Fri, 8 Sep 2023 23:10:04 +0800 Subject: [PATCH 35/50] =?UTF-8?q?trade:=20=E4=BC=98=E5=8C=96=E5=88=86?= =?UTF-8?q?=E9=94=80=E7=94=A8=E6=88=B7=E4=BD=A3=E9=87=91=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/mysql/brokerage.sql | 26 ++++++------ .../trade/enums/ErrorCodeConstants.java | 2 +- .../user/vo/BrokerageUserBaseVO.java | 4 +- .../brokerage/AppBrokerageUserController.java | 24 +++++------ .../AppBrokerageUserChildSummaryRespVO.java | 2 +- .../user/AppBrokerageUserMySummaryRespVO.java | 8 ++-- .../AppBrokerageUserRankByPriceRespVO.java | 2 +- .../vo/user/AppBrokerageUserRespVO.java | 4 +- .../record/BrokerageRecordConvert.java | 2 +- .../convert/order/TradeOrderConvert.java | 4 +- .../brokerage/user/BrokerageUserDO.java | 5 +-- .../brokerage/user/BrokerageUserMapper.java | 24 +++++------ .../brokerage/bo/BrokerageAddReqBO.java | 4 +- .../record/BrokerageRecordServiceImpl.java | 42 +++++++++---------- .../brokerage/user/BrokerageUserService.java | 18 ++++---- .../user/BrokerageUserServiceImpl.java | 30 ++++++------- .../BrokerageRecordServiceImplTest.java | 22 +++++----- .../src/test/resources/sql/create_tables.sql | 26 ++++++------ 18 files changed, 124 insertions(+), 125 deletions(-) diff --git a/sql/mysql/brokerage.sql b/sql/mysql/brokerage.sql index 08b05da14..a84d80051 100644 --- a/sql/mysql/brokerage.sql +++ b/sql/mysql/brokerage.sql @@ -23,19 +23,19 @@ create table trade_config -- 增加分销用户扩展表 create table trade_brokerage_user ( - id bigint auto_increment comment '用户编号' primary key, - bind_user_id bigint null comment '推广员编号', - bind_user_time datetime null comment '推广员绑定时间', - brokerage_enabled bit default 1 not null comment '是否成为推广员', - brokerage_time datetime null comment '成为分销员时间', - brokerage_price int default 0 not null comment '可用佣金', - frozen_brokerage_price int default 0 not null comment '冻结佣金', - creator varchar(64) collate utf8mb4_unicode_ci default '' null comment '创建者', - create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间', - updater varchar(64) collate utf8mb4_unicode_ci default '' null comment '更新者', - update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间', - deleted bit default b'0' not null comment '是否删除', - tenant_id bigint default 0 not null comment '租户编号' + id bigint auto_increment comment '用户编号' primary key, + bind_user_id bigint null comment '推广员编号', + bind_user_time datetime null comment '推广员绑定时间', + brokerage_enabled bit default 1 not null comment '是否成为推广员', + brokerage_time datetime null comment '成为分销员时间', + price int default 0 not null comment '可用佣金', + frozen_price int default 0 not null comment '冻结佣金', + creator varchar(64) collate utf8mb4_unicode_ci default '' null comment '创建者', + create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间', + updater varchar(64) collate utf8mb4_unicode_ci default '' null comment '更新者', + update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间', + deleted bit default b'0' not null comment '是否删除', + tenant_id bigint default 0 not null comment '租户编号' ) comment '分销用户'; create index idx_invite_user_id on trade_brokerage_user (bind_user_id) comment '推广员编号'; diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java index 5ddff9b11..fa5be50b7 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java @@ -77,6 +77,6 @@ public interface ErrorCodeConstants { // ========== 分销用户 模块 1011007000 ========== ErrorCode BROKERAGE_USER_NOT_EXISTS = new ErrorCode(1011007000, "分销用户不存在"); - ErrorCode USER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH = new ErrorCode(1011007001, "用户冻结佣金({})数量不足"); + ErrorCode BROKERAGE_USER_FROZEN_PRICE_NOT_ENOUGH = new ErrorCode(1011007001, "用户冻结佣金({})数量不足"); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserBaseVO.java index 5da0b5d6b..34f792b72 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserBaseVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserBaseVO.java @@ -34,10 +34,10 @@ public class BrokerageUserBaseVO { @Schema(description = "可用佣金", requiredMode = Schema.RequiredMode.REQUIRED, example = "11089") @NotNull(message = "可用佣金不能为空") - private Integer brokeragePrice; + private Integer price; @Schema(description = "冻结佣金", requiredMode = Schema.RequiredMode.REQUIRED, example = "30916") @NotNull(message = "冻结佣金不能为空") - private Integer frozenBrokeragePrice; + private Integer frozenPrice; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java index 1b760be05..ecbb7de45 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java @@ -34,8 +34,8 @@ public class AppBrokerageUserController { @PreAuthenticated public CommonResult getBrokerageUser() { AppBrokerageUserRespVO respVO = new AppBrokerageUserRespVO() - .setBrokeragePrice(2000) - .setFrozenBrokeragePrice(3000); + .setPrice(2000) + .setFrozenPrice(3000); return success(respVO); } @@ -45,10 +45,10 @@ public class AppBrokerageUserController { @PreAuthenticated public CommonResult getBrokerageUserSummary() { AppBrokerageUserMySummaryRespVO respVO = new AppBrokerageUserMySummaryRespVO() - .setYesterdayBrokeragePrice(1) - .setBrokeragePrice(2) - .setFrozenBrokeragePrice(3) - .setWithdrawBrokeragePrice(4) + .setYesterdayPrice(1) + .setPrice(2) + .setFrozenPrice(3) + .setWithdrawPrice(4) .setFirstBrokerageUserCount(166) .setSecondBrokerageUserCount(233); return success(respVO); @@ -81,16 +81,16 @@ public class AppBrokerageUserController { public CommonResult> getBrokerageUserChildSummaryPageByPrice(AppBrokerageUserRankPageReqVO pageReqVO) { AppBrokerageUserRankByPriceRespVO vo1 = new AppBrokerageUserRankByPriceRespVO() .setId(1L).setNickname("芋1**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") - .setBrokeragePrice(10); + .setPrice(10); AppBrokerageUserRankByPriceRespVO vo2 = new AppBrokerageUserRankByPriceRespVO() .setId(2L).setNickname("芋2**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") - .setBrokeragePrice(6); + .setPrice(6); AppBrokerageUserRankByPriceRespVO vo3 = new AppBrokerageUserRankByPriceRespVO() .setId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") - .setBrokeragePrice(4); + .setPrice(4); AppBrokerageUserRankByPriceRespVO vo4 = new AppBrokerageUserRankByPriceRespVO() .setId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") - .setBrokeragePrice(4); + .setPrice(4); return success(new PageResult<>(asList(vo1, vo2, vo3, vo4), 10L)); } @@ -102,11 +102,11 @@ public class AppBrokerageUserController { AppBrokerageUserChildSummaryPageReqVO pageReqVO) { AppBrokerageUserChildSummaryRespVO vo1 = new AppBrokerageUserChildSummaryRespVO() .setId(1L).setNickname("芋1**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") - .setBrokeragePrice(10).setBrokeragePrice(20).setBrokerageOrderCount(30) + .setPrice(10).setPrice(20).setBrokerageOrderCount(30) .setBrokerageTime(LocalDateTime.now()); AppBrokerageUserChildSummaryRespVO vo2 = new AppBrokerageUserChildSummaryRespVO() .setId(1L).setNickname("芋2**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") - .setBrokeragePrice(20).setBrokeragePrice(30).setBrokerageOrderCount(40) + .setPrice(20).setPrice(30).setBrokerageOrderCount(40) .setBrokerageTime(LocalDateTime.now()); return success(new PageResult<>(asList(vo1, vo2), 10L)); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserChildSummaryRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserChildSummaryRespVO.java index 1beb1b5e2..55d88d74f 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserChildSummaryRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserChildSummaryRespVO.java @@ -19,7 +19,7 @@ public class AppBrokerageUserChildSummaryRespVO { private String avatar; @Schema(description = "佣金金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - private Integer brokeragePrice; + private Integer price; @Schema(description = "分销订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") private Integer brokerageOrderCount; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserMySummaryRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserMySummaryRespVO.java index 64fafe329..33a089cc6 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserMySummaryRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserMySummaryRespVO.java @@ -8,16 +8,16 @@ import lombok.Data; public class AppBrokerageUserMySummaryRespVO { @Schema(description = "昨天的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - private Integer yesterdayBrokeragePrice; + private Integer yesterdayPrice; @Schema(description = "提现的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer withdrawBrokeragePrice; + private Integer withdrawPrice; @Schema(description = "可用的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2408") - private Integer brokeragePrice; + private Integer price; @Schema(description = "冻结的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "234") - private Integer frozenBrokeragePrice; + private Integer frozenPrice; @Schema(description = "分销用户数量(一级)", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") private Integer firstBrokerageUserCount; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByPriceRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByPriceRespVO.java index 91345ea78..d80fb67a2 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByPriceRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByPriceRespVO.java @@ -17,6 +17,6 @@ public class AppBrokerageUserRankByPriceRespVO { private String avatar; @Schema(description = "佣金金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - private Integer brokeragePrice; + private Integer price; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRespVO.java index 04f1a7278..9db6e0cc2 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRespVO.java @@ -8,9 +8,9 @@ import lombok.Data; public class AppBrokerageUserRespVO { @Schema(description = "可用的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2408") - private Integer brokeragePrice; + private Integer price; @Schema(description = "冻结的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "234") - private Integer frozenBrokeragePrice; + private Integer frozenPrice; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java index d619c6926..9307a4f55 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java @@ -43,7 +43,7 @@ public interface BrokerageRecordConvert { .setBizType(bizType.getType()) .setBizId(bizId) .setPrice(brokerage) - .setTotalPrice(user.getBrokeragePrice()) + .setTotalPrice(user.getPrice()) .setTitle(title) .setDescription(StrUtil.format(bizType.getDescription(), String.valueOf(brokerage / 100.0))) .setStatus(status) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java index 27854def6..8588fb972 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java @@ -278,7 +278,7 @@ public interface TradeOrderConvert { default BrokerageAddReqBO convert(TradeOrderItemDO item, ProductSkuRespDTO sku) { return new BrokerageAddReqBO().setBizId(String.valueOf(item.getId())) .setBasePrice(item.getPayPrice() * item.getCount()) - .setFirstBrokeragePrice(sku.getSubCommissionFirstPrice()) - .setSecondBrokeragePrice(sku.getSubCommissionSecondPrice()); + .setFirstFixedPrice(sku.getSubCommissionFirstPrice()) + .setSecondFixedPrice(sku.getSubCommissionSecondPrice()); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/BrokerageUserDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/BrokerageUserDO.java index 09ad6d72d..1773e41e7 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/BrokerageUserDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/BrokerageUserDO.java @@ -8,7 +8,6 @@ import lombok.*; import java.time.LocalDateTime; -// TODO @疯狂:因为独立了表,是不是可以把字段的 brokerage 去掉了哈? /** * 分销用户 DO * @@ -55,10 +54,10 @@ public class BrokerageUserDO extends BaseDO { /** * 可用佣金 */ - private Integer brokeragePrice; + private Integer price; /** * 冻结佣金 */ - private Integer frozenBrokeragePrice; + private Integer frozenPrice; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java index 2d536bb88..2f7d1d19c 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java @@ -31,10 +31,10 @@ public interface BrokerageUserMapper extends BaseMapperX { * @param id 用户编号 * @param incrCount 增加佣金(正数) */ - default void updateBrokeragePriceIncr(Long id, Integer incrCount) { + default void updatePriceIncr(Long id, Integer incrCount) { Assert.isTrue(incrCount > 0); LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() - .setSql(" brokerage_price = brokerage_price + " + incrCount) + .setSql(" price = price + " + incrCount) .eq(BrokerageUserDO::getId, id); update(null, lambdaUpdateWrapper); } @@ -46,10 +46,10 @@ public interface BrokerageUserMapper extends BaseMapperX { * @param id 用户编号 * @param incrCount 增加佣金(负数) */ - default void updateBrokeragePriceDecr(Long id, Integer incrCount) { + default void updatePriceDecr(Long id, Integer incrCount) { Assert.isTrue(incrCount < 0); LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() - .setSql(" brokerage_price = brokerage_price + " + incrCount) // 负数,所以使用 + 号 + .setSql(" price = price + " + incrCount) // 负数,所以使用 + 号 .eq(BrokerageUserDO::getId, id); update(null, lambdaUpdateWrapper); } @@ -60,10 +60,10 @@ public interface BrokerageUserMapper extends BaseMapperX { * @param id 用户编号 * @param incrCount 增加冻结佣金(正数) */ - default void updateFrozenBrokeragePriceIncr(Long id, Integer incrCount) { + default void updateFrozenPriceIncr(Long id, Integer incrCount) { Assert.isTrue(incrCount > 0); LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() - .setSql(" frozen_brokerage_price = frozen_brokerage_price + " + incrCount) + .setSql(" frozen_price = frozen_price + " + incrCount) .eq(BrokerageUserDO::getId, id); update(null, lambdaUpdateWrapper); } @@ -75,10 +75,10 @@ public interface BrokerageUserMapper extends BaseMapperX { * @param id 用户编号 * @param incrCount 减少冻结佣金(负数) */ - default void updateFrozenBrokeragePriceDecr(Long id, Integer incrCount) { + default void updateFrozenPriceDecr(Long id, Integer incrCount) { Assert.isTrue(incrCount < 0); LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() - .setSql(" frozen_brokerage_price = frozen_brokerage_price + " + incrCount) // 负数,所以使用 + 号 + .setSql(" frozen_price = frozen_price + " + incrCount) // 负数,所以使用 + 号 .eq(BrokerageUserDO::getId, id); update(null, lambdaUpdateWrapper); } @@ -90,13 +90,13 @@ public interface BrokerageUserMapper extends BaseMapperX { * @param incrCount 减少冻结佣金(负数) * @return 更新条数 */ - default int updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(Long id, Integer incrCount) { + default int updateFrozenPriceDecrAndPriceIncr(Long id, Integer incrCount) { Assert.isTrue(incrCount < 0); LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() - .setSql(" frozen_brokerage_price = frozen_brokerage_price + " + incrCount + // 负数,所以使用 + 号 - ", brokerage_price = brokerage_price + " + -incrCount) // 负数,所以使用 - 号 + .setSql(" frozen_price = frozen_price + " + incrCount + // 负数,所以使用 + 号 + ", price = price + " + -incrCount) // 负数,所以使用 - 号 .eq(BrokerageUserDO::getId, id) - .ge(BrokerageUserDO::getFrozenBrokeragePrice, -incrCount); // cas 逻辑 + .ge(BrokerageUserDO::getFrozenPrice, -incrCount); // cas 逻辑 return update(null, lambdaUpdateWrapper); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java index 510960beb..07e07817e 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java @@ -28,10 +28,10 @@ public class BrokerageAddReqBO { /** * 一级佣金(固定) */ - private Integer firstBrokeragePrice; + private Integer firstFixedPrice; /** * 二级佣金(固定) */ - private Integer secondBrokeragePrice; + private Integer secondFixedPrice; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java index 1a0cf4fe7..960b45ae5 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java @@ -72,7 +72,7 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { return; } // 1.2 计算一级分佣 - addBrokerage(firstUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageFirstPercent(), BrokerageAddReqBO::getFirstBrokeragePrice, bizType); + addBrokerage(firstUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageFirstPercent(), BrokerageAddReqBO::getFirstFixedPrice, bizType); // 2.1 获得二级推广员 if (firstUser.getBindUserId() == null) { @@ -83,7 +83,7 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { return; } // 2.2 计算二级分佣 - addBrokerage(secondUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageSecondPercent(), BrokerageAddReqBO::getSecondBrokeragePrice, bizType); + addBrokerage(secondUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageSecondPercent(), BrokerageAddReqBO::getSecondFixedPrice, bizType); } @Override @@ -105,24 +105,24 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { // 2. 更新用户的佣金 if (BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus().equals(record.getStatus())) { - brokerageUserService.updateUserFrozenBrokeragePrice(userId, -record.getPrice()); + brokerageUserService.updateUserFrozenPrice(userId, -record.getPrice()); } else if (BrokerageRecordStatusEnum.SETTLEMENT.getStatus().equals(record.getStatus())) { - brokerageUserService.updateUserBrokeragePrice(userId, -record.getPrice()); + brokerageUserService.updateUserPrice(userId, -record.getPrice()); } } /** * 计算佣金 * - * @param basePrice 佣金基数 - * @param percent 佣金比例 - * @param fixedBrokeragePrice 固定佣金 + * @param basePrice 佣金基数 + * @param percent 佣金比例 + * @param fixedPrice 固定佣金 * @return 佣金 */ - int calculateBrokeragePrice(Integer basePrice, Integer percent, Integer fixedBrokeragePrice) { + int calculatePrice(Integer basePrice, Integer percent, Integer fixedPrice) { // 1. 优先使用固定佣金 - if (fixedBrokeragePrice != null && fixedBrokeragePrice > 0) { - return ObjectUtil.defaultIfNull(fixedBrokeragePrice, 0); + if (fixedPrice != null && fixedPrice > 0) { + return ObjectUtil.defaultIfNull(fixedPrice, 0); } // 2. 根据比例计算佣金 if (basePrice != null && basePrice > 0 && percent != null && percent > 0) { @@ -134,15 +134,15 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { /** * 增加用户佣金 * - * @param user 用户 - * @param list 佣金增加参数列表 - * @param brokerageFrozenDays 冻结天数 - * @param brokeragePercent 佣金比例 - * @param FixedBrokeragePriceFun 固定佣金 - * @param bizType 业务类型 + * @param user 用户 + * @param list 佣金增加参数列表 + * @param brokerageFrozenDays 冻结天数 + * @param brokeragePercent 佣金比例 + * @param fixedPriceFun 固定佣金 + * @param bizType 业务类型 */ private void addBrokerage(BrokerageUserDO user, List list, Integer brokerageFrozenDays, - Integer brokeragePercent, Function FixedBrokeragePriceFun, + Integer brokeragePercent, Function fixedPriceFun, BrokerageRecordBizTypeEnum bizType) { // 1.1 处理冻结时间 LocalDateTime unfreezeTime = null; @@ -153,7 +153,7 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { int totalBrokerage = 0; List records = new ArrayList<>(); for (BrokerageAddReqBO item : list) { - int brokeragePerItem = calculateBrokeragePrice(item.getBasePrice(), brokeragePercent, FixedBrokeragePriceFun.apply(item)); + int brokeragePerItem = calculatePrice(item.getBasePrice(), brokeragePercent, fixedPriceFun.apply(item)); if (brokeragePerItem <= 0) { continue; } @@ -169,9 +169,9 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { // 2. 更新用户佣金 if (brokerageFrozenDays != null && brokerageFrozenDays > 0) { // 更新用户冻结佣金 - brokerageUserService.updateUserFrozenBrokeragePrice(user.getId(), totalBrokerage); + brokerageUserService.updateUserFrozenPrice(user.getId(), totalBrokerage); } else { // 更新用户可用佣金 - brokerageUserService.updateUserBrokeragePrice(user.getId(), totalBrokerage); + brokerageUserService.updateUserPrice(user.getId(), totalBrokerage); } } @@ -218,7 +218,7 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { } // 更新用户冻结佣金 - brokerageUserService.updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(record.getUserId(), -record.getPrice()); + brokerageUserService.updateFrozenPriceDecrAndPriceIncr(record.getUserId(), -record.getPrice()); log.info("[unfreezeRecord][record({}) 更新为已结算成功]", record.getId()); return true; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java index 5ba7eb4c1..c26cfb6e3 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java @@ -65,26 +65,26 @@ public interface BrokerageUserService { /** * 更新用户佣金 * - * @param id 用户编号 - * @param brokeragePrice 用户可用佣金 + * @param id 用户编号 + * @param price 用户可用佣金 */ - void updateUserBrokeragePrice(Long id, Integer brokeragePrice); + void updateUserPrice(Long id, Integer price); /** * 更新用户冻结佣金 * - * @param id 用户编号 - * @param frozenBrokeragePrice 用户冻结佣金 + * @param id 用户编号 + * @param frozenPrice 用户冻结佣金 */ - void updateUserFrozenBrokeragePrice(Long id, Integer frozenBrokeragePrice); + void updateUserFrozenPrice(Long id, Integer frozenPrice); /** * 更新用户冻结佣金(减少), 更新用户佣金(增加) * - * @param id 用户编号 - * @param frozenBrokeragePrice 减少冻结佣金(负数) + * @param id 用户编号 + * @param frozenPrice 减少冻结佣金(负数) */ - void updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(Long id, Integer frozenBrokeragePrice); + void updateFrozenPriceDecrAndPriceIncr(Long id, Integer frozenPrice); /** * 获得推广用户数量(一级) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java index a09192ed6..33f81602d 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java @@ -14,8 +14,8 @@ import java.util.List; import java.util.Optional; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.BROKERAGE_USER_FROZEN_PRICE_NOT_ENOUGH; import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.BROKERAGE_USER_NOT_EXISTS; -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.USER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH; /** * 分销用户 Service 实现类 @@ -74,29 +74,29 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { } @Override - public void updateUserBrokeragePrice(Long id, Integer brokeragePrice) { - if (brokeragePrice > 0) { - brokerageUserMapper.updateBrokeragePriceIncr(id, brokeragePrice); - } else if (brokeragePrice < 0) { - brokerageUserMapper.updateBrokeragePriceDecr(id, brokeragePrice); + public void updateUserPrice(Long id, Integer price) { + if (price > 0) { + brokerageUserMapper.updatePriceIncr(id, price); + } else if (price < 0) { + brokerageUserMapper.updatePriceDecr(id, price); } } @Override - public void updateUserFrozenBrokeragePrice(Long id, Integer frozenBrokeragePrice) { - if (frozenBrokeragePrice > 0) { - brokerageUserMapper.updateFrozenBrokeragePriceIncr(id, frozenBrokeragePrice); - } else if (frozenBrokeragePrice < 0) { - brokerageUserMapper.updateFrozenBrokeragePriceDecr(id, frozenBrokeragePrice); + public void updateUserFrozenPrice(Long id, Integer frozenPrice) { + if (frozenPrice > 0) { + brokerageUserMapper.updateFrozenPriceIncr(id, frozenPrice); + } else if (frozenPrice < 0) { + brokerageUserMapper.updateFrozenPriceDecr(id, frozenPrice); } } @Override - public void updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(Long id, Integer frozenBrokeragePrice) { - Assert.isTrue(frozenBrokeragePrice < 0); - int updateRows = brokerageUserMapper.updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(id, frozenBrokeragePrice); + public void updateFrozenPriceDecrAndPriceIncr(Long id, Integer frozenPrice) { + Assert.isTrue(frozenPrice < 0); + int updateRows = brokerageUserMapper.updateFrozenPriceDecrAndPriceIncr(id, frozenPrice); if (updateRows == 0) { - throw exception(USER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH); + throw exception(BROKERAGE_USER_FROZEN_PRICE_NOT_ENOUGH); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImplTest.java b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImplTest.java index 00ff04d6d..abf2b37c1 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImplTest.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImplTest.java @@ -79,38 +79,38 @@ public class BrokerageRecordServiceImplTest extends BaseDbUnitTest { } @Test - public void testCalculateBrokeragePrice_useFixedBrokeragePrice() { + public void testCalculatePrice_useFixedPrice() { // mock 数据 Integer payPrice = randomInteger(); Integer percent = randomInt(1, 101); - Integer fixedBrokeragePrice = randomInt(); + Integer fixedPrice = randomInt(); // 调用 - int brokerage = brokerageRecordService.calculateBrokeragePrice(payPrice, percent, fixedBrokeragePrice); + int brokerage = brokerageRecordService.calculatePrice(payPrice, percent, fixedPrice); // 断言 - assertEquals(brokerage, fixedBrokeragePrice); + assertEquals(brokerage, fixedPrice); } @Test - public void testCalculateBrokeragePrice_usePercent() { + public void testCalculatePrice_usePercent() { // mock 数据 Integer payPrice = randomInteger(); Integer percent = randomInt(1, 101); - Integer skuBrokeragePrice = randomEle(new Integer[]{0, null}); - System.out.println("skuBrokeragePrice=" + skuBrokeragePrice); + Integer fixedPrice = randomEle(new Integer[]{0, null}); + System.out.println("fixedPrice=" + fixedPrice); // 调用 - int brokerage = brokerageRecordService.calculateBrokeragePrice(payPrice, percent, skuBrokeragePrice); + int brokerage = brokerageRecordService.calculatePrice(payPrice, percent, fixedPrice); // 断言 assertEquals(brokerage, NumberUtil.div(NumberUtil.mul(payPrice, percent), 100, 0, RoundingMode.DOWN).intValue()); } @Test - public void testCalculateBrokeragePrice_equalsZero() { + public void testCalculatePrice_equalsZero() { // mock 数据 Integer payPrice = null; Integer percent = null; - Integer skuBrokeragePrice = null; + Integer fixedPrice = null; // 调用 - int brokerage = brokerageRecordService.calculateBrokeragePrice(payPrice, percent, skuBrokeragePrice); + int brokerage = brokerageRecordService.calculatePrice(payPrice, percent, fixedPrice); // 断言 assertEquals(brokerage, 0); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql b/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql index eafad666f..4c0e0fcea 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql @@ -128,19 +128,19 @@ CREATE TABLE IF NOT EXISTS "trade_after_sale_log" ( CREATE TABLE IF NOT EXISTS "trade_brokerage_user" ( - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "bind_user_id" bigint NOT NULL, - "bind_user_time" varchar, - "brokerage_enabled" bit NOT NULL, - "brokerage_time" varchar, - "brokerage_price" int NOT NULL, - "frozen_brokerage_price" int NOT NULL, - "creator" varchar DEFAULT '', - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar DEFAULT '', - "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - "tenant_id" bigint NOT NULL DEFAULT '0', + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "bind_user_id" bigint NOT NULL, + "bind_user_time" varchar, + "brokerage_enabled" bit NOT NULL, + "brokerage_time" varchar, + "price" int NOT NULL, + "frozen_price" int NOT NULL, + "creator" varchar DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT '0', PRIMARY KEY ("id") ) COMMENT '分销用户'; CREATE TABLE IF NOT EXISTS "trade_brokerage_record" From 6ef36d5ca6277d9ad64a824e9af8ec6aefd71a70 Mon Sep 17 00:00:00 2001 From: owen Date: Fri, 8 Sep 2023 23:33:02 +0800 Subject: [PATCH 36/50] =?UTF-8?q?trade:=20=E5=A2=9E=E5=8A=A0=E5=88=86?= =?UTF-8?q?=E9=94=80=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../trade/api/brokerage/BrokerageApi.java | 30 +++++++++++ .../api/brokerage/dto/BrokerageUserDTO.java | 51 +++++++++++++++++++ .../trade/api/brokerage/BrokerageApiImpl.java | 33 ++++++++++++ .../brokerage/user/BrokerageUserConvert.java | 3 ++ .../yudao-module-member-biz/pom.xml | 5 ++ .../app/user/AppMemberUserController.java | 9 +++- 6 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApi.java create mode 100644 yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/dto/BrokerageUserDTO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApiImpl.java diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApi.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApi.java new file mode 100644 index 000000000..4952e5cad --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApi.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.trade.api.brokerage; + +import cn.iocoder.yudao.module.trade.api.brokerage.dto.BrokerageUserDTO; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageBindModeEnum; + +/** + * 分销 API 接口 + * + * @author owen + */ +public interface BrokerageApi { + + /** + * 获得分销用户 + * + * @param userId 用户编号 + * @return 分销用户信息 + */ + BrokerageUserDTO getBrokerageUser(Long userId); + + /** + * 绑定推广员 + * + * @param userId 用户编号 + * @param bindUserId 推广员编号 + * @param bindMode 绑定模式 {@link BrokerageBindModeEnum} + * @return 是否绑定 + */ + boolean bindUser(Long userId, Long bindUserId, Integer bindMode); +} diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/dto/BrokerageUserDTO.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/dto/BrokerageUserDTO.java new file mode 100644 index 000000000..864abe148 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/dto/BrokerageUserDTO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.trade.api.brokerage.dto; + +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 分销用户 DTO + * + * @author owen + */ +@Data +public class BrokerageUserDTO { + + /** + * 用户编号 + *

+ * 对应 MemberUserDO 的 id 字段 + */ + private Long id; + + /** + * 推广员编号 + *

+ * 关联 MemberUserDO 的 id 字段 + */ + private Long bindUserId; + /** + * 推广员绑定时间 + */ + private LocalDateTime bindUserTime; + + /** + * 推广资格 + */ + private Boolean brokerageEnabled; + /** + * 成为分销员时间 + */ + private LocalDateTime brokerageTime; + + /** + * 可用佣金 + */ + private Integer price; + /** + * 冻结佣金 + */ + private Integer frozenPrice; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApiImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApiImpl.java new file mode 100644 index 000000000..1bb520734 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApiImpl.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.trade.api.brokerage; + +import cn.iocoder.yudao.module.trade.api.brokerage.dto.BrokerageUserDTO; +import cn.iocoder.yudao.module.trade.convert.brokerage.user.BrokerageUserConvert; +import cn.iocoder.yudao.module.trade.service.brokerage.user.BrokerageUserService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; + +/** + * 分销 API 接口实现类 + * + * @author owen + */ +@Service +@Validated +public class BrokerageApiImpl implements BrokerageApi { + + @Resource + private BrokerageUserService brokerageUserService; + + public BrokerageUserDTO getBrokerageUser(Long userId) { + return BrokerageUserConvert.INSTANCE.convertDTO(brokerageUserService.getBrokerageUser(userId)); + } + + @Override + public boolean bindUser(Long userId, Long bindUserId, Integer bindMode) { + // todo 待实现 + return false; + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/BrokerageUserConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/BrokerageUserConvert.java index c4a31cc98..01d0be8c8 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/BrokerageUserConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/BrokerageUserConvert.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.convert.brokerage.user; import cn.hutool.core.map.MapUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.trade.api.brokerage.dto.BrokerageUserDTO; import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.BrokerageUserRespVO; import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO; import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO; @@ -58,4 +59,6 @@ public interface BrokerageUserConvert { } return result; } + + BrokerageUserDTO convertDTO(BrokerageUserDO brokerageUser); } diff --git a/yudao-module-member/yudao-module-member-biz/pom.xml b/yudao-module-member/yudao-module-member-biz/pom.xml index a5eda05b0..1df7e7be8 100644 --- a/yudao-module-member/yudao-module-member-biz/pom.xml +++ b/yudao-module-member/yudao-module-member-biz/pom.xml @@ -33,6 +33,11 @@ yudao-module-infra-api ${revision} + + cn.iocoder.boot + yudao-module-trade-api + ${revision} + diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java index 4d15aad1f..461a1a5c5 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java @@ -8,6 +8,8 @@ import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; import cn.iocoder.yudao.module.member.service.level.MemberLevelService; import cn.iocoder.yudao.module.member.service.user.MemberUserService; +import cn.iocoder.yudao.module.trade.api.brokerage.BrokerageApi; +import cn.iocoder.yudao.module.trade.api.brokerage.dto.BrokerageUserDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; @@ -16,6 +18,7 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.Valid; +import java.util.Optional; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @@ -33,14 +36,18 @@ public class AppMemberUserController { @Resource private MemberLevelService levelService; + @Resource + private BrokerageApi brokerageApi; + @GetMapping("/get") @Operation(summary = "获得基本信息") @PreAuthenticated public CommonResult getUserInfo() { MemberUserDO user = userService.getUser(getLoginUserId()); MemberLevelDO level = levelService.getLevel(user.getLevelId()); + BrokerageUserDTO brokerageUser = brokerageApi.getBrokerageUser(user.getId()); return success(MemberUserConvert.INSTANCE.convert(user, level) - .setBrokerageEnabled(true) // TODO @疯狂:这里我先写死,后面改成 db 返回; + .setBrokerageEnabled(Optional.ofNullable(brokerageUser).map(BrokerageUserDTO::getBrokerageEnabled).orElse(false)) ); } From 87c55784c4bd119c28a24c758c8d66b3dbb5fdca Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 9 Sep 2023 01:27:55 +0800 Subject: [PATCH 37/50] =?UTF-8?q?code=20review=EF=BC=9A=E8=90=A5=E9=94=80?= =?UTF-8?q?=E6=B4=BB=E5=8A=A8+=E8=AE=A2=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/common/pojo/CommonResult.java | 8 -- .../api/combination/CombinationRecordApi.java | 4 +- .../api/seckill/SeckillActivityApi.java | 1 - .../dto/SeckillActivityUpdateStockReqDTO.java | 4 + .../api/bargain/BargainActivityApiImpl.java | 2 + .../api/seckill/SeckillActivityApiImpl.java | 11 ++- .../combination/CombinationRecordDO.java | 84 +++++++++++-------- .../seckill/SeckillActivityService.java | 4 +- .../seckill/SeckillActivityServiceImpl.java | 8 +- .../aftersale/TradeAfterSaleController.java | 9 +- .../admin/order/TradeOrderController.java | 9 +- .../app/order/AppTradeOrderController.java | 8 +- .../vo/AppTradeOrderSettlementReqVO.java | 2 + .../dal/redis/no/TradeOrderNoRedisDAO.java | 1 + .../order/TradeOrderUpdateServiceImpl.java | 4 + .../module/pay/api/order/PayOrderApi.java | 2 + .../module/pay/api/order/PayOrderApiImpl.java | 1 - .../service/order/PayOrderServiceImpl.java | 1 + 18 files changed, 96 insertions(+), 67 deletions(-) diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/CommonResult.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/CommonResult.java index 3a974456e..e29292dd8 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/CommonResult.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/CommonResult.java @@ -68,14 +68,6 @@ public class CommonResult implements Serializable { return result; } - public static CommonResult success(T data, String msg) { - CommonResult result = new CommonResult<>(); - result.code = GlobalErrorCodeConstants.SUCCESS.getCode(); - result.data = data; - result.msg = msg; - return result; - } - public static boolean isSuccess(Integer code) { return Objects.equals(code, GlobalErrorCodeConstants.SUCCESS.getCode()); } diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java index c03559785..859eb5c7e 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java @@ -52,7 +52,7 @@ public interface CombinationRecordApi { void validateCombinationLimitCount(Long activityId, Integer count, Integer sumCount); /** - * 更新拼团状态为 成功 + * 更新拼团状态为成功 * * @param userId 用户编号 * @param orderId 订单编号 @@ -60,7 +60,7 @@ public interface CombinationRecordApi { void updateRecordStatusToSuccess(Long userId, Long orderId); /** - * 更新拼团状态为 失败 + * 更新拼团状态为失败 * * @param userId 用户编号 * @param orderId 订单编号 diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java index 09ec051a3..9c5cf1d35 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java @@ -9,7 +9,6 @@ import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateSt */ public interface SeckillActivityApi { - /** * 更新秒杀库存 * diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java index 476ba8e15..df7c5649c 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java @@ -12,6 +12,10 @@ import java.util.List; @Data public class SeckillActivityUpdateStockReqDTO { + // TODO @puhui999:参数校验 + + // TODO @puhui999:秒杀的话,一次只能购买一种商品哈;不能多个哈; + /** * 活动编号 */ diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApiImpl.java index 826b4b2aa..02620c5ec 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApiImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApiImpl.java @@ -23,6 +23,7 @@ public class BargainActivityApiImpl implements BargainActivityApi { @Override public void updateBargainActivityStock(Long activityId, Integer count) { + // TODO @puhui999:可以整个实现到 bargainActivityService 中 // 查询砍价活动 BargainActivityDO activity = bargainActivityService.getBargainActivity(activityId); if (activity == null) { @@ -30,6 +31,7 @@ public class BargainActivityApiImpl implements BargainActivityApi { } // 更新砍价库存 + // TODO @puhui999:考虑下并发更新问题 BargainActivityUpdateReqVO reqVO = new BargainActivityUpdateReqVO(); reqVO.setId(activityId); reqVO.setStock(activity.getStock() - count); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java index 299316aa0..1f5c15755 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java @@ -27,14 +27,19 @@ public class SeckillActivityApiImpl implements SeckillActivityApi { @Resource private SeckillActivityService activityService; + // TODO @puhui:建议这块弄到 activityService 实现哈; + // TODO @puhui:这个方法,要考虑事务性 @Override public void updateSeckillStock(SeckillActivityUpdateStockReqDTO updateStockReqDTO) { + // TODO @puhui999:长方法,最好有 1.1 1.2 2.1 这种步骤哈; SeckillActivityDO seckillActivity = activityService.getSeckillActivity(updateStockReqDTO.getActivityId()); if (seckillActivity.getStock() < updateStockReqDTO.getCount()) { throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); } // 获取活动商品 + // TODO @puhui999:在一个方法里,dos 和 dolist 最好保持一致,要么用 s,要么用 list 哈; List productDOs = activityService.getSeckillProductListByActivityId(updateStockReqDTO.getActivityId()); + // TODO @puhui999:这个是不是搞成 CollectionUtils.convertMultiMap() List items = updateStockReqDTO.getItems(); Map> map = new HashMap<>(); items.forEach(item -> { @@ -49,9 +54,11 @@ public class SeckillActivityApiImpl implements SeckillActivityApi { } }); // 过滤出购买的商品 + // TODO @puhui999:productDOList 可以简化成 productList;一般来说,do 之类不用带着哈,在变量里; List productDOList = CollectionUtils.filterList(productDOs, item -> map.get(item.getSpuId()).contains(item.getSkuId())); Map productDOMap = CollectionUtils.convertMap(items, SeckillActivityUpdateStockReqDTO.Item::getSkuId, p -> p); // 检查活动商品库存是否充足 + // TODO @puhui999:避免 b 这种无业务含义的变量; boolean b = CollectionUtils.anyMatch(productDOList, item -> { SeckillActivityUpdateStockReqDTO.Item item1 = productDOMap.get(item.getSkuId()); return (item.getStock() < item1.getCount()) || (item.getStock() - item1.getCount()) < 0; @@ -59,17 +66,19 @@ public class SeckillActivityApiImpl implements SeckillActivityApi { if (b) { throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); } + // TODO @puhui999:类似 doList,应该和下面的 update 逻辑粘的更紧密一点;so 在空行的时候,应该挪到 74 之后里去;甚至更合理,应该是 79 之后;说白了,逻辑要分块,每个模块涉及的代码要紧密在一起; List doList = CollectionUtils.convertList(productDOList, item -> { item.setStock(item.getStock() - productDOMap.get(item.getSkuId()).getCount()); return item; }); // 更新活动库存 + // TODO @puhui999:考虑下并发更新 seckillActivity.setStock(seckillActivity.getStock() + updateStockReqDTO.getCount()); seckillActivity.setTotalStock(seckillActivity.getTotalStock() - updateStockReqDTO.getCount()); activityService.updateSeckillActivity(seckillActivity); // 更新活动商品库存 - activityService.updateSeckillActivityProductByList(doList); + activityService.updateSeckillActivityProductList(doList); } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationRecordDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationRecordDO.java index 898d2a822..ea851d67e 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationRecordDO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationRecordDO.java @@ -9,6 +9,7 @@ import lombok.*; import java.time.LocalDateTime; +// TODO 芋艿:把字段的顺序,和 do 顺序对齐下 /** * 拼团记录 DO * @@ -27,34 +28,28 @@ import java.time.LocalDateTime; @AllArgsConstructor public class CombinationRecordDO extends BaseDO { + /** + * 编号,主键自增 + */ @TableId private Long id; + /** * 拼团活动编号 + * + * 关联 {@link CombinationActivityDO#getId()} */ private Long activityId; + /** + * 拼团商品单价 + * + * 冗余 {@link CombinationProductDO#getCombinationPrice()} + */ + private Integer combinationPrice; /** * SPU 编号 */ private Long spuId; - /** - * SKU 编号 - */ - private Long skuId; - /** - * 用户编号 - */ - private Long userId; - /** - * 订单编号 - */ - private Long orderId; - /** - * 团长编号 - * - * 关联 {@link CombinationRecordDO#getId()} - */ - private Long headId; /** * 商品名字 */ @@ -64,9 +59,14 @@ public class CombinationRecordDO extends BaseDO { */ private String picUrl; /** - * 拼团商品单价 + * SKU 编号 */ - private Integer combinationPrice; + private Long skuId; + + /** + * 用户编号 + */ + private Long userId; /** * 用户昵称 */ @@ -75,6 +75,13 @@ public class CombinationRecordDO extends BaseDO { * 用户头像 */ private String avatar; + + /** + * 团长编号 + * + * 关联 {@link CombinationRecordDO#getId()} + */ + private Long headId; /** * 开团状态 * @@ -82,23 +89,9 @@ public class CombinationRecordDO extends BaseDO { */ private Integer status; /** - * 是否虚拟成团 + * 订单编号 */ - private Boolean virtualGroup; - /** - * 过期时间 - * - * {@link CombinationRecordDO#getStartTime()} + {@link CombinationActivityDO#getLimitDuration()} 计算 - */ - private LocalDateTime expireTime; - /** - * 开始时间 (订单付款后开始的时间) - */ - private LocalDateTime startTime; - /** - * 结束时间(成团时间/失败时间) - */ - private LocalDateTime endTime; + private Long orderId; /** * 开团需要人数 * @@ -109,5 +102,24 @@ public class CombinationRecordDO extends BaseDO { * 已加入拼团人数 */ private Integer userCount; + /** + * 是否虚拟成团 + */ + private Boolean virtualGroup; + + /** + * 过期时间 + * + * 基于 {@link CombinationRecordDO#getStartTime()} + {@link CombinationActivityDO#getLimitDuration()} 计算 + */ + private LocalDateTime expireTime; + /** + * 开始时间 (订单付款后开始的时间) + */ + private LocalDateTime startTime; + /** + * 结束时间(成团时间/失败时间) + */ + private LocalDateTime endTime; } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java index 052b59561..079470814 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java @@ -43,9 +43,9 @@ public interface SeckillActivityService { /** * 更新秒杀活动商品 * - * @param productDOList 活动商品列表 + * @param productList 活动商品列表 */ - void updateSeckillActivityProductByList(List productDOList); + void updateSeckillActivityProductList(List productList); /** * 关闭秒杀活动 diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java index 17fb9a90f..28f654049 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java @@ -93,8 +93,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { activityList.removeIf(item -> ObjectUtil.equal(item.getId(), activityId)); } // 2.2 过滤出所有 configIds 有交集的活动,判断是否存在重叠 - List activityDOs = filterList(activityList, s -> containsAny(s.getConfigIds(), configIds)); - if (isNotEmpty(activityDOs)) { + List conflictActivityList = filterList(activityList, s -> containsAny(s.getConfigIds(), configIds)); + if (isNotEmpty(conflictActivityList)) { throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS); } } @@ -150,8 +150,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { } @Override - public void updateSeckillActivityProductByList(List productDOList) { - seckillProductMapper.updateBatch(productDOList); + public void updateSeckillActivityProductList(List productList) { + seckillProductMapper.updateBatch(productList); } /** diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java index 60afbc0ab..fec1fc1aa 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java @@ -36,7 +36,6 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.AFTER_SALE_NOT_FOUND; @Tag(name = "管理后台 - 售后订单") @RestController @@ -77,9 +76,11 @@ public class TradeAfterSaleController { public CommonResult getOrderDetail(@RequestParam("id") Long id) { // 查询订单 TradeAfterSaleDO afterSale = afterSaleService.getAfterSale(id); - if (afterSale == null) { - return success(null, AFTER_SALE_NOT_FOUND.getMsg()); - } + // TODO @puhui999:这里建议改成,如果为 null,直接返回 success null;主要查询操作,尽量不要有非空的提示哈;交给前端处理; +// if (afterSale == null) { +// return success(null, AFTER_SALE_NOT_FOUND.getMsg()); +// } + // 查询订单 TradeOrderDO order = tradeOrderQueryService.getOrder(afterSale.getOrderId()); // 查询订单项 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java index 728c70c67..546519a1b 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java @@ -25,7 +25,6 @@ import java.util.Map; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_NOT_FOUND; @Tag(name = "管理后台 - 交易订单") @RestController @@ -68,9 +67,11 @@ public class TradeOrderController { public CommonResult getOrderDetail(@RequestParam("id") Long id) { // 查询订单 TradeOrderDO order = tradeOrderQueryService.getOrder(id); - if (order == null) { - return success(null, ORDER_NOT_FOUND.getMsg()); - } + // TODO @puhui999:这里建议改成,如果为 null,直接返回 success null;主要查询操作,尽量不要有非空的提示哈;交给前端处理; +// if (order == null) { +// return success(null, ORDER_NOT_FOUND.getMsg()); +// } + // 查询订单项 List orderItems = tradeOrderQueryService.getOrderItemListByOrderId(id); // orderLog diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java index a65836c33..a2ea2f79f 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java @@ -33,7 +33,6 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_NOT_FOUND; @Tag(name = "用户 App - 交易订单") @RestController @@ -82,9 +81,10 @@ public class AppTradeOrderController { public CommonResult getOrder(@RequestParam("id") Long id) { // 查询订单 TradeOrderDO order = tradeOrderQueryService.getOrder(getLoginUserId(), id); - if (order == null) { - return success(null, ORDER_NOT_FOUND.getMsg()); - } + // TODO @puhui999:这里建议改成,如果为 null,直接返回 success null;主要查询操作,尽量不要有非空的提示哈;交给前端处理; +// if (order == null) { +// return success(null, ORDER_NOT_FOUND.getMsg()); +// } // 查询订单项 List orderItems = tradeOrderQueryService.getOrderItemListByOrderId(order.getId()); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java index 6b8c14725..929a2ec19 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java @@ -50,6 +50,7 @@ public class AppTradeOrderSettlementReqVO { private Long seckillActivityId; // ========== 拼团活动相关字段 ========== + // TODO @puhui999:是不是拼团记录的编号哈? @Schema(description = "拼团活动编号", example = "1024") private Long combinationActivityId; @@ -57,6 +58,7 @@ public class AppTradeOrderSettlementReqVO { private Long combinationHeadId; // ========== 砍价活动相关字段 ========== + // TODO @puhui999:是不是砍价记录的编号哈? @Schema(description = "砍价活动编号", example = "123") private Long bargainActivityId; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/no/TradeOrderNoRedisDAO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/no/TradeOrderNoRedisDAO.java index 781975aca..8ad619269 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/no/TradeOrderNoRedisDAO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/no/TradeOrderNoRedisDAO.java @@ -15,6 +15,7 @@ import java.time.LocalDateTime; */ @Repository public class TradeOrderNoRedisDAO { + public static final String TRADE_ORDER_NO_PREFIX = "O"; @Resource diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index 56e887b42..94fdfe17e 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -561,6 +561,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { } @Override + // TODO @puhui999:考虑事务性 public void updateOrderPrice(TradeOrderUpdatePriceReqVO reqVO) { // 校验交易订单 TradeOrderDO order = validateOrderExists(reqVO.getId()); @@ -571,6 +572,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { throw exception(ORDER_UPDATE_PRICE_FAIL_EQUAL); } + // TODO @puhui999:应该是按照 payPrice 分配;并且要考虑取余问题;payPrice 也要考虑,item 里的 List itemDOs = tradeOrderItemMapper.selectListByOrderId(order.getId()); // TradeOrderItemDO 需要做 adjustPrice 的分摊 int price = reqVO.getAdjustPrice() / itemDOs.size(); @@ -578,8 +580,10 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { item.setAdjustPrice(price); }); // 更新 TradeOrderItem + // TODO @puhui999:不要整个对象去更新哈;应该 new 一下; tradeOrderItemMapper.updateBatch(itemDOs); // 更新订单 + // TODO @puhui999:要考虑多次修改价格,不能单单的 payPrice + 价格; TradeOrderDO update = TradeOrderConvert.INSTANCE.convert(reqVO); update.setPayPrice(update.getPayPrice() + update.getAdjustPrice()); // TODO @芋艿:改价时,赠送的积分,要不要做改动??? diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java index 94a79ea3d..b46f19534 100644 --- a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java @@ -29,6 +29,7 @@ public interface PayOrderApi { */ PayOrderRespDTO getOrder(Long id); + // TODO @puhui999:可以去掉 byId;然后 payOrderId 参数改成 id; /** * 更新支付订单价格 * @@ -36,4 +37,5 @@ public interface PayOrderApi { * @param payPrice 支付单价格 */ void updatePayOrderPriceById(Long payOrderId, Integer payPrice); + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java index 18c9ff3ef..1740e3bba 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java @@ -36,5 +36,4 @@ public class PayOrderApiImpl implements PayOrderApi { payOrderService.updatePayOrderPriceById(payOrderId, payPrice); } - } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java index 46d83d32c..2a6750e5d 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java @@ -413,6 +413,7 @@ public class PayOrderServiceImpl implements PayOrderService { @Override public void updatePayOrderPriceById(Long payOrderId, Integer payPrice) { + // TODO @puhui999:不能直接这样修改哈;应该只有未支付状态的订单才可以改;另外,如果价格如果没变,可以直接 return 哈; PayOrderDO order = orderMapper.selectById(payOrderId); if (order == null) { throw exception(ORDER_NOT_FOUND); From f97c7a0f6e14decc794b538d2611dd8a6a4f138f Mon Sep 17 00:00:00 2001 From: owen Date: Sat, 9 Sep 2023 01:46:42 +0800 Subject: [PATCH 38/50] =?UTF-8?q?trade:=20=E5=88=86=E9=94=80=E4=B8=9A?= =?UTF-8?q?=E5=8A=A1=E7=BB=91=E5=AE=9A=E6=8E=A8=E5=B9=BF=E5=91=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../trade/api/brokerage/BrokerageApi.java | 5 +- .../trade/enums/ErrorCodeConstants.java | 6 ++ .../trade/api/brokerage/BrokerageApiImpl.java | 5 +- .../brokerage/AppBrokerageUserController.java | 17 +++- .../vo/user/AppBrokerageUserBindReqVO.java | 17 ++++ .../brokerage/user/BrokerageUserService.java | 10 ++ .../user/BrokerageUserServiceImpl.java | 92 ++++++++++++++++++- 7 files changed, 140 insertions(+), 12 deletions(-) create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserBindReqVO.java diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApi.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApi.java index 4952e5cad..4d7314d4b 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApi.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApi.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.trade.api.brokerage; import cn.iocoder.yudao.module.trade.api.brokerage.dto.BrokerageUserDTO; -import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageBindModeEnum; /** * 分销 API 接口 @@ -23,8 +22,8 @@ public interface BrokerageApi { * * @param userId 用户编号 * @param bindUserId 推广员编号 - * @param bindMode 绑定模式 {@link BrokerageBindModeEnum} + * @param isNewUser 是否为新用户 * @return 是否绑定 */ - boolean bindUser(Long userId, Long bindUserId, Integer bindMode); + boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser); } diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java index fa5be50b7..236e7af23 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java @@ -78,5 +78,11 @@ public interface ErrorCodeConstants { // ========== 分销用户 模块 1011007000 ========== ErrorCode BROKERAGE_USER_NOT_EXISTS = new ErrorCode(1011007000, "分销用户不存在"); ErrorCode BROKERAGE_USER_FROZEN_PRICE_NOT_ENOUGH = new ErrorCode(1011007001, "用户冻结佣金({})数量不足"); + ErrorCode BROKERAGE_BIND_SELF = new ErrorCode(1011007002, "不能绑定自己"); + ErrorCode BROKERAGE_BIND_USER_NOT_ENABLED = new ErrorCode(1011007003, "绑定用户没有推广资格"); + ErrorCode BROKERAGE_BIND_CONDITION_ADMIN = new ErrorCode(1011007004, "仅可在后台绑定推广员"); + ErrorCode BROKERAGE_BIND_MODE_REGISTER = new ErrorCode(1011007005, "只有在注册时可以绑定"); + ErrorCode BROKERAGE_BIND_OVERRIDE = new ErrorCode(1011007006, "已绑定了推广人"); + ErrorCode BROKERAGE_BIND_LOOP = new ErrorCode(1011007007, "下级不能绑定自己的上级"); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApiImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApiImpl.java index 1bb520734..4a534fa22 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApiImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApiImpl.java @@ -25,9 +25,8 @@ public class BrokerageApiImpl implements BrokerageApi { } @Override - public boolean bindUser(Long userId, Long bindUserId, Integer bindMode) { - // todo 待实现 - return false; + public boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser) { + return brokerageUserService.bindUser(userId, bindUserId, isNewUser); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java index ecbb7de45..ef1634098 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java @@ -4,21 +4,22 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.*; +import cn.iocoder.yudao.module.trade.service.brokerage.user.BrokerageUserService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import javax.validation.Valid; import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static java.util.Arrays.asList; @Tag(name = "用户 APP - 分销用户") @@ -27,6 +28,8 @@ import static java.util.Arrays.asList; @Validated @Slf4j public class AppBrokerageUserController { + @Resource + private BrokerageUserService brokerageUserService; // TODO 芋艿:临时 mock => @GetMapping("/get") @@ -120,4 +123,10 @@ public class AppBrokerageUserController { return success(1); } + @PutMapping("/bind-user") + @Operation(summary = "绑定推广员") + public CommonResult getBrokerageUserRankByPrice(@Valid AppBrokerageUserBindReqVO reqVO) { + return success(brokerageUserService.bindUser(getLoginUserId(), reqVO.getBindUserId(), false)); + } + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserBindReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserBindReqVO.java new file mode 100644 index 000000000..f2a14996a --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserBindReqVO.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Schema(description = "应用 App - 绑定推广员 Request VO") +@Data +public class AppBrokerageUserBindReqVO extends PageParam { + + @Schema(description = "推广员编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "推广员编号不能为空") + private Long bindUserId; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java index c26cfb6e3..61aa8bde0 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java @@ -93,4 +93,14 @@ public interface BrokerageUserService { * @return 推广用户数量 */ Long getCountByBindUserId(Long bindUserId); + + /** + * 【会员】绑定推广员 + * + * @param userId 用户编号 + * @param bindUserId 推广员编号 + * @param isNewUser 是否为新用户 + * @return 是否绑定 + */ + boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java index 33f81602d..7666da49b 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java @@ -1,21 +1,27 @@ package cn.iocoder.yudao.module.trade.service.brokerage.user; import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.BooleanUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.BrokerageUserPageReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user.BrokerageUserMapper; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageBindModeEnum; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageEnabledConditionEnum; +import cn.iocoder.yudao.module.trade.service.config.TradeConfigService; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; +import java.util.Objects; import java.util.Optional; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.BROKERAGE_USER_FROZEN_PRICE_NOT_ENOUGH; -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.BROKERAGE_USER_NOT_EXISTS; +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; /** * 分销用户 Service 实现类 @@ -29,6 +35,9 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { @Resource private BrokerageUserMapper brokerageUserMapper; + @Resource + private TradeConfigService tradeConfigService; + @Override public BrokerageUserDO getBrokerageUser(Long id) { return brokerageUserMapper.selectById(id); @@ -105,4 +114,83 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { return brokerageUserMapper.selectCount(BrokerageUserDO::getBindUserId, bindUserId); } + @Override + public boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser) { + if (userId == null) { + throw exception(0); + } + + boolean isInsert = false; + BrokerageUserDO brokerageUser = brokerageUserMapper.selectById(userId); + // 分销用户不存在的情况:1.新注册 2.旧数据 3.分销功能关闭后又打开 + if (brokerageUser == null) { + isInsert = true; + brokerageUser = new BrokerageUserDO().setId(userId).setBrokerageEnabled(false).setPrice(0).setFrozenPrice(0); + } + + // 校验能否绑定 + boolean validated = validateCanBindUser(brokerageUser, bindUserId, isNewUser); + if (!validated) { + return false; + } + + if (isInsert) { + Integer enabledCondition = tradeConfigService.getTradeConfig().getBrokerageEnabledCondition(); + if (BrokerageEnabledConditionEnum.ALL.getCondition().equals(enabledCondition)) { + // 人人分销:用户默认就有分销资格 + brokerageUser.setBrokerageEnabled(true).setBindUserTime(LocalDateTime.now()); + } + brokerageUserMapper.insert(brokerageUser); + } else { + brokerageUserMapper.updateById(new BrokerageUserDO().setId(userId) + .setBindUserId(bindUserId).setBindUserTime(LocalDateTime.now())); + } + return true; + } + + private boolean validateCanBindUser(BrokerageUserDO user, Long bindUserId, Boolean isNewUser) { + if (bindUserId == null) { + return false; + } + + // 校验分销功能是否启用 + TradeConfigDO tradeConfig = tradeConfigService.getTradeConfig(); + if (tradeConfig == null || !BooleanUtil.isTrue(tradeConfig.getBrokerageEnabled())) { + return false; + } + + // 校验绑定自己 + if (Objects.equals(user.getId(), bindUserId)) { + throw exception(BROKERAGE_BIND_SELF); + } + + // 校验要绑定的用户有无推广资格 + BrokerageUserDO bindUser = brokerageUserMapper.selectById(bindUserId); + if (bindUser == null || !BooleanUtil.isTrue(bindUser.getBrokerageEnabled())) { + throw exception(BROKERAGE_BIND_USER_NOT_ENABLED); + } + + // 校验分佣模式:仅可后台手动设置推广员 + if (BrokerageEnabledConditionEnum.ADMIN.getCondition().equals(tradeConfig.getBrokerageEnabledCondition())) { + throw exception(BROKERAGE_BIND_CONDITION_ADMIN); + } + + // 校验分销关系绑定模式 + if (BrokerageBindModeEnum.REGISTER.getMode().equals(tradeConfig.getBrokerageBindMode())) { + if (!BooleanUtil.isTrue(isNewUser)) { + throw exception(BROKERAGE_BIND_MODE_REGISTER); // 只有在注册时可以绑定 + } + } else if (BrokerageBindModeEnum.ANYTIME.getMode().equals(tradeConfig.getBrokerageBindMode())) { + if (user.getBindUserId() != null) { + throw exception(BROKERAGE_BIND_OVERRIDE); // 已绑定了推广人 + } + } + + // A->B->A:下级不能绑定自己的上级, A->B->C->A可以!! + if (Objects.equals(user.getId(), bindUser.getBindUserId())) { + throw exception(BROKERAGE_BIND_LOOP); + } + return true; + } + } From 259734964de364fd6d58c1db4cecd0fc3b126246 Mon Sep 17 00:00:00 2001 From: owen Date: Sat, 9 Sep 2023 01:54:48 +0800 Subject: [PATCH 39/50] =?UTF-8?q?trade:=20=E5=88=86=E9=94=80=E4=B8=9A?= =?UTF-8?q?=E5=8A=A1=E5=90=8E=E5=8F=B0=E5=8A=9F=E8=83=BD=EF=BC=9A=E6=B8=85?= =?UTF-8?q?=E9=99=A4=E6=8E=A8=E5=B9=BF=E5=91=98=E3=80=81=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=8E=A8=E5=B9=BF=E5=91=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/brokerage/user/BrokerageUserController.java | 2 +- .../vo/BrokerageUserUpdateBrokerageUserReqVO.java | 2 +- .../dal/mysql/brokerage/user/BrokerageUserMapper.java | 5 +++++ .../service/brokerage/user/BrokerageUserService.java | 6 +++--- .../brokerage/user/BrokerageUserServiceImpl.java | 11 +++++++++-- 5 files changed, 19 insertions(+), 7 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java index 0992f52e0..f29e2c9a8 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java @@ -46,7 +46,7 @@ public class BrokerageUserController { @Operation(summary = "修改推广员") @PreAuthorize("@ss.hasPermission('trade:brokerage-user:update-brokerage-user')") public CommonResult updateBrokerageUser(@Valid @RequestBody BrokerageUserUpdateBrokerageUserReqVO updateReqVO) { - brokerageUserService.updateBrokerageUserId(updateReqVO.getId(), updateReqVO.getBrokerageUserId()); + brokerageUserService.updateBrokerageUserId(updateReqVO.getId(), updateReqVO.getBindUserId()); return success(true); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserUpdateBrokerageUserReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserUpdateBrokerageUserReqVO.java index c6c72999d..d62c7fd1e 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserUpdateBrokerageUserReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserUpdateBrokerageUserReqVO.java @@ -17,6 +17,6 @@ public class BrokerageUserUpdateBrokerageUserReqVO { @Schema(description = "推广员编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4587") @NotNull(message = "推广员编号不能为空") - private Long brokerageUserId; + private Long bindUserId; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java index 2f7d1d19c..b7d045a66 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java @@ -100,4 +100,9 @@ public interface BrokerageUserMapper extends BaseMapperX { return update(null, lambdaUpdateWrapper); } + default void updateBindUserIdAndBindUserTimeToNull(Long id) { + update(null, new LambdaUpdateWrapper() + .eq(BrokerageUserDO::getId, id) + .set(BrokerageUserDO::getBindUserId, null).set(BrokerageUserDO::getBindUserTime, null)); + } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java index 61aa8bde0..f06bb7ffc 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java @@ -41,10 +41,10 @@ public interface BrokerageUserService { /** * 修改推广员编号 * - * @param id 用户编号 - * @param brokerageUserId 推广员编号 + * @param id 用户编号 + * @param bindUserId 推广员编号 */ - void updateBrokerageUserId(Long id, Long brokerageUserId); + void updateBrokerageUserId(Long id, Long bindUserId); /** * 修改推广资格 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java index 7666da49b..5df10fa58 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java @@ -54,10 +54,17 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { } @Override - public void updateBrokerageUserId(Long id, Long brokerageUserId) { + public void updateBrokerageUserId(Long id, Long bindUserId) { // 校验存在 validateBrokerageUserExists(id); - // TODO @疯狂:貌似没实现完 + if (bindUserId == null) { + // 清除推广员 + brokerageUserMapper.updateBindUserIdAndBindUserTimeToNull(id); + } else { + // 修改推广员 + brokerageUserMapper.updateById(new BrokerageUserDO().setId(id) + .setBindUserId(bindUserId).setBindUserTime(LocalDateTime.now())); + } } @Override From 4e9be7a1815f8c96567294d7600870ee88c7c028 Mon Sep 17 00:00:00 2001 From: owen Date: Sat, 9 Sep 2023 01:58:46 +0800 Subject: [PATCH 40/50] =?UTF-8?q?trade:=20=E5=88=86=E9=94=80=E4=B8=9A?= =?UTF-8?q?=E5=8A=A1=E5=90=8E=E5=8F=B0=E5=8A=9F=E8=83=BD=EF=BC=9A=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E6=8E=A8=E5=B9=BF=E8=B5=84=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dal/mysql/brokerage/user/BrokerageUserMapper.java | 6 ++++++ .../service/brokerage/user/BrokerageUserServiceImpl.java | 9 ++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java index b7d045a66..ee90b3e7d 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java @@ -105,4 +105,10 @@ public interface BrokerageUserMapper extends BaseMapperX { .eq(BrokerageUserDO::getId, id) .set(BrokerageUserDO::getBindUserId, null).set(BrokerageUserDO::getBindUserTime, null)); } + + default void updateEnabledFalseAndBrokerageTimeToNull(Long id) { + update(null, new LambdaUpdateWrapper() + .eq(BrokerageUserDO::getId, id) + .set(BrokerageUserDO::getBrokerageEnabled, false).set(BrokerageUserDO::getBrokerageTime, null)); + } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java index 5df10fa58..6d6d7d2ac 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java @@ -71,7 +71,14 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { public void updateBrokerageEnabled(Long id, Boolean enabled) { // 校验存在 validateBrokerageUserExists(id); - // TODO @疯狂:貌似没实现完 + if (BooleanUtil.isTrue(enabled)) { + // 开通推广资格 + brokerageUserMapper.updateById(new BrokerageUserDO().setId(id) + .setBrokerageEnabled(true).setBrokerageTime(LocalDateTime.now())); + } else { + // 取消推广资格 + brokerageUserMapper.updateEnabledFalseAndBrokerageTimeToNull(id); + } } private void validateBrokerageUserExists(Long id) { From 557b09a15773733b7d3c1730059d222b37bfc508 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 9 Sep 2023 09:41:57 +0800 Subject: [PATCH 41/50] =?UTF-8?q?code=20review=EF=BC=9A=E5=88=86=E9=94=80?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../trade/api/brokerage/BrokerageApiImpl.java | 1 + .../user/BrokerageUserController.java | 6 +-- .../AppBrokerageWithdrawCreateReqVO.java | 3 -- .../record/BrokerageRecordConvert.java | 18 +++----- .../brokerage/user/BrokerageUserConvert.java | 20 +++------ .../record/BrokerageRecordMapper.java | 1 + .../brokerage/user/BrokerageUserMapper.java | 1 + .../brokerage/bo/BrokerageAddReqBO.java | 2 + .../brokerage/bo/UserBrokerageSummaryBO.java | 2 + .../record/BrokerageRecordService.java | 2 +- .../record/BrokerageRecordServiceImpl.java | 7 +-- .../brokerage/user/BrokerageUserService.java | 8 ++-- .../user/BrokerageUserServiceImpl.java | 44 ++++++++++++------- .../order/TradeOrderUpdateServiceImpl.java | 12 ++--- .../yudao-module-member-biz/pom.xml | 5 --- .../app/user/AppMemberUserController.java | 12 +---- 16 files changed, 68 insertions(+), 76 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApiImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApiImpl.java index 4a534fa22..114ba39ac 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApiImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApiImpl.java @@ -20,6 +20,7 @@ public class BrokerageApiImpl implements BrokerageApi { @Resource private BrokerageUserService brokerageUserService; + @Override public BrokerageUserDTO getBrokerageUser(Long userId) { return BrokerageUserConvert.INSTANCE.convertDTO(brokerageUserService.getBrokerageUser(userId)); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java index f29e2c9a8..b0263f684 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java @@ -62,7 +62,7 @@ public class BrokerageUserController { @Operation(summary = "修改推广资格") @PreAuthorize("@ss.hasPermission('trade:brokerage-user:update-brokerage-enable')") public CommonResult updateBrokerageEnabled(@Valid @RequestBody BrokerageUserUpdateBrokerageEnabledReqVO updateReqVO) { - brokerageUserService.updateBrokerageEnabled(updateReqVO.getId(), updateReqVO.getEnabled()); + brokerageUserService.updateBrokerageUserEnabled(updateReqVO.getId(), updateReqVO.getEnabled()); return success(true); } @@ -89,12 +89,12 @@ public class BrokerageUserController { // 合计分佣订单 Map userOrderSummaryMap = convertMap(userIds, userId -> userId, - userId -> brokerageRecordService.summaryByUserIdAndBizTypeAndStatus(userId, + userId -> brokerageRecordService.getUserBrokerageSummaryByUserId(userId, BrokerageRecordBizTypeEnum.ORDER.getType(), BrokerageRecordStatusEnum.SETTLEMENT.getStatus())); // 合计推广用户数量 Map brokerageUserCountMap = convertMap(userIds, userId -> userId, - userId -> brokerageUserService.getCountByBindUserId(userId)); + userId -> brokerageUserService.getBrokerageUserCountByBindUserId(userId)); // todo 合计提现 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java index 752818130..a8b1523b2 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java @@ -23,21 +23,18 @@ public class AppBrokerageWithdrawCreateReqVO { @Min(value = 1, message = "提现金额不能小于 1") private Integer price; - // ========== 银行卡、微信、支付宝 提现相关字段 ========== @Schema(description = "提现账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456789") @NotBlank(message = "提现账号不能为空", groups = {Bank.class, Wechat.class, Alipay.class}) private String accountNo; - // ========== 微信、支付宝 提现相关字段 ========== @Schema(description = "收款码的图片", example = "https://www.iocoder.cn/1.png") @URL(message = "收款码的图片,必须是一个 URL") private String accountQrCodeUrl; - // ========== 银行卡 提现相关字段 ========== @Schema(description = "持卡人姓名", example = "张三") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java index 9307a4f55..f313fa39f 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java @@ -30,25 +30,21 @@ public interface BrokerageRecordConvert { PageResult convertPage(PageResult page); + // TODO @疯狂:可能 title 不是很固化,会存在类似:沐晴成功购买《XXX JVM 实战》 default BrokerageRecordDO convert(BrokerageUserDO user, BrokerageRecordBizTypeEnum bizType, String bizId, - Integer brokerageFrozenDays, int brokerage, LocalDateTime unfreezeTime, + Integer brokerageFrozenDays, int brokeragePrice, LocalDateTime unfreezeTime, String title) { brokerageFrozenDays = ObjectUtil.defaultIfNull(brokerageFrozenDays, 0); // 不冻结时,佣金直接就是结算状态 Integer status = brokerageFrozenDays > 0 ? BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus() : BrokerageRecordStatusEnum.SETTLEMENT.getStatus(); - return new BrokerageRecordDO() - .setUserId(user.getId()) - .setBizType(bizType.getType()) - .setBizId(bizId) - .setPrice(brokerage) - .setTotalPrice(user.getPrice()) + return new BrokerageRecordDO().setUserId(user.getId()) + .setBizType(bizType.getType()).setBizId(bizId) + .setPrice(brokeragePrice).setTotalPrice(user.getPrice()) .setTitle(title) - .setDescription(StrUtil.format(bizType.getDescription(), String.valueOf(brokerage / 100.0))) - .setStatus(status) - .setFrozenDays(brokerageFrozenDays) - .setUnfreezeTime(unfreezeTime); + .setDescription(StrUtil.format(bizType.getDescription(), String.valueOf(brokeragePrice / 100.0))) + .setStatus(status).setFrozenDays(brokerageFrozenDays).setUnfreezeTime(unfreezeTime); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/BrokerageUserConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/BrokerageUserConvert.java index 01d0be8c8..6f0222b5b 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/BrokerageUserConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/BrokerageUserConvert.java @@ -37,24 +37,16 @@ public interface BrokerageUserConvert { PageResult result = convertPage(pageResult); for (BrokerageUserRespVO vo : result.getList()) { // 用户信息 - Optional.ofNullable(userMap.get(vo.getId())) - .ifPresent(user -> { - vo.setNickname(user.getNickname()); - vo.setAvatar(user.getAvatar()); - }); - + Optional.ofNullable(userMap.get(vo.getId())).ifPresent( + user -> vo.setNickname(user.getNickname()).setAvatar(user.getAvatar())); // 推广用户数量(一级) vo.setBrokerageUserCount(MapUtil.getInt(brokerageUserCountMap, vo.getId(), 0)); - + // 推广订单数量、推广订单金额 Optional orderSummaryOptional = Optional.ofNullable(userOrderSummaryMap.get(vo.getId())); - // 推广订单数量 - vo.setBrokerageOrderCount(orderSummaryOptional.map(UserBrokerageSummaryBO::getCount).orElse(0)); - // 推广订单金额 - vo.setBrokerageOrderPrice(orderSummaryOptional.map(UserBrokerageSummaryBO::getPrice).orElse(0)); - - // todo 已提现次数 + vo.setBrokerageOrderCount(orderSummaryOptional.map(UserBrokerageSummaryBO::getCount).orElse(0)) + .setBrokerageOrderPrice(orderSummaryOptional.map(UserBrokerageSummaryBO::getPrice).orElse(0)); + // todo 已提现次数、已提现金额 vo.setWithdrawCount(0); - // todo 已提现金额 vo.setWithdrawPrice(0); } return result; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/BrokerageRecordMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/BrokerageRecordMapper.java index 9f9aae824..b72b50ca7 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/BrokerageRecordMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/BrokerageRecordMapper.java @@ -48,6 +48,7 @@ public interface BrokerageRecordMapper extends BaseMapperX { BrokerageRecordDO::getBizId, bizId); } + // TODO @疯狂:mysql 关键字,大写哈;这样看起来清晰点;例如说 SELECT COUNT(1) @Select("select count(1), sum(price) from trade_brokerage_record where user_id = #{userId} and biz_type = #{bizType} and status = #{status}") UserBrokerageSummaryBO selectCountAndSumPriceByUserIdAndBizTypeAndStatus(@Param("userId") Long userId, @Param("bizType") Integer bizType, diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java index ee90b3e7d..7fa3e415a 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java @@ -111,4 +111,5 @@ public interface BrokerageUserMapper extends BaseMapperX { .eq(BrokerageUserDO::getId, id) .set(BrokerageUserDO::getBrokerageEnabled, false).set(BrokerageUserDO::getBrokerageTime, null)); } + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java index 07e07817e..ff16ba16a 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java @@ -5,6 +5,7 @@ import lombok.Data; import lombok.NoArgsConstructor; import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; /** * 佣金 增加 Request BO @@ -24,6 +25,7 @@ public class BrokerageAddReqBO { /** * 佣金基数 */ + @NotNull(message = "佣金基数不能为空") private Integer basePrice; /** * 一级佣金(固定) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/UserBrokerageSummaryBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/UserBrokerageSummaryBO.java index ffbb3ed9a..4504290be 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/UserBrokerageSummaryBO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/UserBrokerageSummaryBO.java @@ -13,6 +13,7 @@ import lombok.NoArgsConstructor; @NoArgsConstructor @AllArgsConstructor public class UserBrokerageSummaryBO { + /** * 佣金数量 */ @@ -21,4 +22,5 @@ public class UserBrokerageSummaryBO { * 佣金总额 */ private Integer price; + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordService.java index 64e5fe52f..a6ef0b659 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordService.java @@ -66,5 +66,5 @@ public interface BrokerageRecordService { * @param status 佣金状态 * @return 用户佣金汇总 */ - UserBrokerageSummaryBO summaryByUserIdAndBizTypeAndStatus(Long userId, Integer bizType, Integer status); + UserBrokerageSummaryBO getUserBrokerageSummaryByUserId(Long userId, Integer bizType, Integer status); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java index 960b45ae5..7740d7d06 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java @@ -89,6 +89,7 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { @Override @Transactional(rollbackFor = Exception.class) public void cancelBrokerage(Long userId, BrokerageRecordBizTypeEnum bizType, String bizId) { + // TODO @疯狂:userId 加进去查询,会不会更好一点?万一穿错参数; BrokerageRecordDO record = brokerageRecordMapper.selectByBizTypeAndBizId(bizType.getType(), bizId); if (record == null || ObjectUtil.notEqual(record.getUserId(), userId)) { log.error("[cancelBrokerage][userId({})][bizId({}) 更新为已失效失败:记录不存在]", userId, bizId); @@ -138,7 +139,7 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { * @param list 佣金增加参数列表 * @param brokerageFrozenDays 冻结天数 * @param brokeragePercent 佣金比例 - * @param fixedPriceFun 固定佣金 + * @param fixedPriceFun 固定佣金 // TODO 疯狂:这里是不是可以直接传递 fixedPrice 呀? * @param bizType 业务类型 */ private void addBrokerage(BrokerageUserDO user, List list, Integer brokerageFrozenDays, @@ -200,9 +201,9 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { } @Override - public UserBrokerageSummaryBO summaryByUserIdAndBizTypeAndStatus(Long userId, Integer bizType, Integer status) { + public UserBrokerageSummaryBO getUserBrokerageSummaryByUserId(Long userId, Integer bizType, Integer status) { UserBrokerageSummaryBO summaryBO = brokerageRecordMapper.selectCountAndSumPriceByUserIdAndBizTypeAndStatus(userId, bizType, status); - return summaryBO == null ? new UserBrokerageSummaryBO(0, 0) : summaryBO; + return summaryBO != null ? summaryBO : new UserBrokerageSummaryBO(0, 0); } @Transactional(rollbackFor = Exception.class) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java index f06bb7ffc..b3d265b29 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java @@ -52,7 +52,7 @@ public interface BrokerageUserService { * @param id 用户编号 * @param enabled 推广资格 */ - void updateBrokerageEnabled(Long id, Boolean enabled); + void updateBrokerageUserEnabled(Long id, Boolean enabled); /** * 获得用户的推广人 @@ -79,20 +79,21 @@ public interface BrokerageUserService { void updateUserFrozenPrice(Long id, Integer frozenPrice); /** - * 更新用户冻结佣金(减少), 更新用户佣金(增加) + * 更新用户冻结佣金(减少),更新用户佣金(增加) * * @param id 用户编号 * @param frozenPrice 减少冻结佣金(负数) */ void updateFrozenPriceDecrAndPriceIncr(Long id, Integer frozenPrice); + // TODO @疯狂:这个后面可能要支持下,二级 /** * 获得推广用户数量(一级) * * @param bindUserId 绑定的推广员编号 * @return 推广用户数量 */ - Long getCountByBindUserId(Long bindUserId); + Long getBrokerageUserCountByBindUserId(Long bindUserId); /** * 【会员】绑定推广员 @@ -103,4 +104,5 @@ public interface BrokerageUserService { * @return 是否绑定 */ boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser); + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java index 6d6d7d2ac..2dd7fb03b 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java @@ -57,18 +57,22 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { public void updateBrokerageUserId(Long id, Long bindUserId) { // 校验存在 validateBrokerageUserExists(id); + + // 情况一:清除推广员 if (bindUserId == null) { // 清除推广员 brokerageUserMapper.updateBindUserIdAndBindUserTimeToNull(id); - } else { - // 修改推广员 - brokerageUserMapper.updateById(new BrokerageUserDO().setId(id) - .setBindUserId(bindUserId).setBindUserTime(LocalDateTime.now())); + return; } + + // 情况二:修改推广员 + // TODO @疯狂:要复用一些 validateCanBindUser 的校验哈; + brokerageUserMapper.updateById(new BrokerageUserDO().setId(id) + .setBindUserId(bindUserId).setBindUserTime(LocalDateTime.now())); } @Override - public void updateBrokerageEnabled(Long id, Boolean enabled) { + public void updateBrokerageUserEnabled(Long id, Boolean enabled) { // 校验存在 validateBrokerageUserExists(id); if (BooleanUtil.isTrue(enabled)) { @@ -124,36 +128,41 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { } @Override - public Long getCountByBindUserId(Long bindUserId) { + public Long getBrokerageUserCountByBindUserId(Long bindUserId) { + // TODO @疯狂:mapper 封装下哈;不直接在 service 调用这种基础 mapper 的基础方法 return brokerageUserMapper.selectCount(BrokerageUserDO::getBindUserId, bindUserId); } + // TODO @疯狂:因为现在 user 会存在使用验证码直接注册,所以 isNewUser 不太好传递;我们是不是可以约定绑定的时间,createTime 在 30 秒内,就认为新用户; @Override public boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser) { + // TODO @疯狂:userId 为空,搞到参数校验里哇; if (userId == null) { throw exception(0); } - boolean isInsert = false; + // 1. 获得分销用户 + boolean isNewBrokerageUser = false; BrokerageUserDO brokerageUser = brokerageUserMapper.selectById(userId); - // 分销用户不存在的情况:1.新注册 2.旧数据 3.分销功能关闭后又打开 - if (brokerageUser == null) { - isInsert = true; + if (brokerageUser == null) { // 分销用户不存在的情况:1. 新注册;2. 旧数据;3. 分销功能关闭后又打开 + isNewBrokerageUser = true; brokerageUser = new BrokerageUserDO().setId(userId).setBrokerageEnabled(false).setPrice(0).setFrozenPrice(0); } - // 校验能否绑定 + // 2.1 校验能否绑定 boolean validated = validateCanBindUser(brokerageUser, bindUserId, isNewUser); if (!validated) { return false; } - if (isInsert) { + // 2.2 绑定用户 + if (isNewBrokerageUser) { Integer enabledCondition = tradeConfigService.getTradeConfig().getBrokerageEnabledCondition(); - if (BrokerageEnabledConditionEnum.ALL.getCondition().equals(enabledCondition)) { - // 人人分销:用户默认就有分销资格 + if (BrokerageEnabledConditionEnum.ALL.getCondition().equals(enabledCondition)) { // 人人分销:用户默认就有分销资格 + // TODO @疯狂:应该设置下 brokerageTime,而不是 bindUserTime brokerageUser.setBrokerageEnabled(true).setBindUserTime(LocalDateTime.now()); } + // TODO @疯狂:这里是不是要设置 bindUserId、bindUserTime 字段哈; brokerageUserMapper.insert(brokerageUser); } else { brokerageUserMapper.updateById(new BrokerageUserDO().setId(userId) @@ -162,14 +171,16 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { return true; } + // TODO @疯狂:validate 方法,一般不返回 true false,而是抛出异常;如果要返回 true false 这种,方法名字可以改成 isUserCanBind private boolean validateCanBindUser(BrokerageUserDO user, Long bindUserId, Boolean isNewUser) { + // TODO @疯狂:bindUserId 为空,搞到参数校验里哇; if (bindUserId == null) { return false; } // 校验分销功能是否启用 TradeConfigDO tradeConfig = tradeConfigService.getTradeConfig(); - if (tradeConfig == null || !BooleanUtil.isTrue(tradeConfig.getBrokerageEnabled())) { + if (tradeConfig == null || BooleanUtil.isFalse(tradeConfig.getBrokerageEnabled())) { return false; } @@ -180,7 +191,7 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { // 校验要绑定的用户有无推广资格 BrokerageUserDO bindUser = brokerageUserMapper.selectById(bindUserId); - if (bindUser == null || !BooleanUtil.isTrue(bindUser.getBrokerageEnabled())) { + if (bindUser == null || BooleanUtil.isFalse(bindUser.getBrokerageEnabled())) { throw exception(BROKERAGE_BIND_USER_NOT_ENABLED); } @@ -200,6 +211,7 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { } } + // TODO @疯狂:这块是不是一直查询到根节点,中间不允许出现自己;就是不能形成环。虽然目前是 2 级,但是未来可能会改多级; = = 环的话,就会存在问题哈 // A->B->A:下级不能绑定自己的上级, A->B->C->A可以!! if (Objects.equals(user.getId(), bindUser.getBindUserId())) { throw exception(BROKERAGE_BIND_LOOP); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index 85d4caae0..7893d62a9 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -395,7 +395,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { // 增加用户经验 getSelf().addUserExperienceAsync(order.getUserId(), order.getPayPrice(), order.getId()); // 增加用户佣金 - getSelf().addBrokerageAsync(order.getUserId(), BrokerageRecordBizTypeEnum.ORDER, order.getId()); + getSelf().addBrokerageAsync(order.getUserId(), order.getId()); } /** @@ -675,7 +675,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { // 扣减用户经验 getSelf().reduceUserExperienceAsync(order.getUserId(), orderRefundPrice, afterSaleId); // 更新分佣记录为已失效 - getSelf().cancelBrokerageAsync(order.getUserId(), BrokerageRecordBizTypeEnum.ORDER, id); + getSelf().cancelBrokerageAsync(order.getUserId(), id); } @Override @@ -785,16 +785,16 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @Async - protected void addBrokerageAsync(Long userId, BrokerageRecordBizTypeEnum bizType, Long orderId) { + protected void addBrokerageAsync(Long userId, Long orderId) { List orderItems = tradeOrderItemMapper.selectListByOrderId(orderId); List list = convertList(orderItems, item -> TradeOrderConvert.INSTANCE.convert(item, productSkuApi.getSku(item.getSkuId()))); - brokerageRecordService.addBrokerage(userId, bizType, list); + brokerageRecordService.addBrokerage(userId, BrokerageRecordBizTypeEnum.ORDER, list); } @Async - protected void cancelBrokerageAsync(Long userId, BrokerageRecordBizTypeEnum bizType, Long orderItemId) { - brokerageRecordService.cancelBrokerage(userId, bizType, String.valueOf(orderItemId)); + protected void cancelBrokerageAsync(Long userId, Long orderItemId) { + brokerageRecordService.cancelBrokerage(userId, BrokerageRecordBizTypeEnum.ORDER, String.valueOf(orderItemId)); } /** diff --git a/yudao-module-member/yudao-module-member-biz/pom.xml b/yudao-module-member/yudao-module-member-biz/pom.xml index 1df7e7be8..a5eda05b0 100644 --- a/yudao-module-member/yudao-module-member-biz/pom.xml +++ b/yudao-module-member/yudao-module-member-biz/pom.xml @@ -33,11 +33,6 @@ yudao-module-infra-api ${revision} - - cn.iocoder.boot - yudao-module-trade-api - ${revision} - diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java index 461a1a5c5..9322f9146 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java @@ -8,8 +8,6 @@ import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; import cn.iocoder.yudao.module.member.service.level.MemberLevelService; import cn.iocoder.yudao.module.member.service.user.MemberUserService; -import cn.iocoder.yudao.module.trade.api.brokerage.BrokerageApi; -import cn.iocoder.yudao.module.trade.api.brokerage.dto.BrokerageUserDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; @@ -18,7 +16,6 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.Valid; -import java.util.Optional; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @@ -32,23 +29,16 @@ public class AppMemberUserController { @Resource private MemberUserService userService; - @Resource private MemberLevelService levelService; - @Resource - private BrokerageApi brokerageApi; - @GetMapping("/get") @Operation(summary = "获得基本信息") @PreAuthenticated public CommonResult getUserInfo() { MemberUserDO user = userService.getUser(getLoginUserId()); MemberLevelDO level = levelService.getLevel(user.getLevelId()); - BrokerageUserDTO brokerageUser = brokerageApi.getBrokerageUser(user.getId()); - return success(MemberUserConvert.INSTANCE.convert(user, level) - .setBrokerageEnabled(Optional.ofNullable(brokerageUser).map(BrokerageUserDTO::getBrokerageEnabled).orElse(false)) - ); + return success(MemberUserConvert.INSTANCE.convert(user, level)); } @PutMapping("/update") From 5858f57fe91ed97693ed10a4bec399aa263bf757 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Sat, 9 Sep 2023 18:32:53 +0800 Subject: [PATCH 42/50] =?UTF-8?q?=E9=92=B1=E5=8C=85=20review=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/mysql/pay_wallet.sql | 4 +- .../wallet/vo/wallet/AppPayWalletRespVO.java | 4 +- .../wallet/PayWalletTransactionConvert.java | 3 + .../dal/dataobject/wallet/PayWalletDO.java | 6 +- .../pay/dal/mysql/wallet/PayWalletMapper.java | 58 +++------- .../framework/pay/wallet/WalletPayClient.java | 13 ++- .../service/wallet/PayWalletServiceImpl.java | 101 ++++++------------ .../wallet/PayWalletTransactionService.java | 7 +- .../PayWalletTransactionServiceImpl.java | 18 +++- .../wallet/bo/CreateWalletTransactionBO.java | 48 +++++++++ 10 files changed, 132 insertions(+), 130 deletions(-) create mode 100644 yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/bo/CreateWalletTransactionBO.java diff --git a/sql/mysql/pay_wallet.sql b/sql/mysql/pay_wallet.sql index bc2ad183e..7d092ef45 100644 --- a/sql/mysql/pay_wallet.sql +++ b/sql/mysql/pay_wallet.sql @@ -8,8 +8,8 @@ CREATE TABLE `pay_wallet` `user_id` bigint NOT NULL COMMENT '用户编号', `user_type` tinyint NOT NULL DEFAULT 0 COMMENT '用户类型', `balance` int NOT NULL DEFAULT 0 COMMENT '余额,单位分', - `total_expense` bigint NOT NULL DEFAULT 0 COMMENT '累计支出,单位分', - `total_recharge` bigint NOT NULL DEFAULT 0 COMMENT '累计充值,单位分', + `total_expense` int NOT NULL DEFAULT 0 COMMENT '累计支出,单位分', + `total_recharge` int NOT NULL DEFAULT 0 COMMENT '累计充值,单位分', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/wallet/AppPayWalletRespVO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/wallet/AppPayWalletRespVO.java index c66cda871..bd0e0b9d7 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/wallet/AppPayWalletRespVO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/wallet/AppPayWalletRespVO.java @@ -11,9 +11,9 @@ public class AppPayWalletRespVO { private Integer balance; @Schema(description = "累计支出, 单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") - private Long totalExpense; + private Integer totalExpense; @Schema(description = "累计充值, 单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000") - private Long totalRecharge; + private Integer totalRecharge; } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletTransactionConvert.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletTransactionConvert.java index 9d1edaf6a..088bdecf3 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletTransactionConvert.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletTransactionConvert.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.pay.convert.wallet; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionRespVO; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; +import cn.iocoder.yudao.module.pay.service.wallet.bo.CreateWalletTransactionBO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -12,4 +13,6 @@ public interface PayWalletTransactionConvert { PayWalletTransactionConvert INSTANCE = Mappers.getMapper(PayWalletTransactionConvert.class); PageResult convertPage(PageResult page); + + PayWalletTransactionDO convert(CreateWalletTransactionBO bo); } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletDO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletDO.java index 4bf8e6151..4536ae635 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletDO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletDO.java @@ -37,8 +37,6 @@ public class PayWalletDO extends BaseDO { */ private Integer userType; - // TODO @jason:三个都搞 integer?应该要统一哈 - /** * 余额,单位分 */ @@ -47,10 +45,10 @@ public class PayWalletDO extends BaseDO { /** * 累计支出,单位分 */ - private Long totalExpense; + private Integer totalExpense; /** * 累计充值,单位分 */ - private Long totalRecharge; + private Integer totalRecharge; } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java index 47717d04a..9184621bd 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java @@ -3,8 +3,7 @@ package cn.iocoder.yudao.module.pay.dal.mysql.wallet; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; -import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; @Mapper @@ -15,56 +14,31 @@ public interface PayWalletMapper extends BaseMapperX { PayWalletDO::getUserType, userType); } - // TODO @jason:减少时,需要 update price -= ? where price >= ?,避免并发问题。现在基于 price 来过滤,虽然也能解决并发问题,但是冲突概率会高一点;可以看到 TradeBrokerageUserMapper 的做法; /** - * 当余额减少时候更新 + * 当消费退款时候, 更新钱包 * - * @param bizType 业务类型 - * @param balance 当前余额 - * @param totalRecharge 当前累计充值 - * @param totalExpense 当前累计支出 - * @param price 支出的金额 + * @param price 消费金额 * @param id 钱包 id */ - default int updateWhenDecBalance(PayWalletBizTypeEnum bizType, Integer balance, Long totalRecharge, - Long totalExpense, Integer price, Long id) { - // TODO @jason:这种偏判断的,最红放在 service 层;mapper 可以写多个方法; - PayWalletDO updateDO = new PayWalletDO().setBalance(balance - price); - if(bizType == PayWalletBizTypeEnum.PAYMENT){ - updateDO.setTotalExpense(totalExpense + price); - } - if (bizType == PayWalletBizTypeEnum.RECHARGE_REFUND) { - updateDO.setTotalRecharge(totalRecharge - price); - } - return update(updateDO, - new LambdaQueryWrapper().eq(PayWalletDO::getId, id) - .eq(PayWalletDO::getBalance, balance) - .ge(PayWalletDO::getBalance, price)); + default int updateWhenConsumptionRefund(Integer price, Long id){ + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() + .setSql(" balance = balance + " + price + ", total_expense = total_expense - " + price) + .eq(PayWalletDO::getId, id); + return update(null, lambdaUpdateWrapper); } - // TODO @jason:类似上面的修改建议哈; /** - * 当余额增加时候更新 + * 当消费时候, 更新钱包 * - * @param bizType 业务类型 - * @param balance 当前余额 - * @param totalRecharge 当前累计充值 - * @param totalExpense 当前累计支出 - * @param price 金额 + * @param price 消费金额 * @param id 钱包 id */ - default int updateWhenIncBalance(PayWalletBizTypeEnum bizType, Integer balance, Long totalRecharge, - Long totalExpense, Integer price, Long id) { - PayWalletDO updateDO = new PayWalletDO().setBalance(balance + price); - if (bizType == PayWalletBizTypeEnum.PAYMENT_REFUND) { - updateDO.setTotalExpense(totalExpense - price); - } - if (bizType == PayWalletBizTypeEnum.RECHARGE) { - updateDO.setTotalExpense(totalRecharge + price); - } - return update(updateDO, - new LambdaQueryWrapper().eq(PayWalletDO::getId, id) - .eq(PayWalletDO::getBalance, balance)); + default int updateWhenConsumption(Integer price, Long id){ + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() + .setSql(" balance = balance - " + price + ", total_expense = total_expense + " + price) + .eq(PayWalletDO::getId, id) + .ge(PayWalletDO::getBalance, price); // cas 逻辑 + return update(null, lambdaUpdateWrapper); } } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java index 47e8217d3..54681f815 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java @@ -62,13 +62,12 @@ public class WalletPayClient extends AbstractPayClient { @Override protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) { try { - // TODO @jason:直接 getLong 和 getInt 会不会更简洁哈 - String userId = MapUtil.getStr(reqDTO.getChannelExtras(), USER_ID_KEY); - String userType = MapUtil.getStr(reqDTO.getChannelExtras(), USER_TYPE_KEY); - Assert.notEmpty(userId, "用户 id 不能为空"); - Assert.notEmpty(userType, "用户类型不能为空"); - PayWalletTransactionDO transaction = wallService.orderPay(Long.valueOf(userId), Integer.valueOf(userType), - reqDTO.getOutTradeNo(), reqDTO.getPrice()); + Long userId = MapUtil.getLong(reqDTO.getChannelExtras(), USER_ID_KEY); + Integer userType = MapUtil.getInt(reqDTO.getChannelExtras(), USER_TYPE_KEY); + Assert.notNull(userId, "用户 id 不能为空"); + Assert.notNull(userType, "用户类型不能为空"); + PayWalletTransactionDO transaction = wallService.orderPay(userId, userType, reqDTO.getOutTradeNo(), + reqDTO.getPrice()); return PayOrderRespDTO.successOf(transaction.getNo(), transaction.getCreator(), transaction.getCreateTime(), reqDTO.getOutTradeNo(), transaction); diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java index d017e5332..2d186b98e 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java @@ -6,10 +6,10 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletMapper; -import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO; import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; import cn.iocoder.yudao.module.pay.service.order.PayOrderService; import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; +import cn.iocoder.yudao.module.pay.service.wallet.bo.CreateWalletTransactionBO; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; @@ -18,7 +18,6 @@ import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.time.LocalDateTime; -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.TOO_MANY_REQUESTS; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum.PAYMENT; @@ -33,20 +32,8 @@ import static cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum.PAYM @Slf4j public class PayWalletServiceImpl implements PayWalletService { - /** - * 余额支付的 no 前缀 - */ - private static final String WALLET_PAY_NO_PREFIX = "WP"; - /** - * 余额退款的 no 前缀 - */ - private static final String WALLET_REFUND_NO_PREFIX = "WR"; - @Resource private PayWalletMapper walletMapper; - @Resource - private PayNoRedisDAO noRedisDAO; - @Resource private PayWalletTransactionService walletTransactionService; @Resource @@ -61,7 +48,7 @@ public class PayWalletServiceImpl implements PayWalletService { PayWalletDO wallet = walletMapper.selectByUserIdAndType(userId, userType); if (wallet == null) { wallet = new PayWalletDO().setUserId(userId).setUserType(userType) - .setBalance(0).setTotalExpense(0L).setTotalRecharge(0L); + .setBalance(0).setTotalExpense(0).setTotalRecharge(0); wallet.setCreateTime(LocalDateTime.now()); walletMapper.insert(wallet); } @@ -127,68 +114,50 @@ public class PayWalletServiceImpl implements PayWalletService { Long bizId, PayWalletBizTypeEnum bizType, Integer price) { // 1.1 获取钱包 PayWalletDO payWallet = getOrCreateWallet(userId, userType); - // 1.2 判断余额是否足够 - int afterBalance = payWallet.getBalance() - price; - if (afterBalance < 0) { + // 2.1 扣除余额 + int number = 0 ; + switch (bizType) { + case PAYMENT: { + number = walletMapper.updateWhenConsumption(price, payWallet.getId()); + break; + } + case RECHARGE_REFUND: { + // TODO + break; + } + } + if (number == 0) { throw exception(WALLET_BALANCE_NOT_ENOUGH); } - - // TODO jason:建议基于 where price >= 来做哈;然后抛出 WALLET_BALANCE_NOT_ENOUGH - // 2.1 扣除余额 - int number = walletMapper.updateWhenDecBalance(bizType, payWallet.getBalance(), - payWallet.getTotalRecharge(), payWallet.getTotalExpense(), price, payWallet.getId()); - if (number == 0) { - throw exception(TOO_MANY_REQUESTS); - } - + int afterBalance = payWallet.getBalance() - price; // 2.2 生成钱包流水 - // TODO @jason:walletNo 交给 payWalletTransactionService 自己生成哈; - String walletNo = generateWalletNo(bizType); - PayWalletTransactionDO walletTransaction = new PayWalletTransactionDO().setWalletId(payWallet.getId()) - .setNo(walletNo).setPrice(-price).setBalance(afterBalance) - .setBizId(String.valueOf(bizId)).setBizType(bizType.getType()).setTitle(bizType.getDescription()); - // TODO @jason:是不是可以 createWalletTransaction 搞个 bo 参数,然后 PayWalletTransactionDO 交回给 walletTransactionService 更好;然后把参数简化下 - walletTransactionService.createWalletTransaction(walletTransaction); - return walletTransaction; + CreateWalletTransactionBO bo = new CreateWalletTransactionBO().setWalletId(payWallet.getId()) + .setPrice(-price).setBalance(afterBalance).setBizId(String.valueOf(bizId)) + .setBizType(bizType.getType()).setTitle(bizType.getDescription()); + return walletTransactionService.createWalletTransaction(bo); } @Override public PayWalletTransactionDO addWalletBalance(Long userId, Integer userType, Long bizId, PayWalletBizTypeEnum bizType, Integer price) { - // 1.1 获取钱包 + // 获取钱包 PayWalletDO payWallet = getOrCreateWallet(userId, userType); - - // 2.1 增加余额 - // TODO @jason:类似上面的思路哈; - int number = walletMapper.updateWhenIncBalance(bizType, payWallet.getBalance(), payWallet.getTotalRecharge(), - payWallet.getTotalExpense(), price, payWallet.getId()); - if (number == 0) { - throw exception(TOO_MANY_REQUESTS); + switch (bizType) { + case PAYMENT_REFUND: { + // 更新退款 + walletMapper.updateWhenConsumptionRefund(price, payWallet.getId()); + break; + } + case RECHARGE: { + //TODO + break; + } } - // 2.2 生成钱包流水 - String walletNo = generateWalletNo(bizType); - PayWalletTransactionDO newWalletTransaction = new PayWalletTransactionDO().setWalletId(payWallet.getId()) - .setNo(walletNo).setPrice(price).setBalance(payWallet.getBalance()+price) - .setBizId(String.valueOf(bizId)).setBizType(bizType.getType()) - .setTitle(bizType.getDescription()); - walletTransactionService.createWalletTransaction(newWalletTransaction); - return newWalletTransaction; - } - - private String generateWalletNo(PayWalletBizTypeEnum bizType) { - // TODO @jason:对于余额来说,是不是直接 W+序号就行了,它其实不关注业务;;;不然就耦合啦 - String no = ""; - switch(bizType){ - case PAYMENT: - no = noRedisDAO.generate(WALLET_PAY_NO_PREFIX); - break; - case PAYMENT_REFUND: - no = noRedisDAO.generate(WALLET_REFUND_NO_PREFIX); - break; - default : - } - return no; + CreateWalletTransactionBO bo = new CreateWalletTransactionBO().setWalletId(payWallet.getId()) + .setPrice(price).setBalance(payWallet.getBalance()+price).setBizId(String.valueOf(bizId)) + .setBizType(bizType.getType()).setTitle(bizType.getDescription()); + return walletTransactionService.createWalletTransaction(bo); } } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionService.java index 432e2f2e0..db6f778f3 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionService.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionPageReqVO; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; +import cn.iocoder.yudao.module.pay.service.wallet.bo.CreateWalletTransactionBO; /** * 钱包余额流水 Service 接口 @@ -25,10 +26,10 @@ public interface PayWalletTransactionService { /** * 新增钱包余额流水 * - * @param payWalletTransaction 余额流水 - * @return id + * @param bo 创建钱包流水 bo + * @return 新建的钱包 do */ - Long createWalletTransaction(PayWalletTransactionDO payWalletTransaction); + PayWalletTransactionDO createWalletTransaction(CreateWalletTransactionBO bo); /** * 根据 no,获取钱包余流水 diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java index 05a2a4800..ba27392f0 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java @@ -2,10 +2,13 @@ package cn.iocoder.yudao.module.pay.service.wallet; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionPageReqVO; +import cn.iocoder.yudao.module.pay.convert.wallet.PayWalletTransactionConvert; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletTransactionMapper; +import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO; import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; +import cn.iocoder.yudao.module.pay.service.wallet.bo.CreateWalletTransactionBO; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -19,11 +22,16 @@ import javax.annotation.Resource; @Service @Slf4j public class PayWalletTransactionServiceImpl implements PayWalletTransactionService { - + /** + * 钱包流水的 no 前缀 + */ + private static final String WALLET_NO_PREFIX = "W"; @Resource private PayWalletService payWalletService; @Resource private PayWalletTransactionMapper payWalletTransactionMapper; + @Resource + private PayNoRedisDAO noRedisDAO; @Override public PageResult getWalletTransactionPage(Long userId, Integer userType, @@ -33,9 +41,11 @@ public class PayWalletTransactionServiceImpl implements PayWalletTransactionServ } @Override - public Long createWalletTransaction(PayWalletTransactionDO payWalletTransaction) { - payWalletTransactionMapper.insert(payWalletTransaction); - return payWalletTransaction.getId(); + public PayWalletTransactionDO createWalletTransaction(CreateWalletTransactionBO bo) { + PayWalletTransactionDO transactionDO = PayWalletTransactionConvert.INSTANCE.convert(bo); + transactionDO.setNo(noRedisDAO.generate(WALLET_NO_PREFIX)); + payWalletTransactionMapper.insert(transactionDO); + return transactionDO; } @Override diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/bo/CreateWalletTransactionBO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/bo/CreateWalletTransactionBO.java new file mode 100644 index 000000000..2b7188606 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/bo/CreateWalletTransactionBO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.pay.service.wallet.bo; + +import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; +import lombok.Data; + +/** + * 创建钱包流水 BO + * + * @author jason + */ +@Data +public class CreateWalletTransactionBO { + + /** + * 钱包编号 + * + */ + private Long walletId; + + /** + * 交易金额,单位分 + * + * 正值表示余额增加,负值表示余额减少 + */ + private Integer price; + + /** + * 交易后余额,单位分 + */ + private Integer balance; + + /** + * 关联业务分类 + * + * 枚举 {@link PayWalletBizTypeEnum#getType()} + */ + private Integer bizType; + + /** + * 关联业务编号 + */ + private String bizId; + + /** + * 流水说明 + */ + private String title; +} From 426594ae001a2465a3476ad18202386a0979550f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 9 Sep 2023 19:34:50 +0800 Subject: [PATCH 43/50] =?UTF-8?q?=E5=88=86=E9=94=80=EF=BC=9A=E8=B0=83?= =?UTF-8?q?=E6=95=B4=20app=20=E7=9A=84=20price=20=E5=88=B0=20brokeragePric?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../brokerage/user/vo/BrokerageUserRespVO.java | 3 --- .../app/brokerage/AppBrokerageUserController.java | 15 ++++++++------- .../user/AppBrokerageUserChildSummaryRespVO.java | 2 +- .../vo/user/AppBrokerageUserMySummaryRespVO.java | 2 +- .../user/AppBrokerageUserRankByPriceRespVO.java | 2 +- .../brokerage/vo/user/AppBrokerageUserRespVO.java | 3 +++ .../brokerage/record/BrokerageRecordConvert.java | 2 +- .../brokerage/user/BrokerageUserDO.java | 4 ++-- .../brokerage/user/BrokerageUserServiceImpl.java | 2 +- 9 files changed, 18 insertions(+), 17 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserRespVO.java index c353b4614..ae7caf5ff 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserRespVO.java @@ -19,7 +19,6 @@ public class BrokerageUserRespVO extends BrokerageUserBaseVO { @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; - // ========== 用户信息 ========== @Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png") @@ -27,7 +26,6 @@ public class BrokerageUserRespVO extends BrokerageUserBaseVO { @Schema(description = "用户昵称", example = "李四") private String nickname; - // ========== 推广信息 ========== @Schema(description = "推广用户数量(一级)", example = "20019") @@ -37,7 +35,6 @@ public class BrokerageUserRespVO extends BrokerageUserBaseVO { @Schema(description = "推广订单金额", example = "20019") private Integer brokerageOrderPrice; - // ========== 提现信息 ========== @Schema(description = "已提现金额", example = "20019") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java index ef1634098..83a1b25e0 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java @@ -37,6 +37,7 @@ public class AppBrokerageUserController { @PreAuthenticated public CommonResult getBrokerageUser() { AppBrokerageUserRespVO respVO = new AppBrokerageUserRespVO() + .setBrokerageEnabled(true) .setPrice(2000) .setFrozenPrice(3000); return success(respVO); @@ -49,7 +50,7 @@ public class AppBrokerageUserController { public CommonResult getBrokerageUserSummary() { AppBrokerageUserMySummaryRespVO respVO = new AppBrokerageUserMySummaryRespVO() .setYesterdayPrice(1) - .setPrice(2) + .setBrokeragePrice(2) .setFrozenPrice(3) .setWithdrawPrice(4) .setFirstBrokerageUserCount(166) @@ -84,16 +85,16 @@ public class AppBrokerageUserController { public CommonResult> getBrokerageUserChildSummaryPageByPrice(AppBrokerageUserRankPageReqVO pageReqVO) { AppBrokerageUserRankByPriceRespVO vo1 = new AppBrokerageUserRankByPriceRespVO() .setId(1L).setNickname("芋1**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") - .setPrice(10); + .setBrokeragePrice(10); AppBrokerageUserRankByPriceRespVO vo2 = new AppBrokerageUserRankByPriceRespVO() .setId(2L).setNickname("芋2**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") - .setPrice(6); + .setBrokeragePrice(6); AppBrokerageUserRankByPriceRespVO vo3 = new AppBrokerageUserRankByPriceRespVO() .setId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") - .setPrice(4); + .setBrokeragePrice(4); AppBrokerageUserRankByPriceRespVO vo4 = new AppBrokerageUserRankByPriceRespVO() .setId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") - .setPrice(4); + .setBrokeragePrice(4); return success(new PageResult<>(asList(vo1, vo2, vo3, vo4), 10L)); } @@ -105,11 +106,11 @@ public class AppBrokerageUserController { AppBrokerageUserChildSummaryPageReqVO pageReqVO) { AppBrokerageUserChildSummaryRespVO vo1 = new AppBrokerageUserChildSummaryRespVO() .setId(1L).setNickname("芋1**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") - .setPrice(10).setPrice(20).setBrokerageOrderCount(30) + .setBrokeragePrice(10).setBrokeragePrice(20).setBrokerageOrderCount(30) .setBrokerageTime(LocalDateTime.now()); AppBrokerageUserChildSummaryRespVO vo2 = new AppBrokerageUserChildSummaryRespVO() .setId(1L).setNickname("芋2**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") - .setPrice(20).setPrice(30).setBrokerageOrderCount(40) + .setBrokeragePrice(20).setBrokeragePrice(30).setBrokerageOrderCount(40) .setBrokerageTime(LocalDateTime.now()); return success(new PageResult<>(asList(vo1, vo2), 10L)); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserChildSummaryRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserChildSummaryRespVO.java index 55d88d74f..1beb1b5e2 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserChildSummaryRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserChildSummaryRespVO.java @@ -19,7 +19,7 @@ public class AppBrokerageUserChildSummaryRespVO { private String avatar; @Schema(description = "佣金金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - private Integer price; + private Integer brokeragePrice; @Schema(description = "分销订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") private Integer brokerageOrderCount; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserMySummaryRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserMySummaryRespVO.java index 33a089cc6..cc9a03ebc 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserMySummaryRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserMySummaryRespVO.java @@ -14,7 +14,7 @@ public class AppBrokerageUserMySummaryRespVO { private Integer withdrawPrice; @Schema(description = "可用的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2408") - private Integer price; + private Integer brokeragePrice; @Schema(description = "冻结的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "234") private Integer frozenPrice; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByPriceRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByPriceRespVO.java index d80fb67a2..91345ea78 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByPriceRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByPriceRespVO.java @@ -17,6 +17,6 @@ public class AppBrokerageUserRankByPriceRespVO { private String avatar; @Schema(description = "佣金金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - private Integer price; + private Integer brokeragePrice; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRespVO.java index 9db6e0cc2..40b70bed2 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRespVO.java @@ -7,6 +7,9 @@ import lombok.Data; @Data public class AppBrokerageUserRespVO { + @Schema(description = "是否有分销资格", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean brokerageEnabled; + @Schema(description = "可用的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2408") private Integer price; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java index f313fa39f..b55a76c88 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java @@ -41,7 +41,7 @@ public interface BrokerageRecordConvert { : BrokerageRecordStatusEnum.SETTLEMENT.getStatus(); return new BrokerageRecordDO().setUserId(user.getId()) .setBizType(bizType.getType()).setBizId(bizId) - .setPrice(brokeragePrice).setTotalPrice(user.getPrice()) + .setPrice(brokeragePrice).setTotalPrice(user.getBrokeragePrice()) .setTitle(title) .setDescription(StrUtil.format(bizType.getDescription(), String.valueOf(brokeragePrice / 100.0))) .setStatus(status).setFrozenDays(brokerageFrozenDays).setUnfreezeTime(unfreezeTime); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/BrokerageUserDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/BrokerageUserDO.java index 1773e41e7..4348fa195 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/BrokerageUserDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/BrokerageUserDO.java @@ -43,7 +43,7 @@ public class BrokerageUserDO extends BaseDO { private LocalDateTime bindUserTime; /** - * 推广资格 + * 是否有分销资格 */ private Boolean brokerageEnabled; /** @@ -54,7 +54,7 @@ public class BrokerageUserDO extends BaseDO { /** * 可用佣金 */ - private Integer price; + private Integer brokeragePrice; /** * 冻结佣金 */ diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java index 2dd7fb03b..47ad454ef 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java @@ -146,7 +146,7 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { BrokerageUserDO brokerageUser = brokerageUserMapper.selectById(userId); if (brokerageUser == null) { // 分销用户不存在的情况:1. 新注册;2. 旧数据;3. 分销功能关闭后又打开 isNewBrokerageUser = true; - brokerageUser = new BrokerageUserDO().setId(userId).setBrokerageEnabled(false).setPrice(0).setFrozenPrice(0); + brokerageUser = new BrokerageUserDO().setId(userId).setBrokerageEnabled(false).setBrokeragePrice(0).setFrozenPrice(0); } // 2.1 校验能否绑定 From cd51d57f122ad8d74c5ade811098472b17860ecb Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 9 Sep 2023 19:42:53 +0800 Subject: [PATCH 44/50] =?UTF-8?q?=E5=88=86=E9=94=80=EF=BC=9A=E8=B0=83?= =?UTF-8?q?=E6=95=B4=20app=20=E7=9A=84=20price=20=E5=88=B0=20brokeragePric?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wallet/PayWalletTransactionConvert.java | 3 ++- .../pay/dal/mysql/wallet/PayWalletMapper.java | 6 ++++-- .../pay/service/wallet/PayWalletServiceImpl.java | 16 +++++++++------- .../wallet/PayWalletTransactionService.java | 5 ++++- .../wallet/PayWalletTransactionServiceImpl.java | 11 +++++++---- .../wallet/bo/CreateWalletTransactionBO.java | 2 ++ 6 files changed, 28 insertions(+), 15 deletions(-) diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletTransactionConvert.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletTransactionConvert.java index 088bdecf3..f806168c8 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletTransactionConvert.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletTransactionConvert.java @@ -14,5 +14,6 @@ public interface PayWalletTransactionConvert { PageResult convertPage(PageResult page); - PayWalletTransactionDO convert(CreateWalletTransactionBO bo); + PayWalletTransactionDO convert(CreateWalletTransactionBO bean); + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java index 9184621bd..ef695c9fe 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java @@ -22,7 +22,8 @@ public interface PayWalletMapper extends BaseMapperX { */ default int updateWhenConsumptionRefund(Integer price, Long id){ LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() - .setSql(" balance = balance + " + price + ", total_expense = total_expense - " + price) + .setSql(" balance = balance + " + price + + ", total_expense = total_expense - " + price) .eq(PayWalletDO::getId, id); return update(null, lambdaUpdateWrapper); } @@ -35,7 +36,8 @@ public interface PayWalletMapper extends BaseMapperX { */ default int updateWhenConsumption(Integer price, Long id){ LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() - .setSql(" balance = balance - " + price + ", total_expense = total_expense + " + price) + .setSql(" balance = balance - " + price + + ", total_expense = total_expense + " + price) .eq(PayWalletDO::getId, id) .ge(PayWalletDO::getBalance, price); // cas 逻辑 return update(null, lambdaUpdateWrapper); diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java index 2d186b98e..f09dfc618 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java @@ -112,13 +112,14 @@ public class PayWalletServiceImpl implements PayWalletService { @Override public PayWalletTransactionDO reduceWalletBalance(Long userId, Integer userType, Long bizId, PayWalletBizTypeEnum bizType, Integer price) { - // 1.1 获取钱包 + // 1. 获取钱包 PayWalletDO payWallet = getOrCreateWallet(userId, userType); + // 2.1 扣除余额 - int number = 0 ; + int updateCounts = 0 ; switch (bizType) { case PAYMENT: { - number = walletMapper.updateWhenConsumption(price, payWallet.getId()); + updateCounts = walletMapper.updateWhenConsumption(price, payWallet.getId()); break; } case RECHARGE_REFUND: { @@ -126,11 +127,11 @@ public class PayWalletServiceImpl implements PayWalletService { break; } } - if (number == 0) { + if (updateCounts == 0) { throw exception(WALLET_BALANCE_NOT_ENOUGH); } - int afterBalance = payWallet.getBalance() - price; // 2.2 生成钱包流水 + Integer afterBalance = payWallet.getBalance() - price; CreateWalletTransactionBO bo = new CreateWalletTransactionBO().setWalletId(payWallet.getId()) .setPrice(-price).setBalance(afterBalance).setBizId(String.valueOf(bizId)) .setBizType(bizType.getType()).setTitle(bizType.getDescription()); @@ -140,7 +141,7 @@ public class PayWalletServiceImpl implements PayWalletService { @Override public PayWalletTransactionDO addWalletBalance(Long userId, Integer userType, Long bizId, PayWalletBizTypeEnum bizType, Integer price) { - // 获取钱包 + // 1. 获取钱包 PayWalletDO payWallet = getOrCreateWallet(userId, userType); switch (bizType) { case PAYMENT_REFUND: { @@ -153,7 +154,8 @@ public class PayWalletServiceImpl implements PayWalletService { break; } } - // 2.2 生成钱包流水 + + // 2. 生成钱包流水 CreateWalletTransactionBO bo = new CreateWalletTransactionBO().setWalletId(payWallet.getId()) .setPrice(price).setBalance(payWallet.getBalance()+price).setBizId(String.valueOf(bizId)) .setBizType(bizType.getType()).setTitle(bizType.getDescription()); diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionService.java index db6f778f3..52c84e159 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionService.java @@ -6,6 +6,8 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; import cn.iocoder.yudao.module.pay.service.wallet.bo.CreateWalletTransactionBO; +import javax.validation.Valid; + /** * 钱包余额流水 Service 接口 * @@ -29,7 +31,7 @@ public interface PayWalletTransactionService { * @param bo 创建钱包流水 bo * @return 新建的钱包 do */ - PayWalletTransactionDO createWalletTransaction(CreateWalletTransactionBO bo); + PayWalletTransactionDO createWalletTransaction(@Valid CreateWalletTransactionBO bo); /** * 根据 no,获取钱包余流水 @@ -46,4 +48,5 @@ public interface PayWalletTransactionService { * @return 钱包流水 */ PayWalletTransactionDO getWalletTransaction(String bizId, PayWalletBizTypeEnum type); + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java index ba27392f0..6ef32a557 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java @@ -22,10 +22,12 @@ import javax.annotation.Resource; @Service @Slf4j public class PayWalletTransactionServiceImpl implements PayWalletTransactionService { + /** * 钱包流水的 no 前缀 */ private static final String WALLET_NO_PREFIX = "W"; + @Resource private PayWalletService payWalletService; @Resource @@ -42,10 +44,10 @@ public class PayWalletTransactionServiceImpl implements PayWalletTransactionServ @Override public PayWalletTransactionDO createWalletTransaction(CreateWalletTransactionBO bo) { - PayWalletTransactionDO transactionDO = PayWalletTransactionConvert.INSTANCE.convert(bo); - transactionDO.setNo(noRedisDAO.generate(WALLET_NO_PREFIX)); - payWalletTransactionMapper.insert(transactionDO); - return transactionDO; + PayWalletTransactionDO transaction = PayWalletTransactionConvert.INSTANCE.convert(bo) + .setNo(noRedisDAO.generate(WALLET_NO_PREFIX)); + payWalletTransactionMapper.insert(transaction); + return transaction; } @Override @@ -57,4 +59,5 @@ public class PayWalletTransactionServiceImpl implements PayWalletTransactionServ public PayWalletTransactionDO getWalletTransaction(String bizId, PayWalletBizTypeEnum type) { return payWalletTransactionMapper.selectByBiz(bizId, type.getType()); } + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/bo/CreateWalletTransactionBO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/bo/CreateWalletTransactionBO.java index 2b7188606..a1b7af8be 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/bo/CreateWalletTransactionBO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/bo/CreateWalletTransactionBO.java @@ -11,6 +11,8 @@ import lombok.Data; @Data public class CreateWalletTransactionBO { + // TODO @jason:bo 的话,最好加个参数校验哈; + /** * 钱包编号 * From a47d744f648cdd60165f757254d176dd5116d919 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 9 Sep 2023 21:05:44 +0800 Subject: [PATCH 45/50] =?UTF-8?q?=E5=88=86=E9=94=80=EF=BC=9A=E7=BB=91?= =?UTF-8?q?=E5=AE=9A=E5=88=86=E9=94=80=E7=9A=84=20url=20=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../trade/api/brokerage/BrokerageApiImpl.java | 2 +- .../app/brokerage/AppBrokerageUserController.java | 15 ++++++++------- .../brokerage/user/BrokerageUserService.java | 2 +- .../brokerage/user/BrokerageUserServiceImpl.java | 2 +- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApiImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApiImpl.java index 114ba39ac..4910f07a5 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApiImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApiImpl.java @@ -27,7 +27,7 @@ public class BrokerageApiImpl implements BrokerageApi { @Override public boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser) { - return brokerageUserService.bindUser(userId, bindUserId, isNewUser); + return brokerageUserService.bindBrokerageUser(userId, bindUserId, isNewUser); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java index 83a1b25e0..208ecee2e 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java @@ -43,6 +43,13 @@ public class AppBrokerageUserController { return success(respVO); } + @PutMapping("/bind") + @Operation(summary = "绑定推广员") + @PreAuthenticated + public CommonResult bindBrokerageUser(@Valid @RequestBody AppBrokerageUserBindReqVO reqVO) { + return success(brokerageUserService.bindBrokerageUser(getLoginUserId(), reqVO.getBindUserId(), false)); + } + // TODO 芋艿:临时 mock => @GetMapping("/get-summary") @Operation(summary = "获得个人分销统计") @@ -119,15 +126,9 @@ public class AppBrokerageUserController { @GetMapping("/get-rank-by-price") @Operation(summary = "获得分销用户排行(基于佣金)") @Parameter(name = "times", description = "时间段", required = true) - public CommonResult getBrokerageUserRankByPrice( + public CommonResult bindBrokerageUser( @RequestParam("times") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) LocalDateTime[] times) { return success(1); } - @PutMapping("/bind-user") - @Operation(summary = "绑定推广员") - public CommonResult getBrokerageUserRankByPrice(@Valid AppBrokerageUserBindReqVO reqVO) { - return success(brokerageUserService.bindUser(getLoginUserId(), reqVO.getBindUserId(), false)); - } - } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java index b3d265b29..de9d0a2b7 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java @@ -103,6 +103,6 @@ public interface BrokerageUserService { * @param isNewUser 是否为新用户 * @return 是否绑定 */ - boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser); + boolean bindBrokerageUser(Long userId, Long bindUserId, Boolean isNewUser); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java index 47ad454ef..1a168d966 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java @@ -135,7 +135,7 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { // TODO @疯狂:因为现在 user 会存在使用验证码直接注册,所以 isNewUser 不太好传递;我们是不是可以约定绑定的时间,createTime 在 30 秒内,就认为新用户; @Override - public boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser) { + public boolean bindBrokerageUser(Long userId, Long bindUserId, Boolean isNewUser) { // TODO @疯狂:userId 为空,搞到参数校验里哇; if (userId == null) { throw exception(0); From 4265441e1daec669527b89a02e4e1a4850b4560c Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 9 Sep 2023 22:28:01 +0800 Subject: [PATCH 46/50] =?UTF-8?q?=E5=88=86=E9=94=80=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E5=95=86=E5=93=81=E7=9A=84=E5=88=86=E4=BD=A3=E9=87=91?= =?UTF-8?q?=E9=A2=9D=E8=AE=A1=E7=AE=97=20api=20mock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AppBrokerageRecordController.java | 12 ++++++++++++ .../AppBrokerageProductPriceRespVO.java | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageProductPriceRespVO.java diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageRecordController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageRecordController.java index d4c72028f..9569162cb 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageRecordController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageRecordController.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.controller.app.brokerage; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; +import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageProductPriceRespVO; import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordPageReqVO; import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordRespVO; import io.swagger.v3.oas.annotations.Operation; @@ -11,6 +12,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import javax.validation.Valid; @@ -40,4 +42,14 @@ public class AppBrokerageRecordController { return success(new PageResult<>(asList(vo1, vo2), 10L)); } + @GetMapping("/get-product-brokerage-price") + @Operation(summary = "获得商品的分销金额") + public CommonResult getProductBrokeragePrice(@RequestParam("spuId") Long spuId) { + AppBrokerageProductPriceRespVO respVO = new AppBrokerageProductPriceRespVO(); + respVO.setEnabled(true); // TODO @疯狂:需要开启分销 + 人允许分销 + respVO.setBrokerageMinPrice(1); + respVO.setBrokerageMaxPrice(2); + return success(respVO); + } + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageProductPriceRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageProductPriceRespVO.java new file mode 100644 index 000000000..6b2191d5f --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageProductPriceRespVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "用户 App - 商品的分销金额 Response VO") +@Data +public class AppBrokerageProductPriceRespVO { + + @Schema(description = "是否开启", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Boolean enabled; + + @Schema(description = "分销最小金额,单位:分", example = "100") + private Integer brokerageMinPrice; + + @Schema(description = "分销最大金额,单位:分", example = "100") + private Integer brokerageMaxPrice; + +} From 40e1a879e3b38d830b25f81716986d485f115d61 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 10 Sep 2023 18:01:53 +0800 Subject: [PATCH 47/50] =?UTF-8?q?=E7=99=BB=E5=BD=95=EF=BC=9A=E7=A4=BE?= =?UTF-8?q?=E4=BA=A4=E7=99=BB=E5=BD=95=E6=97=B6=EF=BC=8C=E9=A2=9D=E5=A4=96?= =?UTF-8?q?=E8=BF=94=E5=9B=9E=20openid?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/auth/AppAuthController.http | 12 +++++++- .../app/auth/vo/AppAuthLoginRespVO.java | 8 +++++ .../member/convert/auth/AuthConvert.java | 2 +- .../service/auth/MemberAuthServiceImpl.java | 30 +++++++++++-------- .../system/api/social/SocialUserApi.java | 13 ++++---- .../api/social/dto/SocialUserRespDTO.java | 27 +++++++++++++++++ .../system/api/social/SocialUserApiImpl.java | 9 +++--- .../service/auth/AdminAuthServiceImpl.java | 7 +++-- .../service/social/SocialUserService.java | 13 ++++---- .../service/social/SocialUserServiceImpl.java | 8 +++-- .../auth/AdminAuthServiceImplTest.java | 5 ++-- .../social/SocialUserServiceImplTest.java | 17 ++++++----- .../src/main/resources/application-local.yaml | 6 ++-- 13 files changed, 111 insertions(+), 46 deletions(-) create mode 100644 yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserRespDTO.java diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.http b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.http index 51252530b..648802b80 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.http +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.http @@ -28,6 +28,17 @@ tenant-id: {{appTenentId}} "code": 9999 } +### 请求 /social-login 接口 => 成功 +POST {{appApi}}/member/auth/social-login +Content-Type: application/json +tenant-id: {{appTenentId}} + +{ + "type": 34, + "code": "0e1oc9000CTjFQ1oim200bhtb61oc90g", + "state": "default" +} + ### 请求 /weixin-mini-app-login 接口 => 成功 POST {{appApi}}/member/auth/weixin-mini-app-login Content-Type: application/json @@ -38,7 +49,6 @@ tenant-id: {{appTenentId}} "loginCode": "001frTkl21JUf94VGxol2hSlff1frTkR" } - ### 请求 /logout 接口 => 成功 POST {{appApi}}/member/auth/logout Content-Type: application/json diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginRespVO.java index 41318fe59..072ec9e4b 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginRespVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginRespVO.java @@ -27,4 +27,12 @@ public class AppAuthLoginRespVO { @Schema(description = "过期时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime expiresTime; + /** + * 仅社交登录、社交绑定时会返回 + * + * 为什么需要返回?微信公众号、微信小程序支付需要传递 openid 给支付接口 + */ + @Schema(description = "社交用户 openid", example = "qq768") + private String openid; + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/auth/AuthConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/auth/AuthConvert.java index 16a8e6d4c..08c9b59ea 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/auth/AuthConvert.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/auth/AuthConvert.java @@ -25,7 +25,7 @@ public interface AuthConvert { SmsCodeUseReqDTO convert(AppMemberUserResetPasswordReqVO reqVO, SmsSceneEnum scene, String usedIp); SmsCodeUseReqDTO convert(AppAuthSmsLoginReqVO reqVO, Integer scene, String usedIp); - AppAuthLoginRespVO convert(OAuth2AccessTokenRespDTO bean); + AppAuthLoginRespVO convert(OAuth2AccessTokenRespDTO bean, String openid); SmsCodeValidateReqDTO convert(AppAuthSmsValidateReqVO bean); diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java index ed89d0a50..e8f816ea6 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java @@ -20,6 +20,7 @@ import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenRespDTO; import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; import cn.iocoder.yudao.module.system.api.social.SocialUserApi; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum; import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum; import cn.iocoder.yudao.module.system.enums.oauth2.OAuth2ClientConstants; @@ -65,13 +66,14 @@ public class MemberAuthServiceImpl implements MemberAuthService { MemberUserDO user = login0(reqVO.getMobile(), reqVO.getPassword()); // 如果 socialType 非空,说明需要绑定社交用户 + String openid = null; if (reqVO.getSocialType() != null) { - socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(), + openid = socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(), reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState())); } // 创建 Token 令牌,记录登录日志 - return createTokenAfterLoginSuccess(user, reqVO.getMobile(), LoginLogTypeEnum.LOGIN_MOBILE); + return createTokenAfterLoginSuccess(user, reqVO.getMobile(), LoginLogTypeEnum.LOGIN_MOBILE, openid); } @Override @@ -86,32 +88,33 @@ public class MemberAuthServiceImpl implements MemberAuthService { Assert.notNull(user, "获取用户失败,结果为空"); // 如果 socialType 非空,说明需要绑定社交用户 + String openid = null; if (reqVO.getSocialType() != null) { - socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(), + openid = socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(), reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState())); } // 创建 Token 令牌,记录登录日志 - return createTokenAfterLoginSuccess(user, reqVO.getMobile(), LoginLogTypeEnum.LOGIN_SMS); + return createTokenAfterLoginSuccess(user, reqVO.getMobile(), LoginLogTypeEnum.LOGIN_SMS, openid); } @Override public AppAuthLoginRespVO socialLogin(AppAuthSocialLoginReqVO reqVO) { // 使用 code 授权码,进行登录。然后,获得到绑定的用户编号 - Long userId = socialUserApi.getBindUserId(UserTypeEnum.MEMBER.getValue(), reqVO.getType(), + SocialUserRespDTO socialUser = socialUserApi.getSocialUser(UserTypeEnum.MEMBER.getValue(), reqVO.getType(), reqVO.getCode(), reqVO.getState()); - if (userId == null) { + if (socialUser == null) { throw exception(AUTH_THIRD_LOGIN_NOT_BIND); } // 自动登录 - MemberUserDO user = userService.getUser(userId); + MemberUserDO user = userService.getUser(socialUser.getUserId()); if (user == null) { throw exception(USER_NOT_EXISTS); } // 创建 Token 令牌,记录登录日志 - return createTokenAfterLoginSuccess(user, user.getMobile(), LoginLogTypeEnum.LOGIN_SOCIAL); + return createTokenAfterLoginSuccess(user, user.getMobile(), LoginLogTypeEnum.LOGIN_SOCIAL, socialUser.getOpenid()); } @Override @@ -129,14 +132,15 @@ public class MemberAuthServiceImpl implements MemberAuthService { Assert.notNull(user, "获取用户失败,结果为空"); // 绑定社交用户 - socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(), + String openid = socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(), SocialTypeEnum.WECHAT_MINI_APP.getType(), reqVO.getLoginCode(), "")); // 创建 Token 令牌,记录登录日志 - return createTokenAfterLoginSuccess(user, user.getMobile(), LoginLogTypeEnum.LOGIN_SOCIAL); + return createTokenAfterLoginSuccess(user, user.getMobile(), LoginLogTypeEnum.LOGIN_SOCIAL, openid); } - private AppAuthLoginRespVO createTokenAfterLoginSuccess(MemberUserDO user, String mobile, LoginLogTypeEnum logType) { + private AppAuthLoginRespVO createTokenAfterLoginSuccess(MemberUserDO user, String mobile, + LoginLogTypeEnum logType, String openid) { // 插入登陆日志 createLoginLog(user.getId(), mobile, logType, LoginResultEnum.SUCCESS); // 创建 Token 令牌 @@ -144,7 +148,7 @@ public class MemberAuthServiceImpl implements MemberAuthService { .setUserId(user.getId()).setUserType(getUserType().getValue()) .setClientId(OAuth2ClientConstants.CLIENT_ID_DEFAULT)); // 构建返回结果 - return AuthConvert.INSTANCE.convert(accessTokenRespDTO); + return AuthConvert.INSTANCE.convert(accessTokenRespDTO, openid); } @Override @@ -231,7 +235,7 @@ public class MemberAuthServiceImpl implements MemberAuthService { public AppAuthLoginRespVO refreshToken(String refreshToken) { OAuth2AccessTokenRespDTO accessTokenDO = oauth2TokenApi.refreshAccessToken(refreshToken, OAuth2ClientConstants.CLIENT_ID_DEFAULT); - return AuthConvert.INSTANCE.convert(accessTokenDO); + return AuthConvert.INSTANCE.convert(accessTokenDO, null); } private void createLogoutLog(Long userId) { diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java index 5d42731c2..c7c2fe459 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.api.social; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO; import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; @@ -27,8 +28,9 @@ public interface SocialUserApi { * 绑定社交用户 * * @param reqDTO 绑定信息 + * @return 社交用户 openid */ - void bindSocialUser(@Valid SocialUserBindReqDTO reqDTO); + String bindSocialUser(@Valid SocialUserBindReqDTO reqDTO); /** * 取消绑定社交用户 @@ -38,16 +40,17 @@ public interface SocialUserApi { void unbindSocialUser(@Valid SocialUserUnbindReqDTO reqDTO); /** - * 获得社交用户的绑定用户编号 - * 注意,返回的是 MemberUser 或者 AdminUser 的 id 编号! + * 获得社交用户 + * * 在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常 * * @param userType 用户类型 * @param type 社交平台的类型 * @param code 授权码 * @param state state - * @return 绑定用户编号 + * @return 社交用户 */ - Long getBindUserId(Integer userType, Integer type, String code, String state); + SocialUserRespDTO getSocialUser(Integer userType, Integer type, + String code, String state); } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserRespDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserRespDTO.java new file mode 100644 index 000000000..ac25b148e --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserRespDTO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.system.api.social.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 社交用户 Response DTO + * + * @author 芋道源码 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SocialUserRespDTO { + + /** + * 社交用户 openid + */ + private String openid; + + /** + * 关联的用户编号 + */ + private Long userId; + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java index ae8903135..d322952af 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.system.api.social; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO; import cn.iocoder.yudao.module.system.service.social.SocialUserService; import org.springframework.stereotype.Service; @@ -26,8 +27,8 @@ public class SocialUserApiImpl implements SocialUserApi { } @Override - public void bindSocialUser(SocialUserBindReqDTO reqDTO) { - socialUserService.bindSocialUser(reqDTO); + public String bindSocialUser(SocialUserBindReqDTO reqDTO) { + return socialUserService.bindSocialUser(reqDTO); } @Override @@ -37,8 +38,8 @@ public class SocialUserApiImpl implements SocialUserApi { } @Override - public Long getBindUserId(Integer userType, Integer type, String code, String state) { - return socialUserService.getBindUserId(userType, type, code, state); + public SocialUserRespDTO getSocialUser(Integer userType, Integer type, String code, String state) { + return socialUserService.getSocialUser(userType, type, code, state); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java index ca34156eb..37fac0997 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java @@ -9,6 +9,7 @@ import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO; import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*; import cn.iocoder.yudao.module.system.convert.auth.AuthConvert; import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; @@ -155,14 +156,14 @@ public class AdminAuthServiceImpl implements AdminAuthService { @Override public AuthLoginRespVO socialLogin(AuthSocialLoginReqVO reqVO) { // 使用 code 授权码,进行登录。然后,获得到绑定的用户编号 - Long userId = socialUserService.getBindUserId(UserTypeEnum.ADMIN.getValue(), reqVO.getType(), + SocialUserRespDTO socialUser = socialUserService.getSocialUser(UserTypeEnum.ADMIN.getValue(), reqVO.getType(), reqVO.getCode(), reqVO.getState()); - if (userId == null) { + if (socialUser == null) { throw exception(AUTH_THIRD_LOGIN_NOT_BIND); } // 获得用户 - AdminUserDO user = userService.getUser(userId); + AdminUserDO user = userService.getUser(socialUser.getUserId()); if (user == null) { throw exception(USER_NOT_EXISTS); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java index 6d89897bb..bc776ec60 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.service.social; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; @@ -50,8 +51,9 @@ public interface SocialUserService { * 绑定社交用户 * * @param reqDTO 绑定信息 + * @return 社交用户 openid */ - void bindSocialUser(@Valid SocialUserBindReqDTO reqDTO); + String bindSocialUser(@Valid SocialUserBindReqDTO reqDTO); /** * 取消绑定社交用户 @@ -64,15 +66,16 @@ public interface SocialUserService { void unbindSocialUser(Long userId, Integer userType, Integer type, String openid); /** - * 获得社交用户的绑定用户编号 - * 注意,返回的是 MemberUser 或者 AdminUser 的 id 编号! + * 获得社交用户 + * * 在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常 * * @param userType 用户类型 * @param type 社交平台的类型 * @param code 授权码 * @param state state - * @return 绑定用户编号 + * @return 社交用户 */ - Long getBindUserId(Integer userType, Integer type, String code, String state); + SocialUserRespDTO getSocialUser(Integer userType, Integer type, String code, String state); + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java index b6999bd01..bd5548af7 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java @@ -5,6 +5,7 @@ import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.framework.common.util.http.HttpUtils; import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserBindDO; import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserBindMapper; @@ -98,7 +99,7 @@ public class SocialUserServiceImpl implements SocialUserService { @Override @Transactional - public void bindSocialUser(SocialUserBindReqDTO reqDTO) { + public String bindSocialUser(SocialUserBindReqDTO reqDTO) { // 获得社交用户 SocialUserDO socialUser = authSocialUser(reqDTO.getType(), reqDTO.getCode(), reqDTO.getState()); Assert.notNull(socialUser, "社交用户不能为空"); @@ -115,6 +116,7 @@ public class SocialUserServiceImpl implements SocialUserService { .userId(reqDTO.getUserId()).userType(reqDTO.getUserType()) .socialUserId(socialUser.getId()).socialType(socialUser.getType()).build(); socialUserBindMapper.insert(socialUserBind); + return socialUser.getOpenid(); } @Override @@ -130,7 +132,7 @@ public class SocialUserServiceImpl implements SocialUserService { } @Override - public Long getBindUserId(Integer userType, Integer type, String code, String state) { + public SocialUserRespDTO getSocialUser(Integer userType, Integer type, String code, String state) { // 获得社交用户 SocialUserDO socialUser = authSocialUser(type, code, state); Assert.notNull(socialUser, "社交用户不能为空"); @@ -141,7 +143,7 @@ public class SocialUserServiceImpl implements SocialUserService { if (socialUserBind == null) { throw exception(AUTH_THIRD_LOGIN_NOT_BIND); } - return socialUserBind.getUserId(); + return new SocialUserRespDTO(socialUser.getOpenid(), socialUserBind.getUserId()); } /** diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImplTest.java index b0331cff2..1009e9220 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImplTest.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*; import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; @@ -235,8 +236,8 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest { AuthSocialLoginReqVO reqVO = randomPojo(AuthSocialLoginReqVO.class); // mock 方法(绑定的用户编号) Long userId = 1L; - when(socialUserService.getBindUserId(eq(UserTypeEnum.ADMIN.getValue()), eq(reqVO.getType()), - eq(reqVO.getCode()), eq(reqVO.getState()))).thenReturn(userId); + when(socialUserService.getSocialUser(eq(UserTypeEnum.ADMIN.getValue()), eq(reqVO.getType()), + eq(reqVO.getCode()), eq(reqVO.getState()))).thenReturn(new SocialUserRespDTO(randomString(), userId)); // mock(用户) AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(userId)); when(userService.getUser(eq(userId))).thenReturn(user); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImplTest.java index fcea1a864..bfbbd40aa 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImplTest.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserBindDO; import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserBindMapper; @@ -195,10 +196,11 @@ public class SocialUserServiceImplTest extends BaseDbUnitTest { .setSocialType(SocialTypeEnum.GITEE.getType()).setSocialUserId(socialUser.getId())); // 调用 - socialUserService.bindSocialUser(reqDTO); + String openid = socialUserService.bindSocialUser(reqDTO); // 断言 List socialUserBinds = socialUserBindMapper.selectList(); assertEquals(1, socialUserBinds.size()); + assertEquals(socialUser.getOpenid(), openid); } @Test @@ -232,25 +234,26 @@ public class SocialUserServiceImplTest extends BaseDbUnitTest { } @Test - public void testGetBindUserId() { + public void testGetSocialUser() { // 准备参数 Integer userType = UserTypeEnum.ADMIN.getValue(); Integer type = SocialTypeEnum.GITEE.getType(); String code = "tudou"; String state = "yuanma"; // mock 社交用户 - SocialUserDO socialUser = randomPojo(SocialUserDO.class).setType(type).setCode(code).setState(state); - socialUserMapper.insert(socialUser); + SocialUserDO socialUserDO = randomPojo(SocialUserDO.class).setType(type).setCode(code).setState(state); + socialUserMapper.insert(socialUserDO); // mock 社交用户的绑定 Long userId = randomLong(); SocialUserBindDO socialUserBind = randomPojo(SocialUserBindDO.class).setUserType(userType).setUserId(userId) - .setSocialType(type).setSocialUserId(socialUser.getId()); + .setSocialType(type).setSocialUserId(socialUserDO.getId()); socialUserBindMapper.insert(socialUserBind); // 调用 - Long result = socialUserService.getBindUserId(userType, type, code, state); + SocialUserRespDTO socialUser = socialUserService.getSocialUser(userType, type, code, state); // 断言 - assertEquals(userId, result); + assertEquals(userId, socialUser.getUserId()); + assertEquals(socialUserDO.getOpenid(), socialUser.getOpenid()); } } diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 5964261ce..4adfb0a9f 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -173,8 +173,10 @@ wx: key-prefix: wx # Redis Key 的前缀 http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台 miniapp: # 小程序配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-miniapp-spring-boot-starter/README.md 文档 - appid: wx62056c0d5e8db250 - secret: 333ae72f41552af1e998fe1f54e1584a +# appid: wx62056c0d5e8db250 +# secret: 333ae72f41552af1e998fe1f54e1584a + appid: wx63c280fe3248a3e7 # wenhualian的接口测试号 + secret: 6f270509224a7ae1296bbf1c8cb97aed config-storage: type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取 key-prefix: wa # Redis Key 的前缀 From 314dee430ed0f90e0e0ef9be3ff6e2b8d9c5529f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 11 Sep 2023 11:06:42 +0800 Subject: [PATCH 48/50] =?UTF-8?q?bugfix=EF=BC=9A=E5=BE=AE=E4=BF=A1?= =?UTF-8?q?=E5=85=AC=E4=BC=97=E5=8F=B7=E7=99=BB=E5=BD=95=E6=8A=A5=20access?= =?UTF-8?q?=20token=20=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../social/core/YudaoAuthRequestFactory.java | 9 + .../core/request/AuthWeChatMpRequest.java | 178 ++++++++++++++++++ .../src/main/resources/application-local.yaml | 11 +- 3 files changed, 196 insertions(+), 2 deletions(-) create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/request/AuthWeChatMpRequest.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/YudaoAuthRequestFactory.java b/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/YudaoAuthRequestFactory.java index 5d5475e84..6cabb0ccd 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/YudaoAuthRequestFactory.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/YudaoAuthRequestFactory.java @@ -4,6 +4,7 @@ import cn.hutool.core.util.EnumUtil; import cn.hutool.core.util.ReflectUtil; import cn.iocoder.yudao.framework.social.core.enums.AuthExtendSource; import cn.iocoder.yudao.framework.social.core.request.AuthWeChatMiniAppRequest; +import cn.iocoder.yudao.framework.social.core.request.AuthWeChatMpRequest; import com.xingyuv.jushauth.cache.AuthStateCache; import com.xingyuv.jushauth.config.AuthConfig; import com.xingyuv.jushauth.config.AuthSource; @@ -13,6 +14,8 @@ import com.xingyuv.justauth.autoconfigure.JustAuthProperties; import java.lang.reflect.Method; +import static com.xingyuv.jushauth.config.AuthDefaultSource.WECHAT_MP; + /** * 第三方授权拓展 request 工厂类 * 为使得拓展配置 {@link AuthConfig} 和默认配置齐平,所以自定义本工厂类 @@ -55,6 +58,12 @@ public class YudaoAuthRequestFactory extends AuthRequestFactory { } protected AuthRequest getExtendRequest(String source) { + // TODO 芋艿:临时兼容 justauth 迁移的类型不对问题; + if (WECHAT_MP.name().equalsIgnoreCase(source)) { + AuthConfig config = properties.getType().get(WECHAT_MP.name()); + return new AuthWeChatMpRequest(config, authStateCache); + } + AuthExtendSource authExtendSource; try { authExtendSource = EnumUtil.fromString(AuthExtendSource.class, source.toUpperCase()); diff --git a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/request/AuthWeChatMpRequest.java b/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/request/AuthWeChatMpRequest.java new file mode 100644 index 000000000..13b77cd35 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/request/AuthWeChatMpRequest.java @@ -0,0 +1,178 @@ +package cn.iocoder.yudao.framework.social.core.request; + +import com.alibaba.fastjson.JSONObject; +import com.xingyuv.jushauth.cache.AuthStateCache; +import com.xingyuv.jushauth.config.AuthConfig; +import com.xingyuv.jushauth.config.AuthDefaultSource; +import com.xingyuv.jushauth.enums.AuthResponseStatus; +import com.xingyuv.jushauth.enums.AuthUserGender; +import com.xingyuv.jushauth.enums.scope.AuthWechatMpScope; +import com.xingyuv.jushauth.exception.AuthException; +import com.xingyuv.jushauth.model.AuthCallback; +import com.xingyuv.jushauth.model.AuthResponse; +import com.xingyuv.jushauth.model.AuthToken; +import com.xingyuv.jushauth.model.AuthUser; +import com.xingyuv.jushauth.request.AuthDefaultRequest; +import com.xingyuv.jushauth.utils.AuthScopeUtils; +import com.xingyuv.jushauth.utils.GlobalAuthUtils; +import com.xingyuv.jushauth.utils.HttpUtils; +import com.xingyuv.jushauth.utils.UrlBuilder; + +/** + * 微信公众平台登录 + * + * @author yangkai.shen (https://xkcoding.com) + * @since 1.1.0 + */ +public class AuthWeChatMpRequest extends AuthDefaultRequest { + public AuthWeChatMpRequest(AuthConfig config) { + super(config, AuthDefaultSource.WECHAT_MP); + } + + public AuthWeChatMpRequest(AuthConfig config, AuthStateCache authStateCache) { + super(config, AuthDefaultSource.WECHAT_MP, authStateCache); + } + + /** + * 微信的特殊性,此时返回的信息同时包含 openid 和 access_token + * + * @param authCallback 回调返回的参数 + * @return 所有信息 + */ + @Override + protected AuthToken getAccessToken(AuthCallback authCallback) { + return this.getToken(accessTokenUrl(authCallback.getCode())); + } + + @Override + protected AuthUser getUserInfo(AuthToken authToken) { + String openId = authToken.getOpenId(); + + String response = doGetUserInfo(authToken); + JSONObject object = JSONObject.parseObject(response); + + this.checkResponse(object); + + String location = String.format("%s-%s-%s", object.getString("country"), object.getString("province"), object.getString("city")); + + if (object.containsKey("unionid")) { + authToken.setUnionId(object.getString("unionid")); + } + + return AuthUser.builder() + .rawUserInfo(object) + .username(object.getString("nickname")) + .nickname(object.getString("nickname")) + .avatar(object.getString("headimgurl")) + .location(location) + .uuid(openId) + .gender(AuthUserGender.getWechatRealGender(object.getString("sex"))) + .token(authToken) + .source(source.toString()) + .build(); + } + + @Override + public AuthResponse refresh(AuthToken oldToken) { + return AuthResponse.builder() + .code(AuthResponseStatus.SUCCESS.getCode()) + .data(this.getToken(refreshTokenUrl(oldToken.getRefreshToken()))) + .build(); + } + + /** + * 检查响应内容是否正确 + * + * @param object 请求响应内容 + */ + private void checkResponse(JSONObject object) { + if (object.containsKey("errcode")) { + throw new AuthException(object.getIntValue("errcode"), object.getString("errmsg")); + } + } + + /** + * 获取token,适用于获取access_token和刷新token + * + * @param accessTokenUrl 实际请求token的地址 + * @return token对象 + */ + private AuthToken getToken(String accessTokenUrl) { + String response = new HttpUtils(config.getHttpConfig()).get(accessTokenUrl).getBody(); + JSONObject accessTokenObject = JSONObject.parseObject(response); + + this.checkResponse(accessTokenObject); + + return AuthToken.builder() + .accessToken(accessTokenObject.getString("access_token")) + .refreshToken(accessTokenObject.getString("refresh_token")) + .expireIn(accessTokenObject.getIntValue("expires_in")) + .openId(accessTokenObject.getString("openid")) + .scope(accessTokenObject.getString("scope")) + .build(); + } + + /** + * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state} + * + * @param state state 验证授权流程的参数,可以防止csrf + * @return 返回授权地址 + * @since 1.9.3 + */ + @Override + public String authorize(String state) { + return UrlBuilder.fromBaseUrl(source.authorize()) + .queryParam("appid", config.getClientId()) + .queryParam("redirect_uri", GlobalAuthUtils.urlEncode(config.getRedirectUri())) + .queryParam("response_type", "code") + .queryParam("scope", this.getScopes(",", false, AuthScopeUtils.getDefaultScopes(AuthWechatMpScope.values()))) + .queryParam("state", getRealState(state).concat("#wechat_redirect")) + .build(); + } + + /** + * 返回获取accessToken的url + * + * @param code 授权码 + * @return 返回获取accessToken的url + */ + @Override + protected String accessTokenUrl(String code) { + return UrlBuilder.fromBaseUrl(source.accessToken()) + .queryParam("appid", config.getClientId()) + .queryParam("secret", config.getClientSecret()) + .queryParam("code", code) + .queryParam("grant_type", "authorization_code") + .build(); + } + + /** + * 返回获取userInfo的url + * + * @param authToken 用户授权后的token + * @return 返回获取userInfo的url + */ + @Override + protected String userInfoUrl(AuthToken authToken) { + return UrlBuilder.fromBaseUrl(source.userInfo()) + .queryParam("access_token", authToken.getAccessToken()) + .queryParam("openid", authToken.getOpenId()) + .queryParam("lang", "zh_CN") + .build(); + } + + /** + * 返回获取userInfo的url + * + * @param refreshToken getAccessToken方法返回的refreshToken + * @return 返回获取userInfo的url + */ + @Override + protected String refreshTokenUrl(String refreshToken) { + return UrlBuilder.fromBaseUrl(source.refresh()) + .queryParam("appid", config.getClientId()) + .queryParam("grant_type", "refresh_token") + .queryParam("refresh_token", refreshToken) + .build(); + } +} diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 4adfb0a9f..5dc82c68c 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -165,8 +165,10 @@ debug: false --- #################### 微信公众号、小程序相关配置 #################### wx: mp: # 公众号配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-mp-spring-boot-starter/README.md 文档 - app-id: wx041349c6f39b268b - secret: 5abee519483bc9f8cb37ce280e814bd0 +# app-id: wx041349c6f39b268b +# secret: 5abee519483bc9f8cb37ce280e814bd0 + app-id: wx5b23ba7a5589ecbb # 测试号 + secret: 2a7b3b20c537e52e74afd395eb85f61f # 存储配置,解决 AccessToken 的跨节点的共享 config-storage: type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取 @@ -221,6 +223,11 @@ justauth: client-secret: ${wx.miniapp.secret} ignore-check-redirect-uri: true ignore-check-state: true # 微信小程序,不会使用到 state,所以不进行校验 + WECHAT_MP: # 微信公众号 + client-id: ${wx.mp.app-id} + client-secret: ${wx.mp.secret} + ignore-check-redirect-uri: true + ignore-check-state: true # 微信公众号,未调用后端的 getSocialAuthorizeUrl 方法,所以无法进行 state 校验 TODO 芋艿:后续考虑支持 cache: type: REDIS From f2ee213caaded5fa78e3c700cd34361edf7fbb85 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 11 Sep 2023 16:42:38 +0800 Subject: [PATCH 49/50] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=95=86=E5=9F=8E?= =?UTF-8?q?=E7=9A=84=E6=BC=94=E7=A4=BA=E5=9C=B0=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ++++-- pom.xml | 4 ++-- yudao-server/pom.xml | 40 ++++++++++++++++++++-------------------- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 27b3bef37..f3e810b7a 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ | [yudao-ui-admin](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin) | [![Gitee star](https://gitee.com/zhijiantianya/ruoyi-vue-pro/badge/star.svg?theme=white)](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin) [![GitHub stars](https://img.shields.io/github/stars/YunaiV/ruoyi-vue-pro.svg?style=social&label=Stars)](https://github.com/YunaiV/ruoyi-vue-pro/tree/master/yudao-ui-admin) | 基于 Vue2 + element-ui 实现的管理后台 | | [yudao-ui-admin-uniapp](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin-uniapp) | [![Gitee star](https://gitee.com/zhijiantianya/ruoyi-vue-pro/badge/star.svg?theme=white)](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin-uniapp) [![GitHub stars](https://img.shields.io/github/stars/YunaiV/ruoyi-vue-pro.svg?style=social&label=Stars)](https://github.com/YunaiV/ruoyi-vue-pro/tree/master/yudao-ui-admin-uniapp) | 基于 uni-app + uni-ui 实现的管理后台的小程序 | | [yudao-ui-go-view](https://gitee.com/yudaocode/yudao-ui-go-view) | [![Gitee star](https://gitee.com/yudaocode/yudao-ui-go-view/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-ui-go-view) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-ui-go-view.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-ui-go-view) | 基于 Vue3 + naive-ui 实现的大屏报表 | -| [yudao-ui-app](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-app) | [![Gitee star](https://gitee.com/zhijiantianya/ruoyi-vue-pro/badge/star.svg?theme=white)](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-app) [![GitHub stars](https://img.shields.io/github/stars/YunaiV/ruoyi-vue-pro.svg?style=social&label=Stars)](https://github.com/YunaiV/ruoyi-vue-pro/tree/master/yudao-ui-app) | 基于 uni-app + uview 实现的用户 App | +| [yudao-ui-app](https://gitee.com/yudaocode/yudao-mall-uniapp) | [![Gitee star](https://gitee.com/yudaocode/yudao-mall-uniapp/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-mall-uniapp) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-mall-uniapp.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-mall-uniapp) | 基于 uni-app 实现的商城小程序 | ## 🐰 分支说明 @@ -218,7 +218,9 @@ ![功能图](/.image/common/mall-preview.png) -前端基于 crmeb uniapp 经过授权重构,优化代码实现,接入芋道快速开发平台 +_前端基于 crmeb uniapp 经过授权重构,优化代码实现,接入芋道快速开发平台_ + +演示地址: ### 会员中心 diff --git a/pom.xml b/pom.xml index ccd2a517d..ad7d84c85 100644 --- a/pom.xml +++ b/pom.xml @@ -19,8 +19,8 @@ - yudao-module-pay - yudao-module-mall + + yudao-example diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index a20f27098..9e676233a 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -54,11 +54,11 @@ - - cn.iocoder.boot - yudao-module-pay-biz - ${revision} - + + + + + @@ -68,21 +68,21 @@ - - cn.iocoder.boot - yudao-module-promotion-biz - ${revision} - - - cn.iocoder.boot - yudao-module-product-biz - ${revision} - - - cn.iocoder.boot - yudao-module-trade-biz - ${revision} - + + + + + + + + + + + + + + + From 1f327ef8ca343919702e405e362b705aeef1ddcb Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 11 Sep 2023 16:55:56 +0800 Subject: [PATCH 50/50] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=95=86=E5=9F=8E?= =?UTF-8?q?=E7=9A=84=E6=BC=94=E7=A4=BA=E5=9C=B0=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- yudao-ui-app/.editorconfig | 22 - yudao-ui-app/.gitignore | 7 - yudao-ui-app/App.vue | 34 - yudao-ui-app/README.md | 1 + yudao-ui-app/api/address.js | 15 - yudao-ui-app/api/auth.js | 15 - yudao-ui-app/api/cart.js | 5 - yudao-ui-app/api/category.js | 5 - yudao-ui-app/api/index.js | 7 - yudao-ui-app/api/order.js | 6 - yudao-ui-app/api/product.js | 8 - yudao-ui-app/api/user.js | 14 - yudao-ui-app/app.scss | 8 - yudao-ui-app/common/config.js | 13 - yudao-ui-app/common/mixin.js | 5 - yudao-ui-app/common/orderStatus.js | 7 - yudao-ui-app/common/props.js | 3 - .../components/w-picker/areadata/areadata.js | 1 - .../components/w-picker/date-picker.vue | 742 --------- .../components/w-picker/half-picker.vue | 345 ----- .../components/w-picker/linkage-picker.vue | 274 ---- .../components/w-picker/range-picker.vue | 344 ----- .../components/w-picker/region-picker.vue | 183 --- .../components/w-picker/selector-picker.vue | 129 -- .../components/w-picker/shortterm-picker.vue | 250 --- .../components/w-picker/time-picker.vue | 218 --- yudao-ui-app/components/w-picker/w-picker.css | 26 - yudao-ui-app/components/w-picker/w-picker.vue | 340 ----- .../yd-address-select/yd-address-select.vue | 106 -- .../components/yd-banner/yd-banner.vue | 58 - .../yd-cart-product/yd-cart-product.vue | 116 -- .../yd-order-product/yd-order-product.vue | 100 -- .../yd-product-box/yd-product-box.vue | 173 --- .../yd-product-more/yd-product-more.vue | 114 -- .../yd-text-price/yd-text-price.vue | 73 - yudao-ui-app/index.html | 20 - yudao-ui-app/main.js | 26 - yudao-ui-app/manifest.json | 72 - yudao-ui-app/pages.json | 156 -- yudao-ui-app/pages/address/create.vue | 148 -- yudao-ui-app/pages/address/list.vue | 116 -- yudao-ui-app/pages/address/update.vue | 178 --- yudao-ui-app/pages/cart/cart.vue | 225 --- yudao-ui-app/pages/category/category.vue | 205 --- yudao-ui-app/pages/category/product-list.vue | 164 -- yudao-ui-app/pages/checkout/checkout.vue | 219 --- yudao-ui-app/pages/forgot/forgot.vue | 157 -- yudao-ui-app/pages/index/index.vue | 149 -- yudao-ui-app/pages/login/mobile.vue | 197 --- yudao-ui-app/pages/login/social.vue | 117 -- yudao-ui-app/pages/order/confirm.vue | 63 - yudao-ui-app/pages/order/detail.vue | 252 ---- yudao-ui-app/pages/order/list.vue | 195 --- yudao-ui-app/pages/product/product.vue | 576 ------- yudao-ui-app/pages/profile/profile.vue | 128 -- yudao-ui-app/pages/search/search.vue | 19 - yudao-ui-app/pages/setting/setting.vue | 62 - yudao-ui-app/pages/user/user.vue | 203 --- yudao-ui-app/sitemap.json | 7 - yudao-ui-app/static/images/empty/address.png | Bin 19443 -> 0 bytes yudao-ui-app/static/images/empty/cart.png | Bin 28547 -> 0 bytes yudao-ui-app/static/images/empty/comment.png | Bin 13930 -> 0 bytes yudao-ui-app/static/images/empty/coupon.png | Bin 23450 -> 0 bytes yudao-ui-app/static/images/empty/data.png | Bin 17165 -> 0 bytes yudao-ui-app/static/images/empty/favor.png | Bin 16647 -> 0 bytes yudao-ui-app/static/images/empty/history.png | Bin 26607 -> 0 bytes yudao-ui-app/static/images/empty/list.png | Bin 17619 -> 0 bytes yudao-ui-app/static/images/empty/message.png | Bin 16362 -> 0 bytes yudao-ui-app/static/images/empty/news.png | Bin 16711 -> 0 bytes yudao-ui-app/static/images/empty/order.png | Bin 16135 -> 0 bytes yudao-ui-app/static/images/empty/page.png | Bin 28220 -> 0 bytes .../static/images/empty/permission.png | Bin 19627 -> 0 bytes yudao-ui-app/static/images/empty/search.png | Bin 18545 -> 0 bytes yudao-ui-app/static/images/empty/wifi.png | Bin 21381 -> 0 bytes .../static/images/tabbar/cart-active.png | Bin 6304 -> 0 bytes yudao-ui-app/static/images/tabbar/cart.png | Bin 6169 -> 0 bytes .../static/images/tabbar/category-active.png | Bin 8172 -> 0 bytes .../static/images/tabbar/category.png | Bin 7893 -> 0 bytes .../static/images/tabbar/index-active.png | Bin 6891 -> 0 bytes yudao-ui-app/static/images/tabbar/index.png | Bin 6766 -> 0 bytes .../static/images/tabbar/user-active.png | Bin 8298 -> 0 bytes yudao-ui-app/static/images/tabbar/user.png | Bin 8070 -> 0 bytes yudao-ui-app/store/getters.js | 7 - yudao-ui-app/store/index.js | 17 - yudao-ui-app/store/mudules/cart.js | 28 - yudao-ui-app/store/mudules/user.js | 101 -- yudao-ui-app/styles/base.scss | 5 - yudao-ui-app/uni.scss | 60 - yudao-ui-app/uni_modules/uview-ui/LICENSE | 21 - yudao-ui-app/uni_modules/uview-ui/README.md | 66 - .../uni_modules/uview-ui/changelog.md | 357 ----- .../uview-ui/components/u--form/u--form.vue | 78 - .../uview-ui/components/u--image/u--image.vue | 47 - .../uview-ui/components/u--input/u--input.vue | 73 - .../uview-ui/components/u--text/u--text.vue | 44 - .../components/u--textarea/u--textarea.vue | 48 - .../components/u-action-sheet/props.js | 54 - .../u-action-sheet/u-action-sheet.vue | 278 ---- .../uview-ui/components/u-album/props.js | 59 - .../uview-ui/components/u-album/u-album.vue | 259 ---- .../uview-ui/components/u-alert/props.js | 44 - .../uview-ui/components/u-alert/u-alert.vue | 243 --- .../components/u-avatar-group/props.js | 52 - .../u-avatar-group/u-avatar-group.vue | 103 -- .../uview-ui/components/u-avatar/props.js | 78 - .../uview-ui/components/u-avatar/u-avatar.vue | 172 --- .../uview-ui/components/u-back-top/props.js | 54 - .../components/u-back-top/u-back-top.vue | 129 -- .../uview-ui/components/u-badge/props.js | 72 - .../uview-ui/components/u-badge/u-badge.vue | 171 --- .../uview-ui/components/u-button/nvue.scss | 46 - .../uview-ui/components/u-button/props.js | 161 -- .../uview-ui/components/u-button/u-button.vue | 490 ------ .../uview-ui/components/u-button/vue.scss | 80 - .../uview-ui/components/u-calendar/header.vue | 99 -- .../uview-ui/components/u-calendar/month.vue | 579 ------- .../uview-ui/components/u-calendar/props.js | 144 -- .../components/u-calendar/u-calendar.vue | 384 ----- .../uview-ui/components/u-calendar/util.js | 85 -- .../components/u-car-keyboard/props.js | 14 - .../u-car-keyboard/u-car-keyboard.vue | 311 ---- .../uview-ui/components/u-cell-group/props.js | 14 - .../components/u-cell-group/u-cell-group.vue | 61 - .../uview-ui/components/u-cell/props.js | 110 -- .../uview-ui/components/u-cell/u-cell.vue | 229 --- .../components/u-checkbox-group/props.js | 82 - .../u-checkbox-group/u-checkbox-group.vue | 103 -- .../uview-ui/components/u-checkbox/props.js | 69 - .../components/u-checkbox/u-checkbox.vue | 344 ----- .../components/u-circle-progress/props.js | 8 - .../u-circle-progress/u-circle-progress.vue | 198 --- .../uview-ui/components/u-code-input/props.js | 79 - .../components/u-code-input/u-code-input.vue | 252 ---- .../uview-ui/components/u-code/props.js | 34 - .../uview-ui/components/u-code/u-code.vue | 129 -- .../uview-ui/components/u-col/props.js | 29 - .../uview-ui/components/u-col/u-col.vue | 162 -- .../components/u-collapse-item/props.js | 59 - .../u-collapse-item/u-collapse-item.vue | 225 --- .../uview-ui/components/u-collapse/props.js | 19 - .../components/u-collapse/u-collapse.vue | 90 -- .../components/u-column-notice/props.js | 55 - .../u-column-notice/u-column-notice.vue | 160 -- .../uview-ui/components/u-count-down/props.js | 24 - .../components/u-count-down/u-count-down.vue | 163 -- .../uview-ui/components/u-count-down/utils.js | 62 - .../uview-ui/components/u-count-to/props.js | 59 - .../components/u-count-to/u-count-to.vue | 184 --- .../components/u-datetime-picker/props.js | 116 -- .../u-datetime-picker/u-datetime-picker.vue | 360 ----- .../uview-ui/components/u-divider/props.js | 44 - .../components/u-divider/u-divider.vue | 116 -- .../components/u-dropdown-item/props.js | 36 - .../u-dropdown-item/u-dropdown-item.vue | 127 -- .../uview-ui/components/u-dropdown/props.js | 65 - .../components/u-dropdown/u-dropdown.vue | 127 -- .../uview-ui/components/u-empty/props.js | 59 - .../uview-ui/components/u-empty/u-empty.vue | 128 -- .../uview-ui/components/u-form-item/props.js | 48 - .../components/u-form-item/u-form-item.vue | 235 --- .../uview-ui/components/u-form/props.js | 45 - .../uview-ui/components/u-form/u-form.vue | 214 --- .../uview-ui/components/u-gap/props.js | 24 - .../uview-ui/components/u-gap/u-gap.vue | 38 - .../uview-ui/components/u-grid-item/props.js | 14 - .../components/u-grid-item/u-grid-item.vue | 209 --- .../uview-ui/components/u-grid/props.js | 19 - .../uview-ui/components/u-grid/u-grid.vue | 97 -- .../uview-ui/components/u-icon/icons.js | 214 --- .../uview-ui/components/u-icon/props.js | 89 -- .../uview-ui/components/u-icon/u-icon.vue | 234 --- .../uview-ui/components/u-image/props.js | 84 -- .../uview-ui/components/u-image/u-image.vue | 232 --- .../components/u-index-anchor/props.js | 29 - .../u-index-anchor/u-index-anchor.vue | 91 -- .../uview-ui/components/u-index-item/props.js | 5 - .../components/u-index-item/u-index-item.vue | 87 -- .../uview-ui/components/u-index-list/props.js | 29 - .../components/u-index-list/u-index-list.vue | 440 ------ .../uview-ui/components/u-input/props.js | 187 --- .../uview-ui/components/u-input/u-input.vue | 354 ----- .../uview-ui/components/u-keyboard/props.js | 84 -- .../components/u-keyboard/u-keyboard.vue | 164 -- .../components/u-line-progress/props.js | 28 - .../u-line-progress/u-line-progress.vue | 144 -- .../uview-ui/components/u-line/props.js | 33 - .../uview-ui/components/u-line/u-line.vue | 62 - .../uview-ui/components/u-link/props.js | 39 - .../uview-ui/components/u-link/u-link.vue | 83 - .../uview-ui/components/u-list-item/props.js | 9 - .../components/u-list-item/u-list-item.vue | 116 -- .../uview-ui/components/u-list/props.js | 76 - .../uview-ui/components/u-list/u-list.vue | 157 -- .../components/u-loading-icon/props.js | 59 - .../u-loading-icon/u-loading-icon.vue | 343 ----- .../components/u-loading-page/props.js | 49 - .../u-loading-page/u-loading-page.vue | 115 -- .../uview-ui/components/u-loadmore/props.js | 94 -- .../components/u-loadmore/u-loadmore.vue | 150 -- .../uview-ui/components/u-modal/props.js | 84 -- .../uview-ui/components/u-modal/u-modal.vue | 227 --- .../uview-ui/components/u-navbar/props.js | 84 -- .../uview-ui/components/u-navbar/u-navbar.vue | 186 --- .../uview-ui/components/u-no-network/props.js | 19 - .../components/u-no-network/u-no-network.vue | 220 --- .../uview-ui/components/u-notice-bar/props.js | 70 - .../components/u-notice-bar/u-notice-bar.vue | 101 -- .../uview-ui/components/u-notify/props.js | 49 - .../uview-ui/components/u-notify/u-notify.vue | 211 --- .../uview-ui/components/u-number-box/props.js | 109 -- .../components/u-number-box/u-number-box.vue | 416 ----- .../components/u-number-keyboard/props.js | 19 - .../u-number-keyboard/u-number-keyboard.vue | 196 --- .../uview-ui/components/u-overlay/props.js | 24 - .../components/u-overlay/u-overlay.vue | 68 - .../uview-ui/components/u-parse/node/node.vue | 499 ------ .../uview-ui/components/u-parse/parser.js | 1075 ------------- .../uview-ui/components/u-parse/props.js | 45 - .../uview-ui/components/u-parse/u-parse.vue | 366 ----- .../components/u-picker-column/props.js | 5 - .../u-picker-column/u-picker-column.vue | 27 - .../uview-ui/components/u-picker/props.js | 79 - .../uview-ui/components/u-picker/u-picker.vue | 283 ---- .../uview-ui/components/u-popup/props.js | 79 - .../uview-ui/components/u-popup/u-popup.vue | 304 ---- .../components/u-radio-group/props.js | 85 -- .../u-radio-group/u-radio-group.vue | 108 -- .../uview-ui/components/u-radio/props.js | 64 - .../uview-ui/components/u-radio/u-radio.vue | 339 ----- .../uview-ui/components/u-rate/props.js | 69 - .../uview-ui/components/u-rate/u-rate.vue | 306 ---- .../uview-ui/components/u-read-more/props.js | 61 - .../components/u-read-more/u-read-more.vue | 157 -- .../uview-ui/components/u-row-notice/props.js | 39 - .../components/u-row-notice/u-row-notice.vue | 330 ---- .../uview-ui/components/u-row/props.js | 19 - .../uview-ui/components/u-row/u-row.vue | 93 -- .../components/u-safe-bottom/props.js | 5 - .../u-safe-bottom/u-safe-bottom.vue | 56 - .../uview-ui/components/u-scroll-list/nvue.js | 28 - .../components/u-scroll-list/other.js | 0 .../components/u-scroll-list/props.js | 34 - .../components/u-scroll-list/scrollWxs.wxs | 50 - .../u-scroll-list/u-scroll-list.vue | 224 --- .../uview-ui/components/u-search/props.js | 118 -- .../uview-ui/components/u-search/u-search.vue | 303 ---- .../uview-ui/components/u-skeleton/props.js | 59 - .../components/u-skeleton/u-skeleton.vue | 244 --- .../uview-ui/components/u-slider/mpother.js | 113 -- .../uview-ui/components/u-slider/mpwxs.js | 42 - .../uview-ui/components/u-slider/mpwxs.wxs | 121 -- .../components/u-slider/nvue - 副本.js | 180 --- .../uview-ui/components/u-slider/nvue.js | 193 --- .../uview-ui/components/u-slider/props.js | 54 - .../uview-ui/components/u-slider/u-slider.vue | 55 - .../uview-ui/components/u-status-bar/props.js | 8 - .../components/u-status-bar/u-status-bar.vue | 46 - .../uview-ui/components/u-steps-item/props.js | 24 - .../components/u-steps-item/u-steps-item.vue | 316 ---- .../uview-ui/components/u-steps/props.js | 39 - .../uview-ui/components/u-steps/u-steps.vue | 80 - .../uview-ui/components/u-sticky/props.js | 40 - .../uview-ui/components/u-sticky/u-sticky.vue | 212 --- .../uview-ui/components/u-subsection/props.js | 49 - .../components/u-subsection/u-subsection.vue | 299 ---- .../u-swipe-action-item/index - backup.wxs | 256 ---- .../components/u-swipe-action-item/index.wxs | 225 --- .../u-swipe-action-item/nvue - backup.js | 270 ---- .../components/u-swipe-action-item/nvue.js | 174 --- .../components/u-swipe-action-item/props.js | 41 - .../u-swipe-action-item.vue | 190 --- .../components/u-swipe-action-item/wxs.js | 15 - .../components/u-swipe-action/props.js | 9 - .../u-swipe-action/u-swipe-action.vue | 67 - .../components/u-swiper-indicator/props.js | 29 - .../u-swiper-indicator/u-swiper-indicator.vue | 110 -- .../uview-ui/components/u-swiper/props.js | 125 -- .../uview-ui/components/u-swiper/u-swiper.vue | 255 ---- .../uview-ui/components/u-switch/props.js | 54 - .../uview-ui/components/u-switch/u-switch.vue | 177 --- .../components/u-tabbar-item/props.js | 35 - .../u-tabbar-item/u-tabbar-item.vue | 142 -- .../uview-ui/components/u-tabbar/props.js | 44 - .../uview-ui/components/u-tabbar/u-tabbar.vue | 141 -- .../uview-ui/components/u-table/props.js | 5 - .../uview-ui/components/u-table/u-table.vue | 29 - .../uview-ui/components/u-tabs-item/props.js | 5 - .../components/u-tabs-item/u-tabs-item.vue | 29 - .../uview-ui/components/u-tabs/props.js | 64 - .../uview-ui/components/u-tabs/u-tabs.vue | 354 ----- .../uview-ui/components/u-tag/props.js | 84 -- .../uview-ui/components/u-tag/u-tag.vue | 358 ----- .../uview-ui/components/u-td/props.js | 5 - .../uview-ui/components/u-td/u-td.vue | 31 - .../uview-ui/components/u-text/props.js | 110 -- .../uview-ui/components/u-text/u-text.vue | 223 --- .../uview-ui/components/u-text/value.js | 85 -- .../uview-ui/components/u-textarea/props.js | 119 -- .../components/u-textarea/u-textarea.vue | 239 --- .../uview-ui/components/u-toast/u-toast.vue | 291 ---- .../uview-ui/components/u-toolbar/props.js | 34 - .../components/u-toolbar/u-toolbar.vue | 102 -- .../components/u-tooltip/clipboard.min.js | 58 - .../uview-ui/components/u-tooltip/props.js | 59 - .../components/u-tooltip/u-tooltip.vue | 365 ----- .../uview-ui/components/u-tr/props.js | 5 - .../uview-ui/components/u-tr/u-tr.vue | 31 - .../components/u-transition/nvue.ani-map.js | 68 - .../uview-ui/components/u-transition/props.js | 24 - .../components/u-transition/transition.js | 157 -- .../components/u-transition/u-transition.vue | 92 -- .../u-transition/vue.ani-style.scss | 113 -- .../uview-ui/components/u-upload/mixin.js | 21 - .../uview-ui/components/u-upload/props.js | 124 -- .../uview-ui/components/u-upload/u-upload.vue | 558 ------- .../uview-ui/components/u-upload/utils.js | 151 -- .../uview-ui/components/uview-ui/uview-ui.vue | 15 - yudao-ui-app/uni_modules/uview-ui/index.js | 79 - yudao-ui-app/uni_modules/uview-ui/index.scss | 23 - .../uni_modules/uview-ui/libs/config/color.js | 17 - .../uview-ui/libs/config/config.js | 34 - .../uni_modules/uview-ui/libs/config/props.js | 190 --- .../uview-ui/libs/config/props/actionSheet.js | 25 - .../uview-ui/libs/config/props/album.js | 25 - .../uview-ui/libs/config/props/alert.js | 22 - .../uview-ui/libs/config/props/avatar.js | 28 - .../uview-ui/libs/config/props/avatarGroup.js | 23 - .../uview-ui/libs/config/props/backtop.js | 27 - .../uview-ui/libs/config/props/badge.js | 27 - .../uview-ui/libs/config/props/button.js | 42 - .../uview-ui/libs/config/props/calendar.js | 42 - .../uview-ui/libs/config/props/carKeyboard.js | 15 - .../uview-ui/libs/config/props/cell.js | 35 - .../uview-ui/libs/config/props/cellGroup.js | 17 - .../uview-ui/libs/config/props/checkbox.js | 27 - .../libs/config/props/checkboxGroup.js | 29 - .../libs/config/props/circleProgress.js | 15 - .../uview-ui/libs/config/props/code.js | 21 - .../uview-ui/libs/config/props/codeInput.js | 29 - .../uview-ui/libs/config/props/col.js | 19 - .../uview-ui/libs/config/props/collapse.js | 17 - .../libs/config/props/collapseItem.js | 25 - .../libs/config/props/columnNotice.js | 24 - .../uview-ui/libs/config/props/countDown.js | 18 - .../uview-ui/libs/config/props/countTo.js | 25 - .../libs/config/props/datetimePicker.js | 36 - .../uview-ui/libs/config/props/divider.js | 23 - .../uview-ui/libs/config/props/empty.js | 26 - .../uview-ui/libs/config/props/form.js | 22 - .../uview-ui/libs/config/props/formItem.js | 23 - .../uview-ui/libs/config/props/gap.js | 19 - .../uview-ui/libs/config/props/grid.js | 17 - .../uview-ui/libs/config/props/gridItem.js | 16 - .../uview-ui/libs/config/props/icon.js | 36 - .../uview-ui/libs/config/props/image.js | 30 - .../uview-ui/libs/config/props/indexAnchor.js | 19 - .../uview-ui/libs/config/props/indexList.js | 19 - .../uview-ui/libs/config/props/input.js | 48 - .../uview-ui/libs/config/props/keyboard.js | 30 - .../uview-ui/libs/config/props/line.js | 20 - .../libs/config/props/lineProgress.js | 19 - .../uview-ui/libs/config/props/link.js | 26 - .../uview-ui/libs/config/props/list.js | 28 - .../uview-ui/libs/config/props/listItem.js | 15 - .../uview-ui/libs/config/props/loadingIcon.js | 30 - .../uview-ui/libs/config/props/loadingPage.js | 23 - .../uview-ui/libs/config/props/loadmore.js | 32 - .../uview-ui/libs/config/props/modal.js | 30 - .../uview-ui/libs/config/props/navbar.js | 32 - .../uview-ui/libs/config/props/noNetwork.js | 18 - .../uview-ui/libs/config/props/noticeBar.js | 27 - .../uview-ui/libs/config/props/notify.js | 22 - .../uview-ui/libs/config/props/numberBox.js | 35 - .../libs/config/props/numberKeyboard.js | 17 - .../uview-ui/libs/config/props/overlay.js | 18 - .../uview-ui/libs/config/props/parse.js | 22 - .../uview-ui/libs/config/props/picker.js | 29 - .../uview-ui/libs/config/props/popup.js | 29 - .../uview-ui/libs/config/props/radio.js | 27 - .../uview-ui/libs/config/props/radioGroup.js | 30 - .../uview-ui/libs/config/props/rate.js | 26 - .../uview-ui/libs/config/props/readMore.js | 22 - .../uview-ui/libs/config/props/row.js | 17 - .../uview-ui/libs/config/props/rowNotice.js | 21 - .../uview-ui/libs/config/props/scrollList.js | 20 - .../uview-ui/libs/config/props/search.js | 37 - .../uview-ui/libs/config/props/section.js | 24 - .../uview-ui/libs/config/props/skeleton.js | 25 - .../uview-ui/libs/config/props/slider.js | 25 - .../uview-ui/libs/config/props/statusBar.js | 15 - .../uview-ui/libs/config/props/steps.js | 21 - .../uview-ui/libs/config/props/stepsItem.js | 18 - .../uview-ui/libs/config/props/sticky.js | 20 - .../uview-ui/libs/config/props/subsection.js | 23 - .../uview-ui/libs/config/props/swipeAction.js | 15 - .../libs/config/props/swipeActionItem.js | 21 - .../uview-ui/libs/config/props/swiper.js | 39 - .../libs/config/props/swipterIndicator.js | 19 - .../uview-ui/libs/config/props/switch.js | 24 - .../uview-ui/libs/config/props/tabbar.js | 22 - .../uview-ui/libs/config/props/tabbarItem.js | 20 - .../uview-ui/libs/config/props/tabs.js | 32 - .../uview-ui/libs/config/props/tag.js | 29 - .../uview-ui/libs/config/props/text.js | 38 - .../uview-ui/libs/config/props/textarea.js | 36 - .../uview-ui/libs/config/props/toast.js | 30 - .../uview-ui/libs/config/props/toolbar.js | 21 - .../uview-ui/libs/config/props/tooltip.js | 25 - .../uview-ui/libs/config/props/transition.js | 18 - .../uview-ui/libs/config/props/upload.js | 36 - .../uview-ui/libs/config/zIndex.js | 20 - .../uni_modules/uview-ui/libs/css/color.scss | 155 -- .../uni_modules/uview-ui/libs/css/common.scss | 97 -- .../uview-ui/libs/css/components.scss | 15 - .../uni_modules/uview-ui/libs/css/flex.scss | 257 ---- .../uni_modules/uview-ui/libs/css/h5.scss | 0 .../uni_modules/uview-ui/libs/css/mixin.scss | 8 - .../uni_modules/uview-ui/libs/css/mp.scss | 0 .../uni_modules/uview-ui/libs/css/nvue.scss | 0 .../uni_modules/uview-ui/libs/css/vue.scss | 27 - .../uview-ui/libs/function/colorGradient.js | 134 -- .../uview-ui/libs/function/debounce.js | 29 - .../uview-ui/libs/function/digit.js | 167 -- .../uview-ui/libs/function/index.js | 705 --------- .../uview-ui/libs/function/platform.js | 75 - .../uview-ui/libs/function/test.js | 288 ---- .../uview-ui/libs/function/throttle.js | 30 - .../libs/luch-request/adapters/index.js | 97 -- .../luch-request/core/InterceptorManager.js | 50 - .../libs/luch-request/core/Request.js | 198 --- .../libs/luch-request/core/buildFullPath.js | 20 - .../libs/luch-request/core/defaults.js | 29 - .../libs/luch-request/core/dispatchRequest.js | 3 - .../libs/luch-request/core/mergeConfig.js | 103 -- .../uview-ui/libs/luch-request/core/settle.js | 16 - .../libs/luch-request/helpers/buildURL.js | 69 - .../libs/luch-request/helpers/combineURLs.js | 14 - .../luch-request/helpers/isAbsoluteURL.js | 14 - .../uview-ui/libs/luch-request/index.d.ts | 116 -- .../uview-ui/libs/luch-request/index.js | 3 - .../uview-ui/libs/luch-request/utils.js | 131 -- .../uview-ui/libs/luch-request/utils/clone.js | 264 ---- .../uni_modules/uview-ui/libs/mixin/button.js | 13 - .../uni_modules/uview-ui/libs/mixin/mixin.js | 160 -- .../uview-ui/libs/mixin/mpMixin.js | 8 - .../uview-ui/libs/mixin/mpShare.js | 13 - .../uview-ui/libs/mixin/openType.js | 25 - .../uni_modules/uview-ui/libs/mixin/style.js | 228 --- .../uni_modules/uview-ui/libs/mixin/touch.js | 59 - .../uview-ui/libs/util/async-validator.js | 1343 ----------------- .../uview-ui/libs/util/calendar.js | 546 ------- .../uni_modules/uview-ui/libs/util/dayjs.js | 308 ---- .../uni_modules/uview-ui/libs/util/emitter.js | 51 - .../uni_modules/uview-ui/libs/util/route.js | 124 -- .../uni_modules/uview-ui/package.json | 84 -- yudao-ui-app/uni_modules/uview-ui/theme.scss | 44 - yudao-ui-app/utils/request/errorCode.js | 6 - yudao-ui-app/utils/request/index.js | 14 - .../utils/request/requestInterceptors.js | 20 - .../utils/request/responseInterceptors.js | 101 -- yudao-ui-app/utils/tree.js | 59 - yudao-ui-app/vue.config.js | 10 - 463 files changed, 2 insertions(+), 46314 deletions(-) delete mode 100644 yudao-ui-app/.editorconfig delete mode 100644 yudao-ui-app/.gitignore delete mode 100644 yudao-ui-app/App.vue create mode 100644 yudao-ui-app/README.md delete mode 100644 yudao-ui-app/api/address.js delete mode 100644 yudao-ui-app/api/auth.js delete mode 100644 yudao-ui-app/api/cart.js delete mode 100644 yudao-ui-app/api/category.js delete mode 100644 yudao-ui-app/api/index.js delete mode 100644 yudao-ui-app/api/order.js delete mode 100644 yudao-ui-app/api/product.js delete mode 100644 yudao-ui-app/api/user.js delete mode 100644 yudao-ui-app/app.scss delete mode 100644 yudao-ui-app/common/config.js delete mode 100644 yudao-ui-app/common/mixin.js delete mode 100644 yudao-ui-app/common/orderStatus.js delete mode 100644 yudao-ui-app/common/props.js delete mode 100644 yudao-ui-app/components/w-picker/areadata/areadata.js delete mode 100644 yudao-ui-app/components/w-picker/date-picker.vue delete mode 100644 yudao-ui-app/components/w-picker/half-picker.vue delete mode 100644 yudao-ui-app/components/w-picker/linkage-picker.vue delete mode 100644 yudao-ui-app/components/w-picker/range-picker.vue delete mode 100644 yudao-ui-app/components/w-picker/region-picker.vue delete mode 100644 yudao-ui-app/components/w-picker/selector-picker.vue delete mode 100644 yudao-ui-app/components/w-picker/shortterm-picker.vue delete mode 100644 yudao-ui-app/components/w-picker/time-picker.vue delete mode 100644 yudao-ui-app/components/w-picker/w-picker.css delete mode 100644 yudao-ui-app/components/w-picker/w-picker.vue delete mode 100644 yudao-ui-app/components/yd-address-select/yd-address-select.vue delete mode 100644 yudao-ui-app/components/yd-banner/yd-banner.vue delete mode 100644 yudao-ui-app/components/yd-cart-product/yd-cart-product.vue delete mode 100644 yudao-ui-app/components/yd-order-product/yd-order-product.vue delete mode 100644 yudao-ui-app/components/yd-product-box/yd-product-box.vue delete mode 100644 yudao-ui-app/components/yd-product-more/yd-product-more.vue delete mode 100644 yudao-ui-app/components/yd-text-price/yd-text-price.vue delete mode 100644 yudao-ui-app/index.html delete mode 100644 yudao-ui-app/main.js delete mode 100644 yudao-ui-app/manifest.json delete mode 100644 yudao-ui-app/pages.json delete mode 100644 yudao-ui-app/pages/address/create.vue delete mode 100644 yudao-ui-app/pages/address/list.vue delete mode 100644 yudao-ui-app/pages/address/update.vue delete mode 100644 yudao-ui-app/pages/cart/cart.vue delete mode 100644 yudao-ui-app/pages/category/category.vue delete mode 100644 yudao-ui-app/pages/category/product-list.vue delete mode 100644 yudao-ui-app/pages/checkout/checkout.vue delete mode 100644 yudao-ui-app/pages/forgot/forgot.vue delete mode 100644 yudao-ui-app/pages/index/index.vue delete mode 100644 yudao-ui-app/pages/login/mobile.vue delete mode 100644 yudao-ui-app/pages/login/social.vue delete mode 100644 yudao-ui-app/pages/order/confirm.vue delete mode 100644 yudao-ui-app/pages/order/detail.vue delete mode 100644 yudao-ui-app/pages/order/list.vue delete mode 100644 yudao-ui-app/pages/product/product.vue delete mode 100644 yudao-ui-app/pages/profile/profile.vue delete mode 100644 yudao-ui-app/pages/search/search.vue delete mode 100644 yudao-ui-app/pages/setting/setting.vue delete mode 100644 yudao-ui-app/pages/user/user.vue delete mode 100644 yudao-ui-app/sitemap.json delete mode 100644 yudao-ui-app/static/images/empty/address.png delete mode 100644 yudao-ui-app/static/images/empty/cart.png delete mode 100644 yudao-ui-app/static/images/empty/comment.png delete mode 100644 yudao-ui-app/static/images/empty/coupon.png delete mode 100644 yudao-ui-app/static/images/empty/data.png delete mode 100644 yudao-ui-app/static/images/empty/favor.png delete mode 100644 yudao-ui-app/static/images/empty/history.png delete mode 100644 yudao-ui-app/static/images/empty/list.png delete mode 100644 yudao-ui-app/static/images/empty/message.png delete mode 100644 yudao-ui-app/static/images/empty/news.png delete mode 100644 yudao-ui-app/static/images/empty/order.png delete mode 100644 yudao-ui-app/static/images/empty/page.png delete mode 100644 yudao-ui-app/static/images/empty/permission.png delete mode 100644 yudao-ui-app/static/images/empty/search.png delete mode 100644 yudao-ui-app/static/images/empty/wifi.png delete mode 100644 yudao-ui-app/static/images/tabbar/cart-active.png delete mode 100644 yudao-ui-app/static/images/tabbar/cart.png delete mode 100644 yudao-ui-app/static/images/tabbar/category-active.png delete mode 100644 yudao-ui-app/static/images/tabbar/category.png delete mode 100644 yudao-ui-app/static/images/tabbar/index-active.png delete mode 100644 yudao-ui-app/static/images/tabbar/index.png delete mode 100644 yudao-ui-app/static/images/tabbar/user-active.png delete mode 100644 yudao-ui-app/static/images/tabbar/user.png delete mode 100644 yudao-ui-app/store/getters.js delete mode 100644 yudao-ui-app/store/index.js delete mode 100644 yudao-ui-app/store/mudules/cart.js delete mode 100644 yudao-ui-app/store/mudules/user.js delete mode 100644 yudao-ui-app/styles/base.scss delete mode 100644 yudao-ui-app/uni.scss delete mode 100644 yudao-ui-app/uni_modules/uview-ui/LICENSE delete mode 100644 yudao-ui-app/uni_modules/uview-ui/README.md delete mode 100644 yudao-ui-app/uni_modules/uview-ui/changelog.md delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u--form/u--form.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u--image/u--image.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u--input/u--input.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u--text/u--text.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u--textarea/u--textarea.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-action-sheet/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-action-sheet/u-action-sheet.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-album/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-album/u-album.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-alert/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-alert/u-alert.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-avatar-group/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-avatar-group/u-avatar-group.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-avatar/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-avatar/u-avatar.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-back-top/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-back-top/u-back-top.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-badge/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-badge/u-badge.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-button/nvue.scss delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-button/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-button/u-button.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-button/vue.scss delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-calendar/header.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-calendar/month.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-calendar/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-calendar/u-calendar.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-calendar/util.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-car-keyboard/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-car-keyboard/u-car-keyboard.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-cell-group/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-cell-group/u-cell-group.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-cell/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-cell/u-cell.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-checkbox-group/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-checkbox-group/u-checkbox-group.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-checkbox/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-checkbox/u-checkbox.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-circle-progress/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-circle-progress/u-circle-progress.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-code-input/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-code-input/u-code-input.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-code/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-code/u-code.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-col/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-col/u-col.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-collapse-item/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-collapse-item/u-collapse-item.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-collapse/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-collapse/u-collapse.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-column-notice/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-column-notice/u-column-notice.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-count-down/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-count-down/u-count-down.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-count-down/utils.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-count-to/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-count-to/u-count-to.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-datetime-picker/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-datetime-picker/u-datetime-picker.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-divider/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-divider/u-divider.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-dropdown-item/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-dropdown-item/u-dropdown-item.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-dropdown/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-dropdown/u-dropdown.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-empty/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-empty/u-empty.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-form-item/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-form-item/u-form-item.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-form/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-form/u-form.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-gap/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-gap/u-gap.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-grid-item/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-grid-item/u-grid-item.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-grid/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-grid/u-grid.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-icon/icons.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-icon/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-icon/u-icon.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-image/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-image/u-image.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-index-anchor/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-index-anchor/u-index-anchor.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-index-item/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-index-item/u-index-item.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-index-list/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-index-list/u-index-list.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-input/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-input/u-input.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-keyboard/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-keyboard/u-keyboard.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-line-progress/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-line-progress/u-line-progress.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-line/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-line/u-line.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-link/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-link/u-link.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-list-item/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-list-item/u-list-item.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-list/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-list/u-list.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-loading-icon/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-loading-icon/u-loading-icon.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-loading-page/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-loading-page/u-loading-page.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-loadmore/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-loadmore/u-loadmore.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-modal/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-modal/u-modal.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-navbar/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-navbar/u-navbar.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-no-network/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-no-network/u-no-network.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-notice-bar/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-notice-bar/u-notice-bar.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-notify/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-notify/u-notify.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-number-box/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-number-box/u-number-box.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-number-keyboard/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-number-keyboard/u-number-keyboard.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-overlay/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-overlay/u-overlay.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-parse/node/node.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-parse/parser.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-parse/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-parse/u-parse.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-picker-column/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-picker-column/u-picker-column.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-picker/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-picker/u-picker.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-popup/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-popup/u-popup.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-radio-group/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-radio-group/u-radio-group.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-radio/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-radio/u-radio.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-rate/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-rate/u-rate.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-read-more/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-read-more/u-read-more.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-row-notice/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-row-notice/u-row-notice.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-row/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-row/u-row.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-safe-bottom/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-safe-bottom/u-safe-bottom.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-scroll-list/nvue.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-scroll-list/other.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-scroll-list/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-scroll-list/scrollWxs.wxs delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-scroll-list/u-scroll-list.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-search/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-search/u-search.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-skeleton/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-skeleton/u-skeleton.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-slider/mpother.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-slider/mpwxs.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-slider/mpwxs.wxs delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-slider/nvue - 副本.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-slider/nvue.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-slider/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-slider/u-slider.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-status-bar/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-status-bar/u-status-bar.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-steps-item/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-steps-item/u-steps-item.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-steps/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-steps/u-steps.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-sticky/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-sticky/u-sticky.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-subsection/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-subsection/u-subsection.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-swipe-action-item/index - backup.wxs delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-swipe-action-item/index.wxs delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-swipe-action-item/nvue - backup.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-swipe-action-item/nvue.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-swipe-action-item/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-swipe-action-item/u-swipe-action-item.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-swipe-action-item/wxs.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-swipe-action/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-swipe-action/u-swipe-action.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-swiper-indicator/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-swiper-indicator/u-swiper-indicator.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-swiper/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-swiper/u-swiper.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-switch/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-switch/u-switch.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-tabbar-item/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-tabbar-item/u-tabbar-item.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-tabbar/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-tabbar/u-tabbar.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-table/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-table/u-table.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-tabs-item/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-tabs-item/u-tabs-item.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-tabs/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-tabs/u-tabs.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-tag/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-tag/u-tag.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-td/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-td/u-td.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-text/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-text/u-text.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-text/value.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-textarea/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-textarea/u-textarea.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-toast/u-toast.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-toolbar/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-toolbar/u-toolbar.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-tooltip/clipboard.min.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-tooltip/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-tooltip/u-tooltip.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-tr/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-tr/u-tr.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-transition/nvue.ani-map.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-transition/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-transition/transition.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-transition/u-transition.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-transition/vue.ani-style.scss delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-upload/mixin.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-upload/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-upload/u-upload.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/u-upload/utils.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/components/uview-ui/uview-ui.vue delete mode 100644 yudao-ui-app/uni_modules/uview-ui/index.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/index.scss delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/color.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/config.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/actionSheet.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/album.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/alert.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/avatar.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/avatarGroup.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/backtop.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/badge.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/button.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/calendar.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/carKeyboard.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/cell.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/cellGroup.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/checkbox.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/checkboxGroup.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/circleProgress.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/code.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/codeInput.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/col.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/collapse.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/collapseItem.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/columnNotice.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/countDown.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/countTo.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/datetimePicker.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/divider.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/empty.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/form.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/formItem.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/gap.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/grid.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/gridItem.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/icon.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/image.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/indexAnchor.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/indexList.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/input.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/keyboard.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/line.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/lineProgress.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/link.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/list.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/listItem.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/loadingIcon.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/loadingPage.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/loadmore.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/modal.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/navbar.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/noNetwork.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/noticeBar.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/notify.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/numberBox.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/numberKeyboard.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/overlay.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/parse.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/picker.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/popup.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/radio.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/radioGroup.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/rate.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/readMore.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/row.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/rowNotice.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/scrollList.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/search.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/section.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/skeleton.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/slider.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/statusBar.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/steps.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/stepsItem.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/sticky.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/subsection.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/swipeAction.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/swipeActionItem.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/swiper.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/swipterIndicator.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/switch.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/tabbar.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/tabbarItem.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/tabs.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/tag.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/text.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/textarea.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/toast.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/toolbar.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/tooltip.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/transition.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/props/upload.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/config/zIndex.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/css/color.scss delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/css/common.scss delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/css/components.scss delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/css/flex.scss delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/css/h5.scss delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/css/mixin.scss delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/css/mp.scss delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/css/nvue.scss delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/css/vue.scss delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/function/colorGradient.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/function/debounce.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/function/digit.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/function/index.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/function/platform.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/function/test.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/function/throttle.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/luch-request/adapters/index.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/luch-request/core/InterceptorManager.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/luch-request/core/Request.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/luch-request/core/buildFullPath.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/luch-request/core/defaults.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/luch-request/core/dispatchRequest.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/luch-request/core/mergeConfig.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/luch-request/core/settle.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/luch-request/helpers/buildURL.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/luch-request/helpers/combineURLs.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/luch-request/helpers/isAbsoluteURL.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/luch-request/index.d.ts delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/luch-request/index.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/luch-request/utils.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/luch-request/utils/clone.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/mixin/button.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/mixin/mixin.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/mixin/mpMixin.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/mixin/mpShare.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/mixin/openType.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/mixin/style.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/mixin/touch.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/util/async-validator.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/util/calendar.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/util/dayjs.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/util/emitter.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/libs/util/route.js delete mode 100644 yudao-ui-app/uni_modules/uview-ui/package.json delete mode 100644 yudao-ui-app/uni_modules/uview-ui/theme.scss delete mode 100644 yudao-ui-app/utils/request/errorCode.js delete mode 100644 yudao-ui-app/utils/request/index.js delete mode 100644 yudao-ui-app/utils/request/requestInterceptors.js delete mode 100644 yudao-ui-app/utils/request/responseInterceptors.js delete mode 100644 yudao-ui-app/utils/tree.js delete mode 100644 yudao-ui-app/vue.config.js diff --git a/README.md b/README.md index f3e810b7a..e998ba990 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ | [yudao-ui-admin](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin) | [![Gitee star](https://gitee.com/zhijiantianya/ruoyi-vue-pro/badge/star.svg?theme=white)](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin) [![GitHub stars](https://img.shields.io/github/stars/YunaiV/ruoyi-vue-pro.svg?style=social&label=Stars)](https://github.com/YunaiV/ruoyi-vue-pro/tree/master/yudao-ui-admin) | 基于 Vue2 + element-ui 实现的管理后台 | | [yudao-ui-admin-uniapp](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin-uniapp) | [![Gitee star](https://gitee.com/zhijiantianya/ruoyi-vue-pro/badge/star.svg?theme=white)](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin-uniapp) [![GitHub stars](https://img.shields.io/github/stars/YunaiV/ruoyi-vue-pro.svg?style=social&label=Stars)](https://github.com/YunaiV/ruoyi-vue-pro/tree/master/yudao-ui-admin-uniapp) | 基于 uni-app + uni-ui 实现的管理后台的小程序 | | [yudao-ui-go-view](https://gitee.com/yudaocode/yudao-ui-go-view) | [![Gitee star](https://gitee.com/yudaocode/yudao-ui-go-view/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-ui-go-view) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-ui-go-view.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-ui-go-view) | 基于 Vue3 + naive-ui 实现的大屏报表 | -| [yudao-ui-app](https://gitee.com/yudaocode/yudao-mall-uniapp) | [![Gitee star](https://gitee.com/yudaocode/yudao-mall-uniapp/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-mall-uniapp) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-mall-uniapp.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-mall-uniapp) | 基于 uni-app 实现的商城小程序 | +| [yudao-mall-uniapp](https://gitee.com/yudaocode/yudao-mall-uniapp) | [![Gitee star](https://gitee.com/yudaocode/yudao-mall-uniapp/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-mall-uniapp) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-mall-uniapp.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-mall-uniapp) | 基于 uni-app 实现的商城小程序 | ## 🐰 分支说明 diff --git a/yudao-ui-app/.editorconfig b/yudao-ui-app/.editorconfig deleted file mode 100644 index 7034f9bf3..000000000 --- a/yudao-ui-app/.editorconfig +++ /dev/null @@ -1,22 +0,0 @@ -# 告诉EditorConfig插件,这是根文件,不用继续往上查找 -root = true - -# 匹配全部文件 -[*] -# 设置字符集 -charset = utf-8 -# 缩进风格,可选space、tab -indent_style = space -# 缩进的空格数 -indent_size = 2 -# 结尾换行符,可选lf、cr、crlf -end_of_line = lf -# 在文件结尾插入新行 -insert_final_newline = true -# 删除一行中的前后空格 -trim_trailing_whitespace = true - -# 匹配md结尾的文件 -[*.md] -insert_final_newline = false -trim_trailing_whitespace = false diff --git a/yudao-ui-app/.gitignore b/yudao-ui-app/.gitignore deleted file mode 100644 index 5823d4712..000000000 --- a/yudao-ui-app/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -/unpackage/dist/* -/unpackage/cache/* -/unpackage/release/* -/node_modules/* -/.idea/* -/.hbuilderx/ -/.vscode/ diff --git a/yudao-ui-app/App.vue b/yudao-ui-app/App.vue deleted file mode 100644 index cf633af8a..000000000 --- a/yudao-ui-app/App.vue +++ /dev/null @@ -1,34 +0,0 @@ - - - diff --git a/yudao-ui-app/README.md b/yudao-ui-app/README.md new file mode 100644 index 000000000..0f320c3d5 --- /dev/null +++ b/yudao-ui-app/README.md @@ -0,0 +1 @@ +迁移至 仓库 diff --git a/yudao-ui-app/api/address.js b/yudao-ui-app/api/address.js deleted file mode 100644 index 5bfe9306e..000000000 --- a/yudao-ui-app/api/address.js +++ /dev/null @@ -1,15 +0,0 @@ -//请求工具参考https://ext.dcloud.net.cn/plugin?id=392 -const { http } = uni.$u - -//获得用户收件地址列表 -export const getAddressList = params => http.get('/member/address/list', params) -//创建用户收件地址 -export const createAddress = data => http.post('/member/address/create', data) -//通过ID获得用户收件地址 -export const getAddressById = params => http.get('/member/address/get', { params }) -//获得默认的用户收件地址 -export const getDefaultUserAddress = params => http.get('/member/address/get-default', { params }) -//更新用户收件地址 -export const updateAddress = params => http.put('/member/address/update', params) -//删除用户收件地址 -export const deleteAddress = params => http.delete('/member/address/delete', {}, { params }) diff --git a/yudao-ui-app/api/auth.js b/yudao-ui-app/api/auth.js deleted file mode 100644 index a2b04e8e7..000000000 --- a/yudao-ui-app/api/auth.js +++ /dev/null @@ -1,15 +0,0 @@ -//请求工具参考https://ext.dcloud.net.cn/plugin?id=392 -const { http } = uni.$u - -//使用手机 + 密码登录 -export const passwordLogin = data => http.post('/member/auth/login', data) -//发送手机验证码 -export const sendSmsCode = data => http.post('/member/auth/send-sms-code', data) -//使用手机 + 验证码登录 -export const smsLogin = data => http.post('/member/auth/sms-login', data) -//微信小程序的一键登录 -export const weixinMiniAppLogin = data => http.post('/member/auth/weixin-mini-app-login', data) -//刷新令牌 -export const refreshToken = data => http.post('/member/auth/refresh-token', {data}) -//退出登录 -export const logout = data => http.post('/member/auth/logout', data) diff --git a/yudao-ui-app/api/cart.js b/yudao-ui-app/api/cart.js deleted file mode 100644 index c7d0a0091..000000000 --- a/yudao-ui-app/api/cart.js +++ /dev/null @@ -1,5 +0,0 @@ -const { http } = uni.$u - -//获取购物车数据 -export const getCartProductDetail = () => http.get('/trade/cart/get-detail') - diff --git a/yudao-ui-app/api/category.js b/yudao-ui-app/api/category.js deleted file mode 100644 index 630efd29d..000000000 --- a/yudao-ui-app/api/category.js +++ /dev/null @@ -1,5 +0,0 @@ -//请求工具参考https://ext.dcloud.net.cn/plugin?id=392 -const { http } = uni.$u - -// 查询分类列表 -export const categoryListData = params => http.get('product/category/list', { params }) diff --git a/yudao-ui-app/api/index.js b/yudao-ui-app/api/index.js deleted file mode 100644 index 17d01638e..000000000 --- a/yudao-ui-app/api/index.js +++ /dev/null @@ -1,7 +0,0 @@ -//请求工具参考https://ext.dcloud.net.cn/plugin?id=392 -const { http } = uni.$u - -// 获取滚动图数据 -export const getBannerData = params => http.get('/index', { params }) -// 获取滚动通知数据 -export const getNoticeData = params => http.get('/notice', { params }) diff --git a/yudao-ui-app/api/order.js b/yudao-ui-app/api/order.js deleted file mode 100644 index cc305f15c..000000000 --- a/yudao-ui-app/api/order.js +++ /dev/null @@ -1,6 +0,0 @@ -const { http } = uni.$u - -// 获得订单交易分页 -export const getOrderPage = params => http.get('/trade/order/page', { params }) -// 获得交易订单详情 -export const getOrderDetail = params => http.get('/trade/order/get-detail', { params }) diff --git a/yudao-ui-app/api/product.js b/yudao-ui-app/api/product.js deleted file mode 100644 index 627013c46..000000000 --- a/yudao-ui-app/api/product.js +++ /dev/null @@ -1,8 +0,0 @@ -//请求工具参考https://ext.dcloud.net.cn/plugin?id=392 -const { http } = uni.$u - -// 查询商品spu列表 -export const productSpuPage = params => http.get('product/spu/page', { params }) - -// 查询商品 -export const getSpuDetail = id => http.get('product/spu/get-detail?id=' + id, { }) diff --git a/yudao-ui-app/api/user.js b/yudao-ui-app/api/user.js deleted file mode 100644 index d6023e243..000000000 --- a/yudao-ui-app/api/user.js +++ /dev/null @@ -1,14 +0,0 @@ -//请求工具参考https://ext.dcloud.net.cn/plugin?id=392 -const { http } = uni.$u - -//获取用户信息 -export const getUserInfo = params => http.get('/member/user/get', params) -//修改用户头像 -export const updateAvatar = filePath => - http.upload('/member/user/update-avatar', { - name: 'avatarFile', - fileType: 'image', - filePath: filePath - }) -//修改用户昵称 -export const updateNickname = params => http.put('/member/user/update-nickname', {}, { params }) diff --git a/yudao-ui-app/app.scss b/yudao-ui-app/app.scss deleted file mode 100644 index 4cff87ce8..000000000 --- a/yudao-ui-app/app.scss +++ /dev/null @@ -1,8 +0,0 @@ -/* 页面公共scss */ -.container { - background-color: $custom-bg-color; - margin: 0; - padding: 0; - box-sizing: border-box; - height: 100%; -} diff --git a/yudao-ui-app/common/config.js b/yudao-ui-app/common/config.js deleted file mode 100644 index 66cf4a94e..000000000 --- a/yudao-ui-app/common/config.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { - //后端接口地址 - baseUrl: 'http://127.0.0.1:48080/app-api', - // baseUrl: 'http://api-dashboard.yudao.iocoder.cn/app-api', - // 超时 - timeout: 30000, - // 禁用 Cookie 等信息 - withCredentials: false, - header: { - //租户ID - 'tenant-id': 1 - } -} diff --git a/yudao-ui-app/common/mixin.js b/yudao-ui-app/common/mixin.js deleted file mode 100644 index f124374df..000000000 --- a/yudao-ui-app/common/mixin.js +++ /dev/null @@ -1,5 +0,0 @@ -export default { - data() { - return {} - } -} diff --git a/yudao-ui-app/common/orderStatus.js b/yudao-ui-app/common/orderStatus.js deleted file mode 100644 index 475d4cfb0..000000000 --- a/yudao-ui-app/common/orderStatus.js +++ /dev/null @@ -1,7 +0,0 @@ -export default { - '0': { name: '待付款', icon: 'red-packet'}, - '10': { name: '待发货', icon: 'car'}, - '20': { name: '待收货', icon: 'order'}, - '30': { name: '已完成', icon: 'integral'}, - '40': { name: '已取消', icon: 'close-circle'} -} diff --git a/yudao-ui-app/common/props.js b/yudao-ui-app/common/props.js deleted file mode 100644 index 935e6a54b..000000000 --- a/yudao-ui-app/common/props.js +++ /dev/null @@ -1,3 +0,0 @@ -/* uView组件全局属性 */ -uni.$u.props.gap.bgColor = '#ffffff' -uni.$u.props.gap.height = '10' diff --git a/yudao-ui-app/components/w-picker/areadata/areadata.js b/yudao-ui-app/components/w-picker/areadata/areadata.js deleted file mode 100644 index b07228cb1..000000000 --- a/yudao-ui-app/components/w-picker/areadata/areadata.js +++ /dev/null @@ -1 +0,0 @@ -const cityData=[{value:'110000',label:'北京市',children:[{value:"110100",label:"北京市",children:[{value:"110101",label:"东城区"},{value:"110102",label:"西城区"},{value:"110105",label:"朝阳区"},{value:"110106",label:"丰台区"},{value:"110107",label:"石景山区"},{value:"110108",label:"海淀区"},{value:"110109",label:"门头沟区"},{value:"110111",label:"房山区"},{value:"110112",label:"通州区"},{value:"110113",label:"顺义区"},{value:"110114",label:"昌平区"},{value:"110115",label:"大兴区"},{value:"110116",label:"怀柔区"},{value:"110117",label:"平谷区"},{value:"110118",label:"密云区"},{value:"110119",label:"延庆区"}]}]},{value:'120000',label:'天津市',children:[{value:"120100",label:"天津市",children:[{value:"120101",label:"和平区"},{value:"120102",label:"河东区"},{value:"120103",label:"河西区"},{value:"120104",label:"南开区"},{value:"120105",label:"河北区"},{value:"120106",label:"红桥区"},{value:"120110",label:"东丽区"},{value:"120111",label:"西青区"},{value:"120112",label:"津南区"},{value:"120113",label:"北辰区"},{value:"120114",label:"武清区"},{value:"120115",label:"宝坻区"},{value:"120116",label:"滨海新区"},{value:"120117",label:"宁河区"},{value:"120118",label:"静海区"},{value:"120119",label:"蓟州区"}]}]},{value:'130000',label:'河北省',children:[{value:"130100",label:"石家庄市",children:[{value:"130102",label:"长安区"},{value:"130104",label:"桥西区"},{value:"130105",label:"新华区"},{value:"130107",label:"井陉矿区"},{value:"130108",label:"裕华区"},{value:"130109",label:"藁城区"},{value:"130110",label:"鹿泉区"},{value:"130111",label:"栾城区"},{value:"130121",label:"井陉县"},{value:"130123",label:"正定县"},{value:"130125",label:"行唐县"},{value:"130126",label:"灵寿县"},{value:"130127",label:"高邑县"},{value:"130128",label:"深泽县"},{value:"130129",label:"赞皇县"},{value:"130130",label:"无极县"},{value:"130131",label:"平山县"},{value:"130132",label:"元氏县"},{value:"130133",label:"赵县"},{value:"130181",label:"辛集市"},{value:"130183",label:"晋州市"},{value:"130184",label:"新乐市"},{value:"130172",label:"石家庄循环化工园区"},{value:"130171",label:"石家庄高新技术产业开发区"}]},{value:"130200",label:"唐山市",children:[{value:"130202",label:"路南区"},{value:"130203",label:"路北区"},{value:"130204",label:"古冶区"},{value:"130205",label:"开平区"},{value:"130207",label:"丰南区"},{value:"130208",label:"丰润区"},{value:"130209",label:"曹妃甸区"},{value:"130223",label:"滦县"},{value:"130224",label:"滦南县"},{value:"130225",label:"乐亭县"},{value:"130227",label:"迁西县"},{value:"130229",label:"玉田县"},{value:"130281",label:"遵化市"},{value:"130283",label:"迁安市"},{value:"130271",label:"唐山市芦台经济技术开发区"},{value:"130272",label:"唐山市汉沽管理区"},{value:"130273",label:"唐山高新技术产业开发区"},{value:"130274",label:"河北唐山海港经济开发区"}]},{value:"130300",label:"秦皇岛市",children:[{value:"130302",label:"海港区"},{value:"130303",label:"山海关区"},{value:"130304",label:"北戴河区"},{value:"130321",label:"青龙满族自治县"},{value:"130322",label:"昌黎县"},{value:"130306",label:"抚宁区"},{value:"130324",label:"卢龙县"},{value:"130371",label:"秦皇岛市经济技术开发区"},{value:"130372",label:"北戴河新区"}]},{value:"130400",label:"邯郸市",children:[{value:"130402",label:"邯山区"},{value:"130403",label:"丛台区"},{value:"130404",label:"复兴区"},{value:"130406",label:"峰峰矿区"},{value:"130421",label:"邯郸县"},{value:"130423",label:"临漳县"},{value:"130424",label:"成安县"},{value:"130425",label:"大名县"},{value:"130426",label:"涉县"},{value:"130427",label:"磁县"},{value:"130407",label:"肥乡区"},{value:"130408",label:"永年区"},{value:"130430",label:"邱县"},{value:"130431",label:"鸡泽县"},{value:"130432",label:"广平县"},{value:"130433",label:"馆陶县"},{value:"130434",label:"魏县"},{value:"130435",label:"曲周县"},{value:"130481",label:"武安市"},{value:"130471",label:"邯郸经济技术开发区"},{value:"130473",label:"邯郸冀南新区"}]},{value:"130500",label:"邢台市",children:[{value:"130502",label:"桥东区"},{value:"130503",label:"桥西区"},{value:"130521",label:"邢台县"},{value:"130522",label:"临城县"},{value:"130523",label:"内丘县"},{value:"130524",label:"柏乡县"},{value:"130525",label:"隆尧县"},{value:"130526",label:"任县"},{value:"130527",label:"南和县"},{value:"130528",label:"宁晋县"},{value:"130529",label:"巨鹿县"},{value:"130530",label:"新河县"},{value:"130531",label:"广宗县"},{value:"130532",label:"平乡县"},{value:"130533",label:"威县"},{value:"130534",label:"清河县"},{value:"130535",label:"临西县"},{value:"130581",label:"南宫市"},{value:"130582",label:"沙河市"},{value:"130571",label:"河北邢台经济开发区"}]},{value:"130600",label:"保定市",children:[{value:"130602",label:"竞秀区"},{value:"130606",label:"莲池区"},{value:"130607",label:"满城区"},{value:"130608",label:"清苑区"},{value:"130623",label:"涞水县"},{value:"130624",label:"阜平县"},{value:"130609",label:"徐水区"},{value:"130626",label:"定兴县"},{value:"130627",label:"唐县"},{value:"130628",label:"高阳县"},{value:"130629",label:"容城县"},{value:"130630",label:"涞源县"},{value:"130631",label:"望都县"},{value:"130632",label:"安新县"},{value:"130633",label:"易县"},{value:"130634",label:"曲阳县"},{value:"130635",label:"蠡县"},{value:"130636",label:"顺平县"},{value:"130637",label:"博野县"},{value:"130638",label:"雄县"},{value:"130681",label:"涿州市"},{value:"130682",label:"定州市"},{value:"130683",label:"安国市"},{value:"130684",label:"高碑店市"},{value:"130671",label:"保定高新技术产业开发区"},{value:"130672",label:"保定白沟新城"}]},{value:"130700",label:"张家口市",children:[{value:"130702",label:"桥东区"},{value:"130703",label:"桥西区"},{value:"130705",label:"宣化区"},{value:"130706",label:"下花园区"},{value:"130708",label:"万全区"},{value:"130709",label:"崇礼区"},{value:"130722",label:"张北县"},{value:"130723",label:"康保县"},{value:"130724",label:"沽源县"},{value:"130725",label:"尚义县"},{value:"130726",label:"蔚县"},{value:"130727",label:"阳原县"},{value:"130728",label:"怀安县"},{value:"130730",label:"怀来县"},{value:"130731",label:"涿鹿县"},{value:"130732",label:"赤城县"},{value:"130733",label:"崇礼县"},{value:"130771",label:"张家口市高新技术产业开发区"},{value:"130772",label:"张家口市察北管理区"},{value:"130773",label:"张家口市塞北管理区"}]},{value:"130800",label:"承德市",children:[{value:"130802",label:"双桥区"},{value:"130803",label:"双滦区"},{value:"130804",label:"鹰手营子矿区"},{value:"130821",label:"承德县"},{value:"130822",label:"兴隆县"},{value:"130881",label:"平泉市"},{value:"130824",label:"滦平县"},{value:"130825",label:"隆化县"},{value:"130826",label:"丰宁满族自治县"},{value:"130827",label:"宽城满族自治县"},{value:"130828",label:"围场满族蒙古族自治县"},{value:"130871",label:"承德高新技术产业开发区"}]},{value:"130900",label:"沧州市",children:[{value:"130902",label:"新华区"},{value:"130903",label:"运河区"},{value:"130921",label:"沧县"},{value:"130922",label:"青县"},{value:"130923",label:"东光县"},{value:"130924",label:"海兴县"},{value:"130925",label:"盐山县"},{value:"130926",label:"肃宁县"},{value:"130927",label:"南皮县"},{value:"130928",label:"吴桥县"},{value:"130929",label:"献县"},{value:"130930",label:"孟村回族自治县"},{value:"130981",label:"泊头市"},{value:"130982",label:"任丘市"},{value:"130983",label:"黄骅市"},{value:"130984",label:"河间市"},{value:"130971",label:"河北沧州经济开发区"},{value:"130972",label:"沧州高新技术产业开发区"},{value:"130973",label:"沧州渤海新区"}]},{value:"131000",label:"廊坊市",children:[{value:"131002",label:"安次区"},{value:"131003",label:"广阳区"},{value:"131022",label:"固安县"},{value:"131023",label:"永清县"},{value:"131024",label:"香河县"},{value:"131025",label:"大城县"},{value:"131026",label:"文安县"},{value:"131028",label:"大厂回族自治县"},{value:"131071",label:"廊坊经济技术开发区"},{value:"131081",label:"霸州市"},{value:"131082",label:"三河市"}]},{value:"131100",label:"衡水市",children:[{value:"131102",label:"桃城区"},{value:"131121",label:"枣强县"},{value:"131122",label:"武邑县"},{value:"131123",label:"武强县"},{value:"131124",label:"饶阳县"},{value:"131125",label:"安平县"},{value:"131126",label:"故城县"},{value:"131127",label:"景县"},{value:"131128",label:"阜城县"},{value:"131103",label:"冀州区"},{value:"131182",label:"深州市"},{value:"131172",label:"衡水滨湖新区"},{value:"131171",label:"河北衡水经济开发区"}]}]},{value:'140000',label:'山西省',children:[{value:"140100",label:"太原市",children:[{value:"140105",label:"小店区"},{value:"140106",label:"迎泽区"},{value:"140107",label:"杏花岭区"},{value:"140108",label:"尖草坪区"},{value:"140109",label:"万柏林区"},{value:"140110",label:"晋源区"},{value:"140121",label:"清徐县"},{value:"140122",label:"阳曲县"},{value:"140123",label:"娄烦县"},{value:"140181",label:"古交市"},{value:"140171",label:"山西转型综合改革示范区"}]},{value:"140200",label:"大同市",children:[{value:"140202",label:"城区"},{value:"140203",label:"矿区"},{value:"140211",label:"南郊区"},{value:"140212",label:"新荣区"},{value:"140221",label:"阳高县"},{value:"140222",label:"天镇县"},{value:"140223",label:"广灵县"},{value:"140224",label:"灵丘县"},{value:"140225",label:"浑源县"},{value:"140226",label:"左云县"},{value:"140227",label:"大同县"},{value:"140271",label:"山西大同经济开发区"}]},{value:"140300",label:"阳泉市",children:[{value:"140302",label:"城区"},{value:"140303",label:"矿区"},{value:"140311",label:"郊区"},{value:"140321",label:"平定县"},{value:"140322",label:"盂县"},{value:"140371",label:"山西阳泉经济开发区"}]},{value:"140400",label:"长治市",children:[{value:"140421",label:"长治县"},{value:"140423",label:"襄垣县"},{value:"140424",label:"屯留县"},{value:"140425",label:"平顺县"},{value:"140426",label:"黎城县"},{value:"140427",label:"壶关县"},{value:"140428",label:"长子县"},{value:"140429",label:"武乡县"},{value:"140430",label:"沁县"},{value:"140431",label:"沁源县"},{value:"140481",label:"潞城市"},{value:"140402",label:"城区"},{value:"140411",label:"郊区"},{value:"140471",label:"山西长治高新技术产业园区"}]},{value:"140500",label:"晋城市",children:[{value:"140502",label:"城区"},{value:"140521",label:"沁水县"},{value:"140522",label:"阳城县"},{value:"140524",label:"陵川县"},{value:"140525",label:"泽州县"},{value:"140581",label:"高平市"}]},{value:"140600",label:"朔州市",children:[{value:"140602",label:"朔城区"},{value:"140603",label:"平鲁区"},{value:"140621",label:"山阴县"},{value:"140622",label:"应县"},{value:"140623",label:"右玉县"},{value:"140624",label:"怀仁县"},{value:"140671",label:"山西朔州经济开发区"}]},{value:"140700",label:"晋中市",children:[{value:"140702",label:"榆次区"},{value:"140721",label:"榆社县"},{value:"140722",label:"左权县"},{value:"140723",label:"和顺县"},{value:"140724",label:"昔阳县"},{value:"140725",label:"寿阳县"},{value:"140726",label:"太谷县"},{value:"140727",label:"祁县"},{value:"140728",label:"平遥县"},{value:"140729",label:"灵石县"},{value:"140781",label:"介休市"}]},{value:"140800",label:"运城市",children:[{value:"140802",label:"盐湖区"},{value:"140821",label:"临猗县"},{value:"140822",label:"万荣县"},{value:"140823",label:"闻喜县"},{value:"140824",label:"稷山县"},{value:"140825",label:"新绛县"},{value:"140826",label:"绛县"},{value:"140827",label:"垣曲县"},{value:"140828",label:"夏县"},{value:"140829",label:"平陆县"},{value:"140830",label:"芮城县"},{value:"140881",label:"永济市"},{value:"140882",label:"河津市"}]},{value:"140900",label:"忻州市",children:[{value:"140902",label:"忻府区"},{value:"140921",label:"定襄县"},{value:"140922",label:"五台县"},{value:"140923",label:"代县"},{value:"140924",label:"繁峙县"},{value:"140925",label:"宁武县"},{value:"140926",label:"静乐县"},{value:"140927",label:"神池县"},{value:"140928",label:"五寨县"},{value:"140929",label:"岢岚县"},{value:"140930",label:"河曲县"},{value:"140931",label:"保德县"},{value:"140932",label:"偏关县"},{value:"140981",label:"原平市"},{value:"140971",label:"五台山风景名胜区"}]},{value:"141000",label:"临汾市",children:[{value:"141002",label:"尧都区"},{value:"141021",label:"曲沃县"},{value:"141022",label:"翼城县"},{value:"141023",label:"襄汾县"},{value:"141024",label:"洪洞县"},{value:"141025",label:"古县"},{value:"141026",label:"安泽县"},{value:"141027",label:"浮山县"},{value:"141028",label:"吉县"},{value:"141029",label:"乡宁县"},{value:"141030",label:"大宁县"},{value:"141031",label:"隰县"},{value:"141032",label:"永和县"},{value:"141033",label:"蒲县"},{value:"141034",label:"汾西县"},{value:"141081",label:"侯马市"},{value:"141082",label:"霍州市"}]},{value:"141100",label:"吕梁市",children:[{value:"141102",label:"离石区"},{value:"141121",label:"文水县"},{value:"141122",label:"交城县"},{value:"141123",label:"兴县"},{value:"141124",label:"临县"},{value:"141125",label:"柳林县"},{value:"141126",label:"石楼县"},{value:"141127",label:"岚县"},{value:"141128",label:"方山县"},{value:"141129",label:"中阳县"},{value:"141130",label:"交口县"},{value:"141181",label:"孝义市"},{value:"141182",label:"汾阳市"}]}]},{value:'150000',label:'内蒙古',children:[{value:"150100",label:"呼和浩特市",children:[{value:"150102",label:"新城区"},{value:"150103",label:"回民区"},{value:"150104",label:"玉泉区"},{value:"150105",label:"赛罕区"},{value:"150121",label:"土默特左旗"},{value:"150122",label:"托克托县"},{value:"150123",label:"和林格尔县"},{value:"150124",label:"清水河县"},{value:"150125",label:"武川县"},{value:"150171",label:"呼和浩特金海工业园区"},{value:"150172",label:"呼和浩特经济技术开发区"}]},{value:"150200",label:"包头市",children:[{value:"150202",label:"东河区"},{value:"150203",label:"昆都仑区"},{value:"150204",label:"青山区"},{value:"150205",label:"石拐区"},{value:"150206",label:"白云矿区"},{value:"150207",label:"九原区"},{value:"150221",label:"土默特右旗"},{value:"150222",label:"固阳县"},{value:"150223",label:"达尔罕茂明安联合旗"},{value:"150271",label:"包头稀土高新技术产业开发区"}]},{value:"150300",label:"乌海市",children:[{value:"150302",label:"海勃湾区"},{value:"150303",label:"海南区"},{value:"150304",label:"乌达区"}]},{value:"150400",label:"赤峰市",children:[{value:"150402",label:"红山区"},{value:"150403",label:"元宝山区"},{value:"150404",label:"松山区"},{value:"150421",label:"阿鲁科尔沁旗"},{value:"150422",label:"巴林左旗"},{value:"150423",label:"巴林右旗"},{value:"150424",label:"林西县"},{value:"150425",label:"克什克腾旗"},{value:"150426",label:"翁牛特旗"},{value:"150428",label:"喀喇沁旗"},{value:"150429",label:"宁城县"},{value:"150430",label:"敖汉旗"}]},{value:"150500",label:"通辽市",children:[{value:"150502",label:"科尔沁区"},{value:"150521",label:"科尔沁左翼中旗"},{value:"150522",label:"科尔沁左翼后旗"},{value:"150523",label:"开鲁县"},{value:"150524",label:"库伦旗"},{value:"150525",label:"奈曼旗"},{value:"150526",label:"扎鲁特旗"},{value:"150581",label:"霍林郭勒市"},{value:"150571",label:"通辽经济技术开发区"}]},{value:"150600",label:"鄂尔多斯市",children:[{value:"150602",label:"东胜区"},{value:"150621",label:"达拉特旗"},{value:"150622",label:"准格尔旗"},{value:"150623",label:"鄂托克前旗"},{value:"150624",label:"鄂托克旗"},{value:"150625",label:"杭锦旗"},{value:"150626",label:"乌审旗"},{value:"150627",label:"伊金霍洛旗"},{value:"150603",label:"康巴什区"}]},{value:"150700",label:"呼伦贝尔市",children:[{value:"150702",label:"海拉尔区"},{value:"150721",label:"阿荣旗"},{value:"150722",label:"莫力达瓦达斡尔族自治旗"},{value:"150723",label:"鄂伦春自治旗"},{value:"150724",label:"鄂温克族自治旗"},{value:"150725",label:"陈巴尔虎旗"},{value:"150726",label:"新巴尔虎左旗"},{value:"150727",label:"新巴尔虎右旗"},{value:"150781",label:"满洲里市"},{value:"150782",label:"牙克石市"},{value:"150783",label:"扎兰屯市"},{value:"150784",label:"额尔古纳市"},{value:"150785",label:"根河市"},{value:"150703",label:"扎赉诺尔区"}]},{value:"150800",label:"巴彦淖尔市",children:[{value:"150802",label:"临河区"},{value:"150821",label:"五原县"},{value:"150822",label:"磴口县"},{value:"150823",label:"乌拉特前旗"},{value:"150824",label:"乌拉特中旗"},{value:"150825",label:"乌拉特后旗"},{value:"150826",label:"杭锦后旗"}]},{value:"150900",label:"乌兰察布市",children:[{value:"150902",label:"集宁区"},{value:"150921",label:"卓资县"},{value:"150922",label:"化德县"},{value:"150923",label:"商都县"},{value:"150924",label:"兴和县"},{value:"150925",label:"凉城县"},{value:"150926",label:"察哈尔右翼前旗"},{value:"150927",label:"察哈尔右翼中旗"},{value:"150928",label:"察哈尔右翼后旗"},{value:"150929",label:"四子王旗"},{value:"150981",label:"丰镇市"}]},{value:"152200",label:"兴安盟",children:[{value:"152201",label:"乌兰浩特市"},{value:"152202",label:"阿尔山市"},{value:"152221",label:"科尔沁右翼前旗"},{value:"152222",label:"科尔沁右翼中旗"},{value:"152223",label:"扎赉特旗"},{value:"152224",label:"突泉县"}]},{value:"152500",label:"锡林郭勒盟",children:[{value:"152501",label:"二连浩特市"},{value:"152502",label:"锡林浩特市"},{value:"152522",label:"阿巴嘎旗"},{value:"152523",label:"苏尼特左旗"},{value:"152524",label:"苏尼特右旗"},{value:"152525",label:"东乌珠穆沁旗"},{value:"152526",label:"西乌珠穆沁旗"},{value:"152527",label:"太仆寺旗"},{value:"152528",label:"镶黄旗"},{value:"152529",label:"正镶白旗"},{value:"152530",label:"正蓝旗"},{value:"152531",label:"多伦县"},{value:"152571",label:"乌拉盖管委会"}]},{value:"152900",label:"阿拉善盟",children:[{value:"152921",label:"阿拉善左旗"},{value:"152922",label:"阿拉善右旗"},{value:"152923",label:"额济纳旗"},{value:"152971",label:"内蒙古阿拉善经济开发区"}]}]},{value:'210000',label:'辽宁省',children:[{value:"210100",label:"沈阳市",children:[{value:"210102",label:"和平区"},{value:"210103",label:"沈河区"},{value:"210104",label:"大东区"},{value:"210105",label:"皇姑区"},{value:"210106",label:"铁西区"},{value:"210111",label:"苏家屯区"},{value:"210112",label:"东陵区"},{value:"210113",label:"新城子区"},{value:"210114",label:"于洪区"},{value:"210115",label:"辽中区"},{value:"210123",label:"康平县"},{value:"210124",label:"法库县"},{value:"210181",label:"新民市"},{value:"210112",label:"浑南区"},{value:"210113",label:"沈北新区"}]},{value:"210200",label:"大连市",children:[{value:"210202",label:"中山区"},{value:"210203",label:"西岗区"},{value:"210204",label:"沙河口区"},{value:"210211",label:"甘井子区"},{value:"210212",label:"旅顺口区"},{value:"210213",label:"金州区"},{value:"210224",label:"长海县"},{value:"210251",label:"开发区"},{value:"210281",label:"瓦房店市"},{value:"210214",label:"普兰店区"},{value:"210283",label:"庄河市"}]},{value:"210300",label:"鞍山市",children:[{value:"210302",label:"铁东区"},{value:"210303",label:"铁西区"},{value:"210304",label:"立山区"},{value:"210311",label:"千山区"},{value:"210321",label:"台安县"},{value:"210323",label:"岫岩满族自治县"},{value:"210381",label:"海城市"}]},{value:"210400",label:"抚顺市",children:[{value:"210402",label:"新抚区"},{value:"210403",label:"东洲区"},{value:"210404",label:"望花区"},{value:"210411",label:"顺城区"},{value:"210421",label:"抚顺县"},{value:"210422",label:"新宾满族自治县"},{value:"210423",label:"清原满族自治县"}]},{value:"210500",label:"本溪市",children:[{value:"210502",label:"平山区"},{value:"210503",label:"溪湖区"},{value:"210504",label:"明山区"},{value:"210505",label:"南芬区"},{value:"210521",label:"本溪满族自治县"},{value:"210522",label:"桓仁满族自治县"}]},{value:"210600",label:"丹东市",children:[{value:"210602",label:"元宝区"},{value:"210603",label:"振兴区"},{value:"210604",label:"振安区"},{value:"210624",label:"宽甸满族自治县"},{value:"210681",label:"东港市"},{value:"210682",label:"凤城市"}]},{value:"210700",label:"锦州市",children:[{value:"210702",label:"古塔区"},{value:"210703",label:"凌河区"},{value:"210711",label:"太和区"},{value:"210726",label:"黑山县"},{value:"210727",label:"义县"},{value:"210781",label:"凌海市"},{value:"210782",label:"北镇市"}]},{value:"210800",label:"营口市",children:[{value:"210802",label:"站前区"},{value:"210803",label:"西市区"},{value:"210804",label:"鲅鱼圈区"},{value:"210811",label:"老边区"},{value:"210881",label:"盖州市"},{value:"210882",label:"大石桥市"}]},{value:"210900",label:"阜新市",children:[{value:"210902",label:"海州区"},{value:"210903",label:"新邱区"},{value:"210904",label:"太平区"},{value:"210905",label:"清河门区"},{value:"210911",label:"细河区"},{value:"210921",label:"阜新蒙古族自治县"},{value:"210922",label:"彰武县"}]},{value:"211000",label:"辽阳市",children:[{value:"211002",label:"白塔区"},{value:"211003",label:"文圣区"},{value:"211004",label:"宏伟区"},{value:"211005",label:"弓长岭区"},{value:"211011",label:"太子河区"},{value:"211021",label:"辽阳县"},{value:"211081",label:"灯塔市"}]},{value:"211100",label:"盘锦市",children:[{value:"211102",label:"双台子区"},{value:"211103",label:"兴隆台区"},{value:"211121",label:"大洼县"},{value:"211122",label:"盘山县"}]},{value:"211200",label:"铁岭市",children:[{value:"211202",label:"银州区"},{value:"211204",label:"清河区"},{value:"211221",label:"铁岭县"},{value:"211223",label:"西丰县"},{value:"211224",label:"昌图县"},{value:"211281",label:"调兵山市"},{value:"211282",label:"开原市"}]},{value:"211300",label:"朝阳市",children:[{value:"211302",label:"双塔区"},{value:"211303",label:"龙城区"},{value:"211321",label:"朝阳县"},{value:"211322",label:"建平县"},{value:"211324",label:"喀喇沁左翼蒙古族自治县"},{value:"211381",label:"北票市"},{value:"211382",label:"凌源市"}]},{value:"211400",label:"葫芦岛市",children:[{value:"211402",label:"连山区"},{value:"211403",label:"龙港区"},{value:"211404",label:"南票区"},{value:"211421",label:"绥中县"},{value:"211422",label:"建昌县"},{value:"211481",label:"兴城市"}]}]},{value:'220000',label:'吉林省',children:[{value:"220100",label:"长春市",children:[{value:"220102",label:"南关区"},{value:"220103",label:"宽城区"},{value:"220104",label:"朝阳区"},{value:"220105",label:"二道区"},{value:"220106",label:"绿园区"},{value:"220112",label:"双阳区"},{value:"220122",label:"农安县"},{value:"220181",label:"九台市"},{value:"220182",label:"榆树市"},{value:"220183",label:"德惠市"},{value:"220171",label:"长春经济技术开发区"},{value:"220172",label:"长春净月高新技术产业开发区"},{value:"220173",label:"长春高新技术产业开发区"},{value:"220174",label:"长春汽车经济技术开发区"}]},{value:"220200",label:"吉林市",children:[{value:"220202",label:"昌邑区"},{value:"220203",label:"龙潭区"},{value:"220204",label:"船营区"},{value:"220211",label:"丰满区"},{value:"220221",label:"永吉县"},{value:"220281",label:"蛟河市"},{value:"220282",label:"桦甸市"},{value:"220283",label:"舒兰市"},{value:"220284",label:"磐石市"},{value:"220271",label:"吉林经济开发区"},{value:"220272",label:"吉林高新技术产业开发区"},{value:"220273",label:"吉林中国新加坡食品区"}]},{value:"220300",label:"四平市",children:[{value:"220302",label:"铁西区"},{value:"220303",label:"铁东区"},{value:"220322",label:"梨树县"},{value:"220323",label:"伊通满族自治县"},{value:"220381",label:"公主岭市"},{value:"220382",label:"双辽市"}]},{value:"220400",label:"辽源市",children:[{value:"220402",label:"龙山区"},{value:"220403",label:"西安区"},{value:"220421",label:"东丰县"},{value:"220422",label:"东辽县"}]},{value:"220500",label:"通化市",children:[{value:"220502",label:"东昌区"},{value:"220503",label:"二道江区"},{value:"220521",label:"通化县"},{value:"220523",label:"辉南县"},{value:"220524",label:"柳河县"},{value:"220581",label:"梅河口市"},{value:"220582",label:"集安市"}]},{value:"220600",label:"白山市",children:[{value:"220602",label:"八道江区"},{value:"220621",label:"抚松县"},{value:"220622",label:"靖宇县"},{value:"220623",label:"长白朝鲜族自治县"},{value:"220605",label:"江源区"},{value:"220681",label:"临江市"},{value:"220602",label:"浑江区"}]},{value:"220700",label:"松原市",children:[{value:"220702",label:"宁江区"},{value:"220721",label:"前郭尔罗斯蒙古族自治县"},{value:"220722",label:"长岭县"},{value:"220723",label:"乾安县"},{value:"220781",label:"扶余市"},{value:"220771",label:"吉林松原经济开发区"}]},{value:"220800",label:"白城市",children:[{value:"220802",label:"洮北区"},{value:"220821",label:"镇赉县"},{value:"220822",label:"通榆县"},{value:"220881",label:"洮南市"},{value:"220882",label:"大安市"},{value:"220871",label:"吉林白城经济开发区"}]},{value:"222400",label:"延边朝鲜族自治州",children:[{value:"222401",label:"延吉市"},{value:"222402",label:"图们市"},{value:"222403",label:"敦化市"},{value:"222404",label:"珲春市"},{value:"222405",label:"龙井市"},{value:"222406",label:"和龙市"},{value:"222424",label:"汪清县"},{value:"222426",label:"安图县"}]}]},{value:'230000',label:'黑龙江省',children:[{value:"230100",label:"哈尔滨市",children:[{value:"230102",label:"道里区"},{value:"230103",label:"南岗区"},{value:"230104",label:"道外区"},{value:"230110",label:"香坊区"},{value:"230107",label:"动力区"},{value:"230108",label:"平房区"},{value:"230109",label:"松北区"},{value:"230111",label:"呼兰区"},{value:"230123",label:"依兰县"},{value:"230124",label:"方正县"},{value:"230125",label:"宾县"},{value:"230126",label:"巴彦县"},{value:"230127",label:"木兰县"},{value:"230128",label:"通河县"},{value:"230129",label:"延寿县"},{value:"230112",label:"阿城区"},{value:"230113",label:"双城区"},{value:"230183",label:"尚志市"},{value:"230184",label:"五常市"}]},{value:"230200",label:"齐齐哈尔市",children:[{value:"230202",label:"龙沙区"},{value:"230203",label:"建华区"},{value:"230204",label:"铁锋区"},{value:"230205",label:"昂昂溪区"},{value:"230206",label:"富拉尔基区"},{value:"230207",label:"碾子山区"},{value:"230208",label:"梅里斯达斡尔族区"},{value:"230221",label:"龙江县"},{value:"230223",label:"依安县"},{value:"230224",label:"泰来县"},{value:"230225",label:"甘南县"},{value:"230227",label:"富裕县"},{value:"230229",label:"克山县"},{value:"230230",label:"克东县"},{value:"230231",label:"拜泉县"},{value:"230281",label:"讷河市"}]},{value:"230300",label:"鸡西市",children:[{value:"230302",label:"鸡冠区"},{value:"230303",label:"恒山区"},{value:"230304",label:"滴道区"},{value:"230305",label:"梨树区"},{value:"230306",label:"城子河区"},{value:"230307",label:"麻山区"},{value:"230321",label:"鸡东县"},{value:"230381",label:"虎林市"},{value:"230382",label:"密山市"}]},{value:"230400",label:"鹤岗市",children:[{value:"230402",label:"向阳区"},{value:"230403",label:"工农区"},{value:"230404",label:"南山区"},{value:"230405",label:"兴安区"},{value:"230406",label:"东山区"},{value:"230407",label:"兴山区"},{value:"230421",label:"萝北县"},{value:"230422",label:"绥滨县"}]},{value:"230500",label:"双鸭山市",children:[{value:"230502",label:"尖山区"},{value:"230503",label:"岭东区"},{value:"230505",label:"四方台区"},{value:"230506",label:"宝山区"},{value:"230521",label:"集贤县"},{value:"230522",label:"友谊县"},{value:"230523",label:"宝清县"},{value:"230524",label:"饶河县"}]},{value:"230600",label:"大庆市",children:[{value:"230602",label:"萨尔图区"},{value:"230603",label:"龙凤区"},{value:"230604",label:"让胡路区"},{value:"230605",label:"红岗区"},{value:"230606",label:"大同区"},{value:"230621",label:"肇州县"},{value:"230622",label:"肇源县"},{value:"230623",label:"林甸县"},{value:"230624",label:"杜尔伯特蒙古族自治县"},{value:"230671",label:"大庆高新技术产业开发区"}]},{value:"230700",label:"伊春市",children:[{value:"230702",label:"伊春区"},{value:"230703",label:"南岔区"},{value:"230704",label:"友好区"},{value:"230705",label:"西林区"},{value:"230706",label:"翠峦区"},{value:"230707",label:"新青区"},{value:"230708",label:"美溪区"},{value:"230709",label:"金山屯区"},{value:"230710",label:"五营区"},{value:"230711",label:"乌马河区"},{value:"230712",label:"汤旺河区"},{value:"230713",label:"带岭区"},{value:"230714",label:"乌伊岭区"},{value:"230715",label:"红星区"},{value:"230716",label:"上甘岭区"},{value:"230722",label:"嘉荫县"},{value:"230781",label:"铁力市"}]},{value:"230800",label:"佳木斯市",children:[{value:"230803",label:"向阳区"},{value:"230804",label:"前进区"},{value:"230805",label:"东风区"},{value:"230811",label:"郊区"},{value:"230822",label:"桦南县"},{value:"230826",label:"桦川县"},{value:"230828",label:"汤原县"},{value:"230833",label:"抚远市"},{value:"230881",label:"同江市"},{value:"230882",label:"富锦市"}]},{value:"230900",label:"七台河市",children:[{value:"230902",label:"新兴区"},{value:"230903",label:"桃山区"},{value:"230904",label:"茄子河区"},{value:"230921",label:"勃利县"}]},{value:"231000",label:"牡丹江市",children:[{value:"231002",label:"东安区"},{value:"231003",label:"阳明区"},{value:"231004",label:"爱民区"},{value:"231005",label:"西安区"},{value:"231086",label:"东宁市"},{value:"231025",label:"林口县"},{value:"231081",label:"绥芬河市"},{value:"231083",label:"海林市"},{value:"231084",label:"宁安市"},{value:"231085",label:"穆棱市"},{value:"231071",label:"牡丹江经济技术开发区"}]},{value:"231100",label:"黑河市",children:[{value:"231102",label:"爱辉区"},{value:"231121",label:"嫩江县"},{value:"231123",label:"逊克县"},{value:"231124",label:"孙吴县"},{value:"231181",label:"北安市"},{value:"231182",label:"五大连池市"}]},{value:"231200",label:"绥化市",children:[{value:"231202",label:"北林区"},{value:"231221",label:"望奎县"},{value:"231222",label:"兰西县"},{value:"231223",label:"青冈县"},{value:"231224",label:"庆安县"},{value:"231225",label:"明水县"},{value:"231226",label:"绥棱县"},{value:"231281",label:"安达市"},{value:"231282",label:"肇东市"},{value:"231283",label:"海伦市"}]},{value:"232700",label:"大兴安岭地区",children:[{value:"232721",label:"呼玛县"},{value:"232722",label:"塔河县"},{value:"232723",label:"漠河县"},{value:"232701",label:"加格达奇区"},{value:"232704",label:"呼中区"},{value:"232703",label:"新林区"}]}]},{value:'310000',label:'上海市',children:[{value:'310100',label:'上海市',children:[{value:"310101",label:"黄浦区"},{value:"310104",label:"徐汇区"},{value:"310105",label:"长宁区"},{value:"310106",label:"静安区"},{value:"310107",label:"普陀区"},{value:"310109",label:"虹口区"},{value:"310110",label:"杨浦区"},{value:"310112",label:"闵行区"},{value:"310113",label:"宝山区"},{value:"310114",label:"嘉定区"},{value:"310115",label:"浦东新区"},{value:"310116",label:"金山区"},{value:"310117",label:"松江区"},{value:"310118",label:"青浦区"},{value:"310120",label:"奉贤区"},{value:"310151",label:"崇明区"}]}]},{value:'320000',label:'江苏省',children:[{value:"320100",label:"南京市",children:[{value:"320102",label:"玄武区"},{value:"320104",label:"秦淮区"},{value:"320105",label:"建邺区"},{value:"320106",label:"鼓楼区"},{value:"320111",label:"浦口区"},{value:"320113",label:"栖霞区"},{value:"320114",label:"雨花台区"},{value:"320115",label:"江宁区"},{value:"320116",label:"六合区"},{value:"320117",label:"溧水区"},{value:"320118",label:"高淳区"}]},{value:"320200",label:"无锡市",children:[{value:"320205",label:"锡山区"},{value:"320206",label:"惠山区"},{value:"320211",label:"滨湖区"},{value:"320281",label:"江阴市"},{value:"320282",label:"宜兴市"},{value:"320213",label:"梁溪区"},{value:"320214",label:"新吴区"}]},{value:"320300",label:"徐州市",children:[{value:"320302",label:"鼓楼区"},{value:"320303",label:"云龙区"},{value:"320305",label:"贾汪区"},{value:"320311",label:"泉山区"},{value:"320321",label:"丰县"},{value:"320322",label:"沛县"},{value:"320324",label:"睢宁县"},{value:"320381",label:"新沂市"},{value:"320382",label:"邳州市"},{value:"320371",label:"徐州经济技术开发区"}]},{value:"320400",label:"常州市",children:[{value:"320402",label:"天宁区"},{value:"320404",label:"钟楼区"},{value:"320411",label:"新北区"},{value:"320412",label:"武进区"},{value:"320481",label:"溧阳市"},{value:"320413",label:"金坛区"}]},{value:"320500",label:"苏州市",children:[{value:"320505",label:"虎丘区"},{value:"320506",label:"吴中区"},{value:"320507",label:"相城区"},{value:"320581",label:"常熟市"},{value:"320582",label:"张家港市"},{value:"320583",label:"昆山市"},{value:"320509",label:"吴江区"},{value:"320585",label:"太仓市"},{value:"320508",label:"姑苏区"},{value:"320571",label:"苏州工业园区"}]},{value:"320600",label:"南通市",children:[{value:"320602",label:"崇川区"},{value:"320611",label:"港闸区"},{value:"320612",label:"通州区"},{value:"320621",label:"海安县"},{value:"320623",label:"如东县"},{value:"320681",label:"启东市"},{value:"320682",label:"如皋市"},{value:"320684",label:"海门市"},{value:"320671",label:"南通经济技术开发区"}]},{value:"320700",label:"连云港市",children:[{value:"320703",label:"连云区"},{value:"320706",label:"海州区"},{value:"320707",label:"赣榆区"},{value:"320722",label:"东海县"},{value:"320723",label:"灌云县"},{value:"320724",label:"灌南县"},{value:"320771",label:"连云港经济技术开发区"},{value:"320772",label:"连云港高新技术产业开发区"}]},{value:"320800",label:"淮安市",children:[{value:"320804",label:"淮阴区"},{value:"320812",label:"清江浦区"},{value:"320826",label:"涟水县"},{value:"320813",label:"洪泽区"},{value:"320830",label:"盱眙县"},{value:"320831",label:"金湖县"},{value:"320803",label:"淮安区"},{value:"320871",label:"淮安经济技术开发区"}]},{value:"320900",label:"盐城市",children:[{value:"320902",label:"亭湖区"},{value:"320903",label:"盐都区"},{value:"320921",label:"响水县"},{value:"320922",label:"滨海县"},{value:"320904",label:"大丰区"},{value:"320923",label:"阜宁县"},{value:"320924",label:"射阳县"},{value:"320925",label:"建湖县"},{value:"320981",label:"东台市"},{value:"320971",label:"盐城经济技术开发区"}]},{value:"321000",label:"扬州市",children:[{value:"321002",label:"广陵区"},{value:"321003",label:"邗江区"},{value:"321011",label:"维扬区"},{value:"321023",label:"宝应县"},{value:"321081",label:"仪征市"},{value:"321084",label:"高邮市"},{value:"321012",label:"江都区"},{value:"321071",label:"扬州经济技术开发区"}]},{value:"321100",label:"镇江市",children:[{value:"321102",label:"京口区"},{value:"321111",label:"润州区"},{value:"321112",label:"丹徒区"},{value:"321181",label:"丹阳市"},{value:"321182",label:"扬中市"},{value:"321183",label:"句容市"},{value:"321171",label:"镇江新区"}]},{value:"321200",label:"泰州市",children:[{value:"321202",label:"海陵区"},{value:"321203",label:"高港区"},{value:"321281",label:"兴化市"},{value:"321282",label:"靖江市"},{value:"321283",label:"泰兴市"},{value:"321204",label:"姜堰区"},{value:"321271",label:"泰州医药高新技术产业开发区"}]},{value:"321300",label:"宿迁市",children:[{value:"321302",label:"宿城区"},{value:"321311",label:"宿豫区"},{value:"321322",label:"沭阳县"},{value:"321323",label:"泗阳县"},{value:"321324",label:"泗洪县"}]}]},{value:'330000',label:'浙江省',children:[{value:"330100",label:"杭州市",children:[{value:"330102",label:"上城区"},{value:"330103",label:"下城区"},{value:"330104",label:"江干区"},{value:"330105",label:"拱墅区"},{value:"330106",label:"西湖区"},{value:"330108",label:"滨江区"},{value:"330109",label:"萧山区"},{value:"330110",label:"余杭区"},{value:"330122",label:"桐庐县"},{value:"330127",label:"淳安县"},{value:"330182",label:"建德市"},{value:"330111",label:"富阳区"},{value:"330112",label:"临安区"},{value:"330186",label:"其它区"}]},{value:"330200",label:"宁波市",children:[{value:"330203",label:"海曙区"},{value:"330205",label:"江北区"},{value:"330206",label:"北仑区"},{value:"330211",label:"镇海区"},{value:"330212",label:"鄞州区"},{value:"330225",label:"象山县"},{value:"330226",label:"宁海县"},{value:"330281",label:"余姚市"},{value:"330282",label:"慈溪市"},{value:"330213",label:"奉化区"}]},{value:"330300",label:"温州市",children:[{value:"330302",label:"鹿城区"},{value:"330303",label:"龙湾区"},{value:"330304",label:"瓯海区"},{value:"330305",label:"洞头区"},{value:"330324",label:"永嘉县"},{value:"330326",label:"平阳县"},{value:"330327",label:"苍南县"},{value:"330328",label:"文成县"},{value:"330329",label:"泰顺县"},{value:"330381",label:"瑞安市"},{value:"330382",label:"乐清市"},{value:"330371",label:"温州经济技术开发区"}]},{value:"330400",label:"嘉兴市",children:[{value:"330402",label:"南湖区"},{value:"330411",label:"秀洲区"},{value:"330421",label:"嘉善县"},{value:"330424",label:"海盐县"},{value:"330481",label:"海宁市"},{value:"330482",label:"平湖市"},{value:"330483",label:"桐乡市"}]},{value:"330500",label:"湖州市",children:[{value:"330502",label:"吴兴区"},{value:"330503",label:"南浔区"},{value:"330521",label:"德清县"},{value:"330522",label:"长兴县"},{value:"330523",label:"安吉县"}]},{value:"330600",label:"绍兴市",children:[{value:"330602",label:"越城区"},{value:"330621",label:"柯桥区"},{value:"330681",label:"诸暨市"},{value:"330604",label:"上虞区"},{value:"330683",label:"嵊州市"},{value:"330624",label:"新昌县"}]},{value:"330700",label:"金华市",children:[{value:"330702",label:"婺城区"},{value:"330703",label:"金东区"},{value:"330723",label:"武义县"},{value:"330726",label:"浦江县"},{value:"330727",label:"磐安县"},{value:"330781",label:"兰溪市"},{value:"330782",label:"义乌市"},{value:"330783",label:"东阳市"},{value:"330784",label:"永康市"}]},{value:"330800",label:"衢州市",children:[{value:"330802",label:"柯城区"},{value:"330803",label:"衢江区"},{value:"330822",label:"常山县"},{value:"330824",label:"开化县"},{value:"330825",label:"龙游县"},{value:"330881",label:"江山市"}]},{value:"330900",label:"舟山市",children:[{value:"330902",label:"定海区"},{value:"330903",label:"普陀区"},{value:"330921",label:"岱山县"},{value:"330922",label:"嵊泗县"}]},{value:"331000",label:"台州市",children:[{value:"331002",label:"椒江区"},{value:"331003",label:"黄岩区"},{value:"331004",label:"路桥区"},{value:"331083",label:"玉环市"},{value:"331022",label:"三门县"},{value:"331023",label:"天台县"},{value:"331024",label:"仙居县"},{value:"331081",label:"温岭市"},{value:"331082",label:"临海市"}]},{value:"331100",label:"丽水市",children:[{value:"331102",label:"莲都区"},{value:"331121",label:"青田县"},{value:"331122",label:"缙云县"},{value:"331123",label:"遂昌县"},{value:"331124",label:"松阳县"},{value:"331125",label:"云和县"},{value:"331126",label:"庆元县"},{value:"331127",label:"景宁畲族自治县"},{value:"331181",label:"龙泉市"}]}]},{value:'340000',label:'安徽省',children:[{value:"340100",label:"合肥市",children:[{value:"340111",label:"包河区"},{value:"340104",label:"蜀山区"},{value:"340103",label:"庐阳区"},{value:"340102",label:"瑶海区"},{value:"340171",label:"合肥高新技术产业开发区"},{value:"340172",label:"合肥经济技术开发区"},{value:"340173",label:"合肥新站高新技术产业开发区"},{value:"340121",label:"长丰县"},{value:"340122",label:"肥东县"},{value:"340123",label:"肥西县"},{value:"340124",label:"庐江县"},{value:"340181",label:"巢湖市"}]},{value:"340200",label:"芜湖市",children:[{value:"340202",label:"镜湖区"},{value:"340203",label:"弋江区"},{value:"340207",label:"鸠江区"},{value:"340208",label:"三山区"},{value:"340221",label:"芜湖县"},{value:"340222",label:"繁昌县"},{value:"340223",label:"南陵县"},{value:"340225",label:"无为县"},{value:"340272",label:"安徽芜湖长江大桥经济开发区"},{value:"340271",label:"芜湖经济技术开发区"}]},{value:"340300",label:"蚌埠市",children:[{value:"340302",label:"龙子湖区"},{value:"340303",label:"蚌山区"},{value:"340304",label:"禹会区"},{value:"340311",label:"淮上区"},{value:"340321",label:"怀远县"},{value:"340322",label:"五河县"},{value:"340323",label:"固镇县"},{value:"340371",label:"蚌埠市高新技术开发区"},{value:"340372 ",label:"蚌埠市经济开发区"}]},{value:"340400",label:"淮南市",children:[{value:"340402",label:"大通区"},{value:"340403",label:"田家庵区"},{value:"340404",label:"谢家集区"},{value:"340405",label:"八公山区"},{value:"340406",label:"潘集区"},{value:"340421",label:"凤台县"},{value:"340422",label:"寿县"}]},{value:"340500",label:"马鞍山市",children:[{value:"340503",label:"花山区"},{value:"340504",label:"雨山区"},{value:"340521",label:"当涂县"},{value:"340506",label:"博望区"},{value:"340522",label:"含山县"},{value:"340523",label:"和县"}]},{value:"340600",label:"淮北市",children:[{value:"340602",label:"杜集区"},{value:"340603",label:"相山区"},{value:"340604",label:"烈山区"},{value:"340621",label:"濉溪县"}]},{value:"340700",label:"铜陵市",children:[{value:"340705",label:"铜官区"},{value:"340706",label:"义安区"},{value:"340711",label:"郊区"},{value:"340722",label:"枞阳县"}]},{value:"340800",label:"安庆市",children:[{value:"340802",label:"迎江区"},{value:"340803",label:"大观区"},{value:"340811",label:"宜秀区"},{value:"340822",label:"怀宁县"},{value:"340824",label:"潜山县"},{value:"340825",label:"太湖县"},{value:"340826",label:"宿松县"},{value:"340827",label:"望江县"},{value:"340828",label:"岳西县"},{value:"340881",label:"桐城市"},{value:"340871",label:"安徽安庆经济开发区"}]},{value:"341000",label:"黄山市",children:[{value:"341002",label:"屯溪区"},{value:"341003",label:"黄山区"},{value:"341004",label:"徽州区"},{value:"341021",label:"歙县"},{value:"341022",label:"休宁县"},{value:"341023",label:"黟县"},{value:"341024",label:"祁门县"}]},{value:"341100",label:"滁州市",children:[{value:"341102",label:"琅琊区"},{value:"341103",label:"南谯区"},{value:"341122",label:"来安县"},{value:"341124",label:"全椒县"},{value:"341125",label:"定远县"},{value:"341126",label:"凤阳县"},{value:"341181",label:"天长市"},{value:"341182",label:"明光市"},{value:"341171",label:"苏滁现代产业园"},{value:"341172",label:"滁州经济技术开发区"}]},{value:"341200",label:"阜阳市",children:[{value:"341202",label:"颍州区"},{value:"341203",label:"颍东区"},{value:"341204",label:"颍泉区"},{value:"341221",label:"临泉县"},{value:"341222",label:"太和县"},{value:"341225",label:"阜南县"},{value:"341226",label:"颍上县"},{value:"341282",label:"界首市"},{value:"341272",label:"阜阳经济技术开发区"},{value:"341271",label:"阜阳合肥现代产业园区"}]},{value:"341300",label:"宿州市",children:[{value:"341302",label:"埇桥区"},{value:"341321",label:"砀山县"},{value:"341322",label:"萧县"},{value:"341323",label:"灵璧县"},{value:"341324",label:"泗县"},{value:"341371",label:"宿州马鞍山现代产业园区"},{value:"341372",label:"宿州经济技术开发区"}]},{value:"341500",label:"六安市",children:[{value:"341502",label:"金安区"},{value:"341503",label:"裕安区"},{value:"341504",label:"叶集区"},{value:"341522",label:"霍邱县"},{value:"341523",label:"舒城县"},{value:"341524",label:"金寨县"},{value:"341525",label:"霍山县"}]},{value:"341600",label:"亳州市",children:[{value:"341602",label:"谯城区"},{value:"341621",label:"涡阳县"},{value:"341622",label:"蒙城县"},{value:"341623",label:"利辛县"}]},{value:"341700",label:"池州市",children:[{value:"341702",label:"贵池区"},{value:"341721",label:"东至县"},{value:"341722",label:"石台县"},{value:"341723",label:"青阳县"}]},{value:"341800",label:"宣城市",children:[{value:"341802",label:"宣州区"},{value:"341821",label:"郎溪县"},{value:"341822",label:"广德县"},{value:"341823",label:"泾县"},{value:"341824",label:"绩溪县"},{value:"341825",label:"旌德县"},{value:"341881",label:"宁国市"},{value:"341871",label:"宣城市经济开发区"}]}]},{value:'350000',label:'福建省',children:[{value:"350100",label:"福州市",children:[{value:"350102",label:"鼓楼区"},{value:"350103",label:"台江区"},{value:"350104",label:"仓山区"},{value:"350105",label:"马尾区"},{value:"350111",label:"晋安区"},{value:"350121",label:"闽侯县"},{value:"350122",label:"连江县"},{value:"350123",label:"罗源县"},{value:"350124",label:"闽清县"},{value:"350125",label:"永泰县"},{value:"350128",label:"平潭县"},{value:"350181",label:"福清市"},{value:"350182",label:"长乐市"}]},{value:"350200",label:"厦门市",children:[{value:"350203",label:"思明区"},{value:"350205",label:"海沧区"},{value:"350206",label:"湖里区"},{value:"350211",label:"集美区"},{value:"350212",label:"同安区"},{value:"350213",label:"翔安区"}]},{value:"350300",label:"莆田市",children:[{value:"350302",label:"城厢区"},{value:"350303",label:"涵江区"},{value:"350304",label:"荔城区"},{value:"350305",label:"秀屿区"},{value:"350322",label:"仙游县"}]},{value:"350400",label:"三明市",children:[{value:"350402",label:"梅列区"},{value:"350403",label:"三元区"},{value:"350421",label:"明溪县"},{value:"350423",label:"清流县"},{value:"350424",label:"宁化县"},{value:"350425",label:"大田县"},{value:"350426",label:"尤溪县"},{value:"350427",label:"沙县"},{value:"350428",label:"将乐县"},{value:"350429",label:"泰宁县"},{value:"350430",label:"建宁县"},{value:"350481",label:"永安市"}]},{value:"350500",label:"泉州市",children:[{value:"350502",label:"鲤城区"},{value:"350503",label:"丰泽区"},{value:"350504",label:"洛江区"},{value:"350505",label:"泉港区"},{value:"350521",label:"惠安县"},{value:"350524",label:"安溪县"},{value:"350525",label:"永春县"},{value:"350526",label:"德化县"},{value:"350527",label:"金门县"},{value:"350581",label:"石狮市"},{value:"350582",label:"晋江市"},{value:"350583",label:"南安市"}]},{value:"350600",label:"漳州市",children:[{value:"350602",label:"芗城区"},{value:"350603",label:"龙文区"},{value:"350622",label:"云霄县"},{value:"350623",label:"漳浦县"},{value:"350624",label:"诏安县"},{value:"350625",label:"长泰县"},{value:"350626",label:"东山县"},{value:"350627",label:"南靖县"},{value:"350628",label:"平和县"},{value:"350629",label:"华安县"},{value:"350681",label:"龙海市"}]},{value:"350700",label:"南平市",children:[{value:"350702",label:"延平区"},{value:"350721",label:"顺昌县"},{value:"350722",label:"浦城县"},{value:"350723",label:"光泽县"},{value:"350724",label:"松溪县"},{value:"350725",label:"政和县"},{value:"350781",label:"邵武市"},{value:"350782",label:"武夷山市"},{value:"350783",label:"建瓯市"},{value:"350703",label:"建阳区"}]},{value:"350800",label:"龙岩市",children:[{value:"350802",label:"新罗区"},{value:"350821",label:"长汀县"},{value:"350803",label:"永定区"},{value:"350823",label:"上杭县"},{value:"350824",label:"武平县"},{value:"350825",label:"连城县"},{value:"350881",label:"漳平市"}]},{value:"350900",label:"宁德市",children:[{value:"350902",label:"蕉城区"},{value:"350921",label:"霞浦县"},{value:"350922",label:"古田县"},{value:"350923",label:"屏南县"},{value:"350924",label:"寿宁县"},{value:"350925",label:"周宁县"},{value:"350926",label:"柘荣县"},{value:"350981",label:"福安市"},{value:"350982",label:"福鼎市"}]}]},{value:'360000',label:'江西省',children:[{value:"360100",label:"南昌市",children:[{value:"360102",label:"东湖区"},{value:"360103",label:"西湖区"},{value:"360104",label:"青云谱区"},{value:"360105",label:"湾里区"},{value:"360111",label:"青山湖区"},{value:"360121",label:"南昌县"},{value:"360112",label:"新建区"},{value:"360123",label:"安义县"},{value:"360124",label:"进贤县"}]},{value:"360200",label:"景德镇市",children:[{value:"360202",label:"昌江区"},{value:"360203",label:"珠山区"},{value:"360222",label:"浮梁县"},{value:"360281",label:"乐平市"}]},{value:"360300",label:"萍乡市",children:[{value:"360302",label:"安源区"},{value:"360313",label:"湘东区"},{value:"360321",label:"莲花县"},{value:"360322",label:"上栗县"},{value:"360323",label:"芦溪县"}]},{value:"360400",label:"九江市",children:[{value:"360402",label:"濂溪区"},{value:"360403",label:"浔阳区"},{value:"360404",label:"柴桑区"},{value:"360423",label:"武宁县"},{value:"360424",label:"修水县"},{value:"360425",label:"永修县"},{value:"360426",label:"德安县"},{value:"360428",label:"都昌县"},{value:"360429",label:"湖口县"},{value:"360430",label:"彭泽县"},{value:"360481",label:"瑞昌市"},{value:"360482",label:"共青城市"},{value:"360483",label:"庐山市"}]},{value:"360500",label:"新余市",children:[{value:"360502",label:"渝水区"},{value:"360521",label:"分宜县"}]},{value:"360600",label:"鹰潭市",children:[{value:"360602",label:"月湖区"},{value:"360622",label:"余江县"},{value:"360681",label:"贵溪市"}]},{value:"360700",label:"赣州市",children:[{value:"360702",label:"章贡区"},{value:"360704",label:"赣县区"},{value:"360722",label:"信丰县"},{value:"360723",label:"大余县"},{value:"360724",label:"上犹县"},{value:"360725",label:"崇义县"},{value:"360726",label:"安远县"},{value:"360727",label:"龙南县"},{value:"360728",label:"定南县"},{value:"360729",label:"全南县"},{value:"360730",label:"宁都县"},{value:"360731",label:"于都县"},{value:"360732",label:"兴国县"},{value:"360733",label:"会昌县"},{value:"360734",label:"寻乌县"},{value:"360735",label:"石城县"},{value:"360781",label:"瑞金市"},{value:"360703",label:"南康区"}]},{value:"360800",label:"吉安市",children:[{value:"360802",label:"吉州区"},{value:"360803",label:"青原区"},{value:"360821",label:"吉安县"},{value:"360822",label:"吉水县"},{value:"360823",label:"峡江县"},{value:"360824",label:"新干县"},{value:"360825",label:"永丰县"},{value:"360826",label:"泰和县"},{value:"360827",label:"遂川县"},{value:"360828",label:"万安县"},{value:"360829",label:"安福县"},{value:"360830",label:"永新县"},{value:"360881",label:"井冈山市"}]},{value:"360900",label:"宜春市",children:[{value:"360902",label:"袁州区"},{value:"360921",label:"奉新县"},{value:"360922",label:"万载县"},{value:"360923",label:"上高县"},{value:"360924",label:"宜丰县"},{value:"360925",label:"靖安县"},{value:"360926",label:"铜鼓县"},{value:"360981",label:"丰城市"},{value:"360982",label:"樟树市"},{value:"360983",label:"高安市"}]},{value:"361000",label:"抚州市",children:[{value:"361002",label:"临川区"},{value:"361021",label:"南城县"},{value:"361022",label:"黎川县"},{value:"361023",label:"南丰县"},{value:"361024",label:"崇仁县"},{value:"361025",label:"乐安县"},{value:"361026",label:"宜黄县"},{value:"361027",label:"金溪县"},{value:"361028",label:"资溪县"},{value:"361003",label:"东乡区"},{value:"361030",label:"广昌县"}]},{value:"361100",label:"上饶市",children:[{value:"361102",label:"信州区"},{value:"361121",label:"上饶县"},{value:"361103",label:"广丰区"},{value:"361123",label:"玉山县"},{value:"361124",label:"铅山县"},{value:"361125",label:"横峰县"},{value:"361126",label:"弋阳县"},{value:"361127",label:"余干县"},{value:"361128",label:"鄱阳县"},{value:"361129",label:"万年县"},{value:"361130",label:"婺源县"},{value:"361181",label:"德兴市"}]}]},{value:'370000',label:'山东省',children:[{value:"370100",label:"济南市",children:[{value:"370102",label:"历下区"},{value:"370103",label:"市中区"},{value:"370104",label:"槐荫区"},{value:"370105",label:"天桥区"},{value:"370112",label:"历城区"},{value:"370113",label:"长清区"},{value:"370124",label:"平阴县"},{value:"370125",label:"济阳县"},{value:"370126",label:"商河县"},{value:"370114",label:"章丘区"},{value:"370171",label:"济南高新技术产业开发区"}]},{value:"370200",label:"青岛市",children:[{value:"370202",label:"市南区"},{value:"370203",label:"市北区"},{value:"370211",label:"黄岛区"},{value:"370212",label:"崂山区"},{value:"370213",label:"李沧区"},{value:"370214",label:"城阳区"},{value:"370281",label:"胶州市"},{value:"370215",label:"即墨区"},{value:"370283",label:"平度市"},{value:"370285",label:"莱西市"},{value:"370271",label:"青岛高新技术产业开发区"}]},{value:"370300",label:"淄博市",children:[{value:"370302",label:"淄川区"},{value:"370303",label:"张店区"},{value:"370304",label:"博山区"},{value:"370305",label:"临淄区"},{value:"370306",label:"周村区"},{value:"370321",label:"桓台县"},{value:"370322",label:"高青县"},{value:"370323",label:"沂源县"}]},{value:"370400",label:"枣庄市",children:[{value:"370402",label:"市中区"},{value:"370403",label:"薛城区"},{value:"370404",label:"峄城区"},{value:"370405",label:"台儿庄区"},{value:"370406",label:"山亭区"},{value:"370481",label:"滕州市"}]},{value:"370500",label:"东营市",children:[{value:"370502",label:"东营区"},{value:"370503",label:"河口区"},{value:"370521",label:"垦利县"},{value:"370522",label:"利津县"},{value:"370523",label:"广饶县"},{value:"370589",label:"西城区"},{value:"370571",label:"东营经济技术开发区"},{value:"370572",label:"东营港经济开发区"}]},{value:"370600",label:"烟台市",children:[{value:"370602",label:"芝罘区"},{value:"370611",label:"福山区"},{value:"370612",label:"牟平区"},{value:"370613",label:"莱山区"},{value:"370634",label:"长岛县"},{value:"370681",label:"龙口市"},{value:"370682",label:"莱阳市"},{value:"370683",label:"莱州市"},{value:"370684",label:"蓬莱市"},{value:"370685",label:"招远市"},{value:"370686",label:"栖霞市"},{value:"370687",label:"海阳市"},{value:"370671",label:"烟台高新技术产业开发区"},{value:"370672",label:"烟台经济技术开发区"}]},{value:"370700",label:"潍坊市",children:[{value:"370702",label:"潍城区"},{value:"370703",label:"寒亭区"},{value:"370704",label:"坊子区"},{value:"370705",label:"奎文区"},{value:"370724",label:"临朐县"},{value:"370725",label:"昌乐县"},{value:"370772",label:"潍坊滨海经济技术开发区"},{value:"370781",label:"青州市"},{value:"370782",label:"诸城市"},{value:"370783",label:"寿光市"},{value:"370784",label:"安丘市"},{value:"370785",label:"高密市"},{value:"370786",label:"昌邑市"}]},{value:"370800",label:"济宁市",children:[{value:"370811",label:"任城区"},{value:"370826",label:"微山县"},{value:"370827",label:"鱼台县"},{value:"370828",label:"金乡县"},{value:"370829",label:"嘉祥县"},{value:"370830",label:"汶上县"},{value:"370831",label:"泗水县"},{value:"370832",label:"梁山县"},{value:"370881",label:"曲阜市"},{value:"370812",label:"兖州区"},{value:"370883",label:"邹城市"},{value:"370871",label:"济宁高新技术产业开发区"}]},{value:"370900",label:"泰安市",children:[{value:"370902",label:"泰山区"},{value:"370903",label:"岱岳区"},{value:"370921",label:"宁阳县"},{value:"370923",label:"东平县"},{value:"370982",label:"新泰市"},{value:"370983",label:"肥城市"}]},{value:"371000",label:"威海市",children:[{value:"371002",label:"环翠区"},{value:"371003",label:"文登区"},{value:"371082",label:"荣成市"},{value:"371083",label:"乳山市"},{value:"371071",label:"威海火炬高技术产业开发区"},{value:"371072",label:"威海经济技术开发区"},{value:"371073",label:"威海临港经济技术开发区"}]},{value:"371100",label:"日照市",children:[{value:"371102",label:"东港区"},{value:"371103",label:"岚山区"},{value:"371121",label:"五莲县"},{value:"371122",label:"莒县"},{value:"371171",label:"日照经济技术开发区"},{value:"371172",label:"日照国际海洋城"}]},{value:"371200",label:"莱芜市",children:[{value:"371202",label:"莱城区"},{value:"371203",label:"钢城区"}]},{value:"371300",label:"临沂市",children:[{value:"371302",label:"兰山区"},{value:"371311",label:"罗庄区"},{value:"371312",label:"河东区"},{value:"371321",label:"沂南县"},{value:"371322",label:"郯城县"},{value:"371323",label:"沂水县"},{value:"371324",label:"兰陵县"},{value:"371325",label:"费县"},{value:"371326",label:"平邑县"},{value:"371327",label:"莒南县"},{value:"371328",label:"蒙阴县"},{value:"371329",label:"临沭县"},{value:"371371",label:"临沂高新技术产业开发区"},{value:"371373",label:"临沂临港经济开发区"},{value:"371372",label:"临沂经济技术开发区"}]},{value:"371400",label:"德州市",children:[{value:"371402",label:"德城区"},{value:"371403",label:"陵城区"},{value:"371422",label:"宁津县"},{value:"371423",label:"庆云县"},{value:"371424",label:"临邑县"},{value:"371425",label:"齐河县"},{value:"371426",label:"平原县"},{value:"371427",label:"夏津县"},{value:"371428",label:"武城县"},{value:"371481",label:"乐陵市"},{value:"371482",label:"禹城市"},{value:"371471",label:"德州经济技术开发区"},{value:"371472",label:"德州运河经济开发区"}]},{value:"371500",label:"聊城市",children:[{value:"371502",label:"东昌府区"},{value:"371521",label:"阳谷县"},{value:"371522",label:"莘县"},{value:"371523",label:"茌平县"},{value:"371524",label:"东阿县"},{value:"371525",label:"冠县"},{value:"371526",label:"高唐县"},{value:"371581",label:"临清市"}]},{value:"371600",label:"滨州市",children:[{value:"371602",label:"滨城区"},{value:"371621",label:"惠民县"},{value:"371622",label:"阳信县"},{value:"371623",label:"无棣县"},{value:"371603",label:"沾化区"},{value:"371625",label:"博兴县"},{value:"371626",label:"邹平县"}]},{value:"371700",label:"菏泽市",children:[{value:"371702",label:"牡丹区"},{value:"371721",label:"曹县"},{value:"371722",label:"单县"},{value:"371723",label:"成武县"},{value:"371724",label:"巨野县"},{value:"371725",label:"郓城县"},{value:"371726",label:"鄄城县"},{value:"371727",label:"定陶区"},{value:"371728",label:"东明县"},{value:"371771",label:"菏泽经济技术开发区"},{value:"371772",label:"菏泽高新技术开发区"}]}]},{value:'410000',label:'河南省',children:[{value:"410100",label:"郑州市",children:[{value:"410102",label:"中原区"},{value:"410103",label:"二七区"},{value:"410104",label:"管城回族区"},{value:"410105",label:"金水区"},{value:"410106",label:"上街区"},{value:"410108",label:"惠济区"},{value:"410122",label:"中牟县"},{value:"410181",label:"巩义市"},{value:"410182",label:"荥阳市"},{value:"410183",label:"新密市"},{value:"410184",label:"新郑市"},{value:"410185",label:"登封市"},{value:"410171",label:"郑州经济技术开发区"},{value:"410172",label:"郑州高新技术产业开发区"},{value:"410173",label:"郑州航空港经济综合实验区"}]},{value:"410200",label:"开封市",children:[{value:"410202",label:"龙亭区"},{value:"410203",label:"顺河回族区"},{value:"410204",label:"鼓楼区"},{value:"410205",label:"禹王台区"},{value:"410211",label:"金明区"},{value:"410221",label:"杞县"},{value:"410222",label:"通许县"},{value:"410223",label:"尉氏县"},{value:"410225",label:"兰考县"},{value:"410212",label:"祥符区"}]},{value:"410300",label:"洛阳市",children:[{value:"410302",label:"老城区"},{value:"410303",label:"西工区"},{value:"410304",label:"廛河回族区"},{value:"410305",label:"涧西区"},{value:"410306",label:"吉利区"},{value:"410307",label:"洛龙区"},{value:"410322",label:"孟津县"},{value:"410323",label:"新安县"},{value:"410324",label:"栾川县"},{value:"410325",label:"嵩县"},{value:"410326",label:"汝阳县"},{value:"410327",label:"宜阳县"},{value:"410328",label:"洛宁县"},{value:"410329",label:"伊川县"},{value:"410381",label:"偃师市"},{value:"410371",label:"洛阳高新技术产业开发区"},{value:"471005",label:"其它区"}]},{value:"410400",label:"平顶山市",children:[{value:"410402",label:"新华区"},{value:"410403",label:"卫东区"},{value:"410404",label:"石龙区"},{value:"410411",label:"湛河区"},{value:"410421",label:"宝丰县"},{value:"410422",label:"叶县"},{value:"410423",label:"鲁山县"},{value:"410425",label:"郏县"},{value:"410481",label:"舞钢市"},{value:"410482",label:"汝州市"},{value:"410471",label:"平顶山高新技术产业开发区"},{value:"410472",label:"平顶山市新城区"}]},{value:"410500",label:"安阳市",children:[{value:"410502",label:"文峰区"},{value:"410503",label:"北关区"},{value:"410505",label:"殷都区"},{value:"410506",label:"龙安区"},{value:"410522",label:"安阳县"},{value:"410523",label:"汤阴县"},{value:"410526",label:"滑县"},{value:"410527",label:"内黄县"},{value:"410581",label:"林州市"},{value:"410571",label:"安阳高新技术产业开发区"}]},{value:"410600",label:"鹤壁市",children:[{value:"410602",label:"鹤山区"},{value:"410603",label:"山城区"},{value:"410611",label:"淇滨区"},{value:"410621",label:"浚县"},{value:"410622",label:"淇县"},{value:"410671",label:"鹤壁经济技术开发区"}]},{value:"410700",label:"新乡市",children:[{value:"410702",label:"红旗区"},{value:"410703",label:"卫滨区"},{value:"410704",label:"凤泉区"},{value:"410711",label:"牧野区"},{value:"410721",label:"新乡县"},{value:"410724",label:"获嘉县"},{value:"410725",label:"原阳县"},{value:"410726",label:"延津县"},{value:"410727",label:"封丘县"},{value:"410728",label:"长垣县"},{value:"410781",label:"卫辉市"},{value:"410782",label:"辉县市"},{value:"410771",label:"新乡高新技术产业开发区"},{value:"410773",label:"新乡市平原城乡一体化示范区"},{value:"410772",label:"新乡经济技术开发区"}]},{value:"410800",label:"焦作市",children:[{value:"410802",label:"解放区"},{value:"410803",label:"中站区"},{value:"410804",label:"马村区"},{value:"410811",label:"山阳区"},{value:"410821",label:"修武县"},{value:"410822",label:"博爱县"},{value:"410823",label:"武陟县"},{value:"410825",label:"温县"},{value:"410882",label:"沁阳市"},{value:"410883",label:"孟州市"},{value:"410871",label:"焦作城乡一体化示范区"}]},{value:"410900",label:"濮阳市",children:[{value:"410902",label:"华龙区"},{value:"410922",label:"清丰县"},{value:"410923",label:"南乐县"},{value:"410926",label:"范县"},{value:"410927",label:"台前县"},{value:"410928",label:"濮阳县"},{value:"410971",label:"河南濮阳工业园区"},{value:"410972",label:"濮阳经济技术开发区"}]},{value:"411000",label:"许昌市",children:[{value:"411002",label:"魏都区"},{value:"411003",label:"建安区"},{value:"411024",label:"鄢陵县"},{value:"411025",label:"襄城县"},{value:"411081",label:"禹州市"},{value:"411082",label:"长葛市"},{value:"411071",label:"许昌经济技术开发区"}]},{value:"411100",label:"漯河市",children:[{value:"411102",label:"源汇区"},{value:"411103",label:"郾城区"},{value:"411104",label:"召陵区"},{value:"411121",label:"舞阳县"},{value:"411122",label:"临颍县"},{value:"411171",label:"漯河经济技术开发区"}]},{value:"411200",label:"三门峡市",children:[{value:"411202",label:"湖滨区"},{value:"411221",label:"渑池县"},{value:"411222",label:"陕县"},{value:"411224",label:"卢氏县"},{value:"411281",label:"义马市"},{value:"411282",label:"灵宝市"},{value:"411203",label:"陕州区"},{value:"411271",label:"河南三门峡经济开发区"}]},{value:"411300",label:"南阳市",children:[{value:"411302",label:"宛城区"},{value:"411303",label:"卧龙区"},{value:"411321",label:"南召县"},{value:"411322",label:"方城县"},{value:"411323",label:"西峡县"},{value:"411324",label:"镇平县"},{value:"411325",label:"内乡县"},{value:"411326",label:"淅川县"},{value:"411327",label:"社旗县"},{value:"411328",label:"唐河县"},{value:"411329",label:"新野县"},{value:"411330",label:"桐柏县"},{value:"411381",label:"邓州市"},{value:"411371",label:"南阳高新技术产业开发区"},{value:"411372",label:"南阳市城乡一体化示范区"}]},{value:"411400",label:"商丘市",children:[{value:"411402",label:"梁园区"},{value:"411403",label:"睢阳区"},{value:"411421",label:"民权县"},{value:"411422",label:"睢县"},{value:"411423",label:"宁陵县"},{value:"411424",label:"柘城县"},{value:"411425",label:"虞城县"},{value:"411426",label:"夏邑县"},{value:"411481",label:"永城市"},{value:"411471",label:"豫东综合物流产业聚集区"},{value:"411472",label:"河南商丘经济开发"}]},{value:"411500",label:"信阳市",children:[{value:"411502",label:"浉河区"},{value:"411503",label:"平桥区"},{value:"411521",label:"罗山县"},{value:"411522",label:"光山县"},{value:"411523",label:"新县"},{value:"411524",label:"商城县"},{value:"411525",label:"固始县"},{value:"411526",label:"潢川县"},{value:"411527",label:"淮滨县"},{value:"411528",label:"息县"},{value:"411571",label:"信阳高新技术产业开发区"}]},{value:"411600",label:"周口市",children:[{value:"411602",label:"川汇区"},{value:"411621",label:"扶沟县"},{value:"411622",label:"西华县"},{value:"411623",label:"商水县"},{value:"411624",label:"沈丘县"},{value:"411625",label:"郸城县"},{value:"411626",label:"淮阳县"},{value:"411627",label:"太康县"},{value:"411628",label:"鹿邑县"},{value:"411681",label:"项城市"},{value:"411671",label:"河南周口经济开发区"}]},{value:"411700",label:"驻马店市",children:[{value:"411702",label:"驿城区"},{value:"411721",label:"西平县"},{value:"411722",label:"上蔡县"},{value:"411723",label:"平舆县"},{value:"411724",label:"正阳县"},{value:"411725",label:"确山县"},{value:"411726",label:"泌阳县"},{value:"411727",label:"汝南县"},{value:"411628",label:"遂平县"},{value:"411729",label:"新蔡县"},{value:"411771",label:"河南驻马店经济开发区"}]}]},{value:'420000',label:'湖北省',children:[{value:"420100",label:"武汉市",children:[{value:"420101",label:"市辖区"},{value:"420102",label:"江岸区"},{value:"420103",label:"江汉区"},{value:"420104",label:"硚口区"},{value:"420105",label:"汉阳区"},{value:"420106",label:"武昌区"},{value:"420107",label:"青山区"},{value:"420111",label:"洪山区"},{value:"420112",label:"东西湖区"},{value:"420113",label:"汉南区"},{value:"420114",label:"蔡甸区"},{value:"420115",label:"江夏区"},{value:"420116",label:"黄陂区"},{value:"420117",label:"新洲区"}]},{value:"420200",label:"黄石市",children:[{value:"420201",label:"市辖区"},{value:"420202",label:"黄石港区"},{value:"420203",label:"西塞山区"},{value:"420204",label:"下陆区"},{value:"420205",label:"铁山区"},{value:"420222",label:"阳新县"},{value:"420281",label:"大冶市"}]},{value:"420300",label:"十堰市",children:[{value:"420301",label:"市辖区"},{value:"420302",label:"茅箭区"},{value:"420303",label:"张湾区"},{value:"420304",label:"郧阳区"},{value:"420322",label:"郧西县"},{value:"420323",label:"竹山县"},{value:"420324",label:"竹溪县"},{value:"420325",label:"房县"},{value:"420381",label:"丹江口市"}]},{value:"420500",label:"宜昌市",children:[{value:"420501",label:"市辖区"},{value:"420502",label:"西陵区"},{value:"420503",label:"伍家岗区"},{value:"420504",label:"点军区"},{value:"420505",label:"猇亭区"},{value:"420506",label:"夷陵区"},{value:"420525",label:"远安县"},{value:"420526",label:"兴山县"},{value:"420527",label:"秭归县"},{value:"420528",label:"长阳土家族自治县"},{value:"420529",label:"五峰土家族自治县"},{value:"420581",label:"宜都市"},{value:"420582",label:"当阳市"},{value:"420583",label:"枝江市"}]},{value:"420600",label:"襄阳市",children:[{value:"420601",label:"市辖区"},{value:"420602",label:"襄城区"},{value:"420606",label:"樊城区"},{value:"420607",label:"襄州区"},{value:"420624",label:"南漳县"},{value:"420625",label:"谷城县"},{value:"420626",label:"保康县"},{value:"420682",label:"老河口市"},{value:"420683",label:"枣阳市"},{value:"420684",label:"宜城市"}]},{value:"420700",label:"鄂州市",children:[{value:"420701",label:"市辖区"},{value:"420702",label:"梁子湖区"},{value:"420703",label:"华容区"},{value:"420704",label:"鄂城区"}]},{value:"420800",label:"荆门市",children:[{value:"420801",label:"市辖区"},{value:"420802",label:"东宝区"},{value:"420804",label:"掇刀区"},{value:"420821",label:"京山县"},{value:"420822",label:"沙洋县"},{value:"420881",label:"钟祥市"}]},{value:"420900",label:"孝感市",children:[{value:"420901",label:"市辖区"},{value:"420902",label:"孝南区"},{value:"420921",label:"孝昌县"},{value:"420922",label:"大悟县"},{value:"420923",label:"云梦县"},{value:"420981",label:"应城市"},{value:"420982",label:"安陆市"},{value:"420984",label:"汉川市"}]},{value:"421000",label:"荆州市",children:[{value:"421001",label:"市辖区"},{value:"421002",label:"沙市区"},{value:"421003",label:"荆州区"},{value:"421022",label:"公安县"},{value:"421023",label:"监利县"},{value:"421024",label:"江陵县"},{value:"421071",label:"荆州经济技术开发区"},{value:"421081",label:"石首市"},{value:"421083",label:"洪湖市"},{value:"421087",label:"松滋市"}]},{value:"421100",label:"黄冈市",children:[{value:"421101",label:"市辖区"},{value:"421102",label:"黄州区"},{value:"421121",label:"团风县"},{value:"421122",label:"红安县"},{value:"421123",label:"罗田县"},{value:"421124",label:"英山县"},{value:"421125",label:"浠水县"},{value:"421126",label:"蕲春县"},{value:"421127",label:"黄梅县"},{value:"421171",label:"龙感湖管理区"},{value:"421181",label:"麻城市"},{value:"421182",label:"武穴市"}]},{value:"421200",label:"咸宁市",children:[{value:"421201",label:"市辖区"},{value:"421202",label:"咸安区"},{value:"421221",label:"嘉鱼县"},{value:"421222",label:"通城县"},{value:"421223",label:"崇阳县"},{value:"421224",label:"通山县"},{value:"421281",label:"赤壁市"}]},{value:"421300",label:"随州市",children:[{value:"421301",label:"市辖区"},{value:"421303",label:"曾都区"},{value:"421321",label:"随县"},{value:"421381",label:"广水市"}]},{value:"422800",label:"恩施土家族苗族自治州",children:[{value:"422801",label:"恩施市"},{value:"422802",label:"利川市"},{value:"422822",label:"建始县"},{value:"422823",label:"巴东县"},{value:"422825",label:"宣恩县"},{value:"422826",label:"咸丰县"},{value:"422827",label:"来凤县"},{value:"422828",label:"鹤峰县"}]},{value:"429000",label:"省直辖县级行政区划",children:[{value:"429004",label:"仙桃市"},{value:"429005",label:"潜江市"},{value:"429006",label:"天门市"},{value:"429021",label:"神农架林区"}]}]},{value:'430000',label:'湖南省',children:[{value:"430100",label:"长沙市",children:[{value:"430101",label:"市辖区"},{value:"430102",label:"芙蓉区"},{value:"430103",label:"天心区"},{value:"430104",label:"岳麓区"},{value:"430105",label:"开福区"},{value:"430111",label:"雨花区"},{value:"430112",label:"望城区"},{value:"430121",label:"长沙县"},{value:"430181",label:"浏阳市"},{value:"430182",label:"宁乡市"}]},{value:"430200",label:"株洲市",children:[{value:"430201",label:"市辖区"},{value:"430202",label:"荷塘区"},{value:"430203",label:"芦淞区"},{value:"430204",label:"石峰区"},{value:"430211",label:"天元区"},{value:"430221",label:"株洲县"},{value:"430223",label:"攸县"},{value:"430224",label:"茶陵县"},{value:"430225",label:"炎陵县"},{value:"430271",label:"云龙示范区"},{value:"430281",label:"醴陵市"}]},{value:"430300",label:"湘潭市",children:[{value:"430301",label:"市辖区"},{value:"430302",label:"雨湖区"},{value:"430304",label:"岳塘区"},{value:"430321",label:"湘潭县"},{value:"430371",label:"湖南湘潭高新技术产业园区"},{value:"430372",label:"湘潭昭山示范区"},{value:"430373",label:"湘潭九华示范区"},{value:"430381",label:"湘乡市"},{value:"430382",label:"韶山市"}]},{value:"430400",label:"衡阳市",children:[{value:"430401",label:"市辖区"},{value:"430405",label:"珠晖区"},{value:"430406",label:"雁峰区"},{value:"430407",label:"石鼓区"},{value:"430408",label:"蒸湘区"},{value:"430412",label:"南岳区"},{value:"430421",label:"衡阳县"},{value:"430422",label:"衡南县"},{value:"430423",label:"衡山县"},{value:"430424",label:"衡东县"},{value:"430426",label:"祁东县"},{value:"430471",label:"衡阳综合保税区"},{value:"430472",label:"湖南衡阳高新技术产业园区"},{value:"430473",label:"湖南衡阳松木经济开发区"},{value:"430481",label:"耒阳市"},{value:"430482",label:"常宁市"}]},{value:"430500",label:"邵阳市",children:[{value:"430501",label:"市辖区"},{value:"430502",label:"双清区"},{value:"430503",label:"大祥区"},{value:"430511",label:"北塔区"},{value:"430521",label:"邵东县"},{value:"430522",label:"新邵县"},{value:"430523",label:"邵阳县"},{value:"430524",label:"隆回县"},{value:"430525",label:"洞口县"},{value:"430527",label:"绥宁县"},{value:"430528",label:"新宁县"},{value:"430529",label:"城步苗族自治县"},{value:"430581",label:"武冈市"}]},{value:"430600",label:"岳阳市",children:[{value:"430601",label:"市辖区"},{value:"430602",label:"岳阳楼区"},{value:"430603",label:"云溪区"},{value:"430611",label:"君山区"},{value:"430621",label:"岳阳县"},{value:"430623",label:"华容县"},{value:"430624",label:"湘阴县"},{value:"430626",label:"平江县"},{value:"430671",label:"岳阳市屈原管理区"},{value:"430681",label:"汨罗市"},{value:"430682",label:"临湘市"}]},{value:"430700",label:"常德市",children:[{value:"430701",label:"市辖区"},{value:"430702",label:"武陵区"},{value:"430703",label:"鼎城区"},{value:"430721",label:"安乡县"},{value:"430722",label:"汉寿县"},{value:"430723",label:"澧县"},{value:"430724",label:"临澧县"},{value:"430725",label:"桃源县"},{value:"430726",label:"石门县"},{value:"430771",label:"常德市西洞庭管理区"},{value:"430781",label:"津市市"}]},{value:"430800",label:"张家界市",children:[{value:"430801",label:"市辖区"},{value:"430802",label:"永定区"},{value:"430811",label:"武陵源区"},{value:"430821",label:"慈利县"},{value:"430822",label:"桑植县"}]},{value:"430900",label:"益阳市",children:[{value:"430901",label:"市辖区"},{value:"430902",label:"资阳区"},{value:"430903",label:"赫山区"},{value:"430921",label:"南县"},{value:"430922",label:"桃江县"},{value:"430923",label:"安化县"},{value:"430971",label:"益阳市大通湖管理区"},{value:"430972",label:"湖南益阳高新技术产业园区"},{value:"430981",label:"沅江市"}]},{value:"431000",label:"郴州市",children:[{value:"431001",label:"市辖区"},{value:"431002",label:"北湖区"},{value:"431003",label:"苏仙区"},{value:"431021",label:"桂阳县"},{value:"431022",label:"宜章县"},{value:"431023",label:"永兴县"},{value:"431024",label:"嘉禾县"},{value:"431025",label:"临武县"},{value:"431026",label:"汝城县"},{value:"431027",label:"桂东县"},{value:"431028",label:"安仁县"},{value:"431081",label:"资兴市"}]},{value:"431100",label:"永州市",children:[{value:"431101",label:"市辖区"},{value:"431102",label:"零陵区"},{value:"431103",label:"冷水滩区"},{value:"431121",label:"祁阳县"},{value:"431122",label:"东安县"},{value:"431123",label:"双牌县"},{value:"431124",label:"道县"},{value:"431125",label:"江永县"},{value:"431126",label:"宁远县"},{value:"431127",label:"蓝山县"},{value:"431128",label:"新田县"},{value:"431129",label:"江华瑶族自治县"},{value:"431171",label:"永州经济技术开发区"},{value:"431172",label:"永州市金洞管理区"},{value:"431173",label:"永州市回龙圩管理区"}]},{value:"431200",label:"怀化市",children:[{value:"431201",label:"市辖区"},{value:"431202",label:"鹤城区"},{value:"431221",label:"中方县"},{value:"431222",label:"沅陵县"},{value:"431223",label:"辰溪县"},{value:"431224",label:"溆浦县"},{value:"431225",label:"会同县"},{value:"431226",label:"麻阳苗族自治县"},{value:"431227",label:"新晃侗族自治县"},{value:"431228",label:"芷江侗族自治县"},{value:"431229",label:"靖州苗族侗族自治县"},{value:"431230",label:"通道侗族自治县"},{value:"431271",label:"怀化市洪江管理区"},{value:"431281",label:"洪江市"}]},{value:"431300",label:"娄底市",children:[{value:"431301",label:"市辖区"},{value:"431302",label:"娄星区"},{value:"431321",label:"双峰县"},{value:"431322",label:"新化县"},{value:"431381",label:"冷水江市"},{value:"431382",label:"涟源市"}]},{value:"433100",label:"湘西土家族苗族自治州",children:[{value:"433101",label:"吉首市"},{value:"433122",label:"泸溪县"},{value:"433123",label:"凤凰县"},{value:"433124",label:"花垣县"},{value:"433125",label:"保靖县"},{value:"433126",label:"古丈县"},{value:"433127",label:"永顺县"},{value:"433130",label:"龙山县"},{value:"433172",label:"湖南吉首经济开发区"},{value:"433173",label:"湖南永顺经济开发区"}]}]},{value:'440000',label:'广东省',children:[{value:"440100",label:"广州市",children:[{value:"440101",label:"市辖区"},{value:"440103",label:"荔湾区"},{value:"440104",label:"越秀区"},{value:"440105",label:"海珠区"},{value:"440106",label:"天河区"},{value:"440111",label:"白云区"},{value:"440112",label:"黄埔区"},{value:"440113",label:"番禺区"},{value:"440114",label:"花都区"},{value:"440115",label:"南沙区"},{value:"440117",label:"从化区"},{value:"440118",label:"增城区"}]},{value:"440200",label:"韶关市",children:[{value:"440201",label:"市辖区"},{value:"440203",label:"武江区"},{value:"440204",label:"浈江区"},{value:"440205",label:"曲江区"},{value:"440222",label:"始兴县"},{value:"440224",label:"仁化县"},{value:"440229",label:"翁源县"},{value:"440232",label:"乳源瑶族自治县"},{value:"440233",label:"新丰县"},{value:"440281",label:"乐昌市"},{value:"440282",label:"南雄市"}]},{value:"440300",label:"深圳市",children:[{value:"440301",label:"市辖区"},{value:"440303",label:"罗湖区"},{value:"440304",label:"福田区"},{value:"440305",label:"南山区"},{value:"440306",label:"宝安区"},{value:"440307",label:"龙岗区"},{value:"440308",label:"盐田区"},{value:"440309",label:"龙华区"},{value:"440310",label:"坪山区"}]},{value:"440400",label:"珠海市",children:[{value:"440401",label:"市辖区"},{value:"440402",label:"香洲区"},{value:"440403",label:"斗门区"},{value:"440404",label:"金湾区"}]},{value:"440500",label:"汕头市",children:[{value:"440501",label:"市辖区"},{value:"440507",label:"龙湖区"},{value:"440511",label:"金平区"},{value:"440512",label:"濠江区"},{value:"440513",label:"潮阳区"},{value:"440514",label:"潮南区"},{value:"440515",label:"澄海区"},{value:"440523",label:"南澳县"}]},{value:"440600",label:"佛山市",children:[{value:"440601",label:"市辖区"},{value:"440604",label:"禅城区"},{value:"440605",label:"南海区"},{value:"440606",label:"顺德区"},{value:"440607",label:"三水区"},{value:"440608",label:"高明区"}]},{value:"440700",label:"江门市",children:[{value:"440701",label:"市辖区"},{value:"440703",label:"蓬江区"},{value:"440704",label:"江海区"},{value:"440705",label:"新会区"},{value:"440781",label:"台山市"},{value:"440783",label:"开平市"},{value:"440784",label:"鹤山市"},{value:"440785",label:"恩平市"}]},{value:"440800",label:"湛江市",children:[{value:"440801",label:"市辖区"},{value:"440802",label:"赤坎区"},{value:"440803",label:"霞山区"},{value:"440804",label:"坡头区"},{value:"440811",label:"麻章区"},{value:"440823",label:"遂溪县"},{value:"440825",label:"徐闻县"},{value:"440881",label:"廉江市"},{value:"440882",label:"雷州市"},{value:"440883",label:"吴川市"}]},{value:"440900",label:"茂名市",children:[{value:"440901",label:"市辖区"},{value:"440902",label:"茂南区"},{value:"440904",label:"电白区"},{value:"440981",label:"高州市"},{value:"440982",label:"化州市"},{value:"440983",label:"信宜市"}]},{value:"441200",label:"肇庆市",children:[{value:"441201",label:"市辖区"},{value:"441202",label:"端州区"},{value:"441203",label:"鼎湖区"},{value:"441204",label:"高要区"},{value:"441223",label:"广宁县"},{value:"441224",label:"怀集县"},{value:"441225",label:"封开县"},{value:"441226",label:"德庆县"},{value:"441284",label:"四会市"}]},{value:"441300",label:"惠州市",children:[{value:"441301",label:"市辖区"},{value:"441302",label:"惠城区"},{value:"441303",label:"惠阳区"},{value:"441322",label:"博罗县"},{value:"441323",label:"惠东县"},{value:"441324",label:"龙门县"}]},{value:"441400",label:"梅州市",children:[{value:"441401",label:"市辖区"},{value:"441402",label:"梅江区"},{value:"441403",label:"梅县区"},{value:"441422",label:"大埔县"},{value:"441423",label:"丰顺县"},{value:"441424",label:"五华县"},{value:"441426",label:"平远县"},{value:"441427",label:"蕉岭县"},{value:"441481",label:"兴宁市"}]},{value:"441500",label:"汕尾市",children:[{value:"441501",label:"市辖区"},{value:"441502",label:"城区"},{value:"441521",label:"海丰县"},{value:"441523",label:"陆河县"},{value:"441581",label:"陆丰市"}]},{value:"441600",label:"河源市",children:[{value:"441601",label:"市辖区"},{value:"441602",label:"源城区"},{value:"441621",label:"紫金县"},{value:"441622",label:"龙川县"},{value:"441623",label:"连平县"},{value:"441624",label:"和平县"},{value:"441625",label:"东源县"}]},{value:"441700",label:"阳江市",children:[{value:"441701",label:"市辖区"},{value:"441702",label:"江城区"},{value:"441704",label:"阳东区"},{value:"441721",label:"阳西县"},{value:"441781",label:"阳春市"}]},{value:"441800",label:"清远市",children:[{value:"441801",label:"市辖区"},{value:"441802",label:"清城区"},{value:"441803",label:"清新区"},{value:"441821",label:"佛冈县"},{value:"441823",label:"阳山县"},{value:"441825",label:"连山壮族瑶族自治县"},{value:"441826",label:"连南瑶族自治县"},{value:"441881",label:"英德市"},{value:"441882",label:"连州市"}]},{value:"441900",label:"东莞市"},{value:"442000",label:"中山市"},{value:"445100",label:"潮州市",children:[{value:"445101",label:"市辖区"},{value:"445102",label:"湘桥区"},{value:"445103",label:"潮安区"},{value:"445122",label:"饶平县"}]},{value:"445200",label:"揭阳市",children:[{value:"445201",label:"市辖区"},{value:"445202",label:"榕城区"},{value:"445203",label:"揭东区"},{value:"445222",label:"揭西县"},{value:"445224",label:"惠来县"},{value:"445281",label:"普宁市"}]},{value:"445300",label:"云浮市",children:[{value:"445301",label:"市辖区"},{value:"445302",label:"云城区"},{value:"445303",label:"云安区"},{value:"445321",label:"新兴县"},{value:"445322",label:"郁南县"},{value:"445381",label:"罗定市"}]}]},{value:'450000',label:'广西壮族',children:[{value:"450100",label:"南宁市",children:[{value:"450101",label:"市辖区"},{value:"450102",label:"兴宁区"},{value:"450103",label:"青秀区"},{value:"450105",label:"江南区"},{value:"450107",label:"西乡塘区"},{value:"450108",label:"良庆区"},{value:"450109",label:"邕宁区"},{value:"450110",label:"武鸣区"},{value:"450123",label:"隆安县"},{value:"450124",label:"马山县"},{value:"450125",label:"上林县"},{value:"450126",label:"宾阳县"},{value:"450127",label:"横县"}]},{value:"450200",label:"柳州市",children:[{value:"450201",label:"市辖区"},{value:"450202",label:"城中区"},{value:"450203",label:"鱼峰区"},{value:"450204",label:"柳南区"},{value:"450205",label:"柳北区"},{value:"450206",label:"柳江区"},{value:"450222",label:"柳城县"},{value:"450223",label:"鹿寨县"},{value:"450224",label:"融安县"},{value:"450225",label:"融水苗族自治县"},{value:"450226",label:"三江侗族自治县"}]},{value:"450300",label:"桂林市",children:[{value:"450301",label:"市辖区"},{value:"450302",label:"秀峰区"},{value:"450303",label:"叠彩区"},{value:"450304",label:"象山区"},{value:"450305",label:"七星区"},{value:"450311",label:"雁山区"},{value:"450312",label:"临桂区"},{value:"450321",label:"阳朔县"},{value:"450323",label:"灵川县"},{value:"450324",label:"全州县"},{value:"450325",label:"兴安县"},{value:"450326",label:"永福县"},{value:"450327",label:"灌阳县"},{value:"450328",label:"龙胜各族自治县"},{value:"450329",label:"资源县"},{value:"450330",label:"平乐县"},{value:"450331",label:"荔浦县"},{value:"450332",label:"恭城瑶族自治县"}]},{value:"450400",label:"梧州市",children:[{value:"450401",label:"市辖区"},{value:"450403",label:"万秀区"},{value:"450405",label:"长洲区"},{value:"450406",label:"龙圩区"},{value:"450421",label:"苍梧县"},{value:"450422",label:"藤县"},{value:"450423",label:"蒙山县"},{value:"450481",label:"岑溪市"}]},{value:"450500",label:"北海市",children:[{value:"450501",label:"市辖区"},{value:"450502",label:"海城区"},{value:"450503",label:"银海区"},{value:"450512",label:"铁山港区"},{value:"450521",label:"合浦县"}]},{value:"450600",label:"防城港市",children:[{value:"450601",label:"市辖区"},{value:"450602",label:"港口区"},{value:"450603",label:"防城区"},{value:"450621",label:"上思县"},{value:"450681",label:"东兴市"}]},{value:"450700",label:"钦州市",children:[{value:"450701",label:"市辖区"},{value:"450702",label:"钦南区"},{value:"450703",label:"钦北区"},{value:"450721",label:"灵山县"},{value:"450722",label:"浦北县"}]},{value:"450800",label:"贵港市",children:[{value:"450801",label:"市辖区"},{value:"450802",label:"港北区"},{value:"450803",label:"港南区"},{value:"450804",label:"覃塘区"},{value:"450821",label:"平南县"},{value:"450881",label:"桂平市"}]},{value:"450900",label:"玉林市",children:[{value:"450901",label:"市辖区"},{value:"450902",label:"玉州区"},{value:"450903",label:"福绵区"},{value:"450921",label:"容县"},{value:"450922",label:"陆川县"},{value:"450923",label:"博白县"},{value:"450924",label:"兴业县"},{value:"450981",label:"北流市"}]},{value:"451000",label:"百色市",children:[{value:"451001",label:"市辖区"},{value:"451002",label:"右江区"},{value:"451021",label:"田阳县"},{value:"451022",label:"田东县"},{value:"451023",label:"平果县"},{value:"451024",label:"德保县"},{value:"451026",label:"那坡县"},{value:"451027",label:"凌云县"},{value:"451028",label:"乐业县"},{value:"451029",label:"田林县"},{value:"451030",label:"西林县"},{value:"451031",label:"隆林各族自治县"},{value:"451081",label:"靖西市"}]},{value:"451100",label:"贺州市",children:[{value:"451101",label:"市辖区"},{value:"451102",label:"八步区"},{value:"451103",label:"平桂区"},{value:"451121",label:"昭平县"},{value:"451122",label:"钟山县"},{value:"451123",label:"富川瑶族自治县"}]},{value:"451200",label:"河池市",children:[{value:"451201",label:"市辖区"},{value:"451202",label:"金城江区"},{value:"451203",label:"宜州区"},{value:"451221",label:"南丹县"},{value:"451222",label:"天峨县"},{value:"451223",label:"凤山县"},{value:"451224",label:"东兰县"},{value:"451225",label:"罗城仫佬族自治县"},{value:"451226",label:"环江毛南族自治县"},{value:"451227",label:"巴马瑶族自治县"},{value:"451228",label:"都安瑶族自治县"},{value:"451229",label:"大化瑶族自治县"}]},{value:"451300",label:"来宾市",children:[{value:"451301",label:"市辖区"},{value:"451302",label:"兴宾区"},{value:"451321",label:"忻城县"},{value:"451322",label:"象州县"},{value:"451323",label:"武宣县"},{value:"451324",label:"金秀瑶族自治县"},{value:"451381",label:"合山市"}]},{value:"451400",label:"崇左市",children:[{value:"451401",label:"市辖区"},{value:"451402",label:"江州区"},{value:"451421",label:"扶绥县"},{value:"451422",label:"宁明县"},{value:"451423",label:"龙州县"},{value:"451424",label:"大新县"},{value:"451425",label:"天等县"},{value:"451481",label:"凭祥市"}]}]},{value:'460000',label:'海南省',children:[{value:"460100",label:"海口市",children:[{value:"460101",label:"市辖区"},{value:"460105",label:"秀英区"},{value:"460106",label:"龙华区"},{value:"460107",label:"琼山区"},{value:"460108",label:"美兰区"}]},{value:"460200",label:"三亚市",children:[{value:"460201",label:"市辖区"},{value:"460202",label:"海棠区"},{value:"460203",label:"吉阳区"},{value:"460204",label:"天涯区"},{value:"460205",label:"崖州区"}]},{value:"460300",label:"三沙市",children:[{value:"460321",label:"西沙群岛"},{value:"460322",label:"南沙群岛"},{value:"460323",label:"中沙群岛的岛礁及其海域"}]},{value:"460400",label:"儋州市"},{value:"469000",label:"省直辖县级行政区划",children:[{value:"469001",label:"五指山市"},{value:"469002",label:"琼海市"},{value:"469005",label:"文昌市"},{value:"469006",label:"万宁市"},{value:"469007",label:"东方市"},{value:"469021",label:"定安县"},{value:"469022",label:"屯昌县"},{value:"469023",label:"澄迈县"},{value:"469024",label:"临高县"},{value:"469025",label:"白沙黎族自治县"},{value:"469026",label:"昌江黎族自治县"},{value:"469027",label:"乐东黎族自治县"},{value:"469028",label:"陵水黎族自治县"},{value:"469029",label:"保亭黎族苗族自治县"},{value:"469030",label:"琼中黎族苗族自治县"}]}]},{value:'500000',label:'重庆',children:[{value:"500100",label:"市辖区",children:[{value:"500101",label:"万州区"},{value:"500102",label:"涪陵区"},{value:"500103",label:"渝中区"},{value:"500104",label:"大渡口区"},{value:"500105",label:"江北区"},{value:"500106",label:"沙坪坝区"},{value:"500107",label:"九龙坡区"},{value:"500108",label:"南岸区"},{value:"500109",label:"北碚区"},{value:"500110",label:"綦江区"},{value:"500111",label:"大足区"},{value:"500112",label:"渝北区"},{value:"500113",label:"巴南区"},{value:"500114",label:"黔江区"},{value:"500115",label:"长寿区"},{value:"500116",label:"江津区"},{value:"500117",label:"合川区"},{value:"500118",label:"永川区"},{value:"500119",label:"南川区"},{value:"500120",label:"璧山区"},{value:"500151",label:"铜梁区"},{value:"500152",label:"潼南区"},{value:"500153",label:"荣昌区"},{value:"500154",label:"开州区"},{value:"500155",label:"梁平区"},{value:"500156",label:"武隆区"}]},{value:"500200",label:"县",children:[{value:"500229",label:"城口县"},{value:"500230",label:"丰都县"},{value:"500231",label:"垫江县"},{value:"500233",label:"忠县"},{value:"500235",label:"云阳县"},{value:"500236",label:"奉节县"},{value:"500237",label:"巫山县"},{value:"500238",label:"巫溪县"},{value:"500240",label:"石柱土家族自治县"},{value:"500241",label:"秀山土家族苗族自治县"},{value:"500242",label:"酉阳土家族苗族自治县"},{value:"500243",label:"彭水苗族土家族自治县"}]}]},{value:'510000',label:'四川省',children:[{value:"510100",label:"成都市",children:[{value:"510101",label:"市辖区"},{value:"510104",label:"锦江区"},{value:"510105",label:"青羊区"},{value:"510106",label:"金牛区"},{value:"510107",label:"武侯区"},{value:"510108",label:"成华区"},{value:"510112",label:"龙泉驿区"},{value:"510113",label:"青白江区"},{value:"510114",label:"新都区"},{value:"510115",label:"温江区"},{value:"510116",label:"双流区"},{value:"510117",label:"郫都区"},{value:"510121",label:"金堂县"},{value:"510129",label:"大邑县"},{value:"510131",label:"蒲江县"},{value:"510132",label:"新津县"},{value:"510181",label:"都江堰市"},{value:"510182",label:"彭州市"},{value:"510183",label:"邛崃市"},{value:"510184",label:"崇州市"},{value:"510185",label:"简阳市"}]},{value:"510300",label:"自贡市",children:[{value:"510301",label:"市辖区"},{value:"510302",label:"自流井区"},{value:"510303",label:"贡井区"},{value:"510304",label:"大安区"},{value:"510311",label:"沿滩区"},{value:"510321",label:"荣县"},{value:"510322",label:"富顺县"}]},{value:"510400",label:"攀枝花市",children:[{value:"510401",label:"市辖区"},{value:"510402",label:"东区"},{value:"510403",label:"西区"},{value:"510411",label:"仁和区"},{value:"510421",label:"米易县"},{value:"510422",label:"盐边县"}]},{value:"510500",label:"泸州市",children:[{value:"510501",label:"市辖区"},{value:"510502",label:"江阳区"},{value:"510503",label:"纳溪区"},{value:"510504",label:"龙马潭区"},{value:"510521",label:"泸县"},{value:"510522",label:"合江县"},{value:"510524",label:"叙永县"},{value:"510525",label:"古蔺县"}]},{value:"510600",label:"德阳市",children:[{value:"510601",label:"市辖区"},{value:"510603",label:"旌阳区"},{value:"510604",label:"罗江区"},{value:"510623",label:"中江县"},{value:"510681",label:"广汉市"},{value:"510682",label:"什邡市"},{value:"510683",label:"绵竹市"}]},{value:"510700",label:"绵阳市",children:[{value:"510701",label:"市辖区"},{value:"510703",label:"涪城区"},{value:"510704",label:"游仙区"},{value:"510705",label:"安州区"},{value:"510722",label:"三台县"},{value:"510723",label:"盐亭县"},{value:"510725",label:"梓潼县"},{value:"510726",label:"北川羌族自治县"},{value:"510727",label:"平武县"},{value:"510781",label:"江油市"}]},{value:"510800",label:"广元市",children:[{value:"510801",label:"市辖区"},{value:"510802",label:"利州区"},{value:"510811",label:"昭化区"},{value:"510812",label:"朝天区"},{value:"510821",label:"旺苍县"},{value:"510822",label:"青川县"},{value:"510823",label:"剑阁县"},{value:"510824",label:"苍溪县"}]},{value:"510900",label:"遂宁市",children:[{value:"510901",label:"市辖区"},{value:"510903",label:"船山区"},{value:"510904",label:"安居区"},{value:"510921",label:"蓬溪县"},{value:"510922",label:"射洪县"},{value:"510923",label:"大英县"}]},{value:"511000",label:"内江市",children:[{value:"511001",label:"市辖区"},{value:"511002",label:"市中区"},{value:"511011",label:"东兴区"},{value:"511024",label:"威远县"},{value:"511025",label:"资中县"},{value:"511071",label:"内江经济开发区"},{value:"511083",label:"隆昌市"}]},{value:"511100",label:"乐山市",children:[{value:"511101",label:"市辖区"},{value:"511102",label:"市中区"},{value:"511111",label:"沙湾区"},{value:"511112",label:"五通桥区"},{value:"511113",label:"金口河区"},{value:"511123",label:"犍为县"},{value:"511124",label:"井研县"},{value:"511126",label:"夹江县"},{value:"511129",label:"沐川县"},{value:"511132",label:"峨边彝族自治县"},{value:"511133",label:"马边彝族自治县"},{value:"511181",label:"峨眉山市"}]},{value:"511300",label:"南充市",children:[{value:"511301",label:"市辖区"},{value:"511302",label:"顺庆区"},{value:"511303",label:"高坪区"},{value:"511304",label:"嘉陵区"},{value:"511321",label:"南部县"},{value:"511322",label:"营山县"},{value:"511323",label:"蓬安县"},{value:"511324",label:"仪陇县"},{value:"511325",label:"西充县"},{value:"511381",label:"阆中市"}]},{value:"511400",label:"眉山市",children:[{value:"511401",label:"市辖区"},{value:"511402",label:"东坡区"},{value:"511403",label:"彭山区"},{value:"511421",label:"仁寿县"},{value:"511423",label:"洪雅县"},{value:"511424",label:"丹棱县"},{value:"511425",label:"青神县"}]},{value:"511500",label:"宜宾市",children:[{value:"511501",label:"市辖区"},{value:"511502",label:"翠屏区"},{value:"511503",label:"南溪区"},{value:"511521",label:"宜宾县"},{value:"511523",label:"江安县"},{value:"511524",label:"长宁县"},{value:"511525",label:"高县"},{value:"511526",label:"珙县"},{value:"511527",label:"筠连县"},{value:"511528",label:"兴文县"},{value:"511529",label:"屏山县"}]},{value:"511600",label:"广安市",children:[{value:"511601",label:"市辖区"},{value:"511602",label:"广安区"},{value:"511603",label:"前锋区"},{value:"511621",label:"岳池县"},{value:"511622",label:"武胜县"},{value:"511623",label:"邻水县"},{value:"511681",label:"华蓥市"}]},{value:"511700",label:"达州市",children:[{value:"511701",label:"市辖区"},{value:"511702",label:"通川区"},{value:"511703",label:"达川区"},{value:"511722",label:"宣汉县"},{value:"511723",label:"开江县"},{value:"511724",label:"大竹县"},{value:"511725",label:"渠县"},{value:"511771",label:"达州经济开发区"},{value:"511781",label:"万源市"}]},{value:"511800",label:"雅安市",children:[{value:"511801",label:"市辖区"},{value:"511802",label:"雨城区"},{value:"511803",label:"名山区"},{value:"511822",label:"荥经县"},{value:"511823",label:"汉源县"},{value:"511824",label:"石棉县"},{value:"511825",label:"天全县"},{value:"511826",label:"芦山县"},{value:"511827",label:"宝兴县"}]},{value:"511900",label:"巴中市",children:[{value:"511901",label:"市辖区"},{value:"511902",label:"巴州区"},{value:"511903",label:"恩阳区"},{value:"511921",label:"通江县"},{value:"511922",label:"南江县"},{value:"511923",label:"平昌县"},{value:"511971",label:"巴中经济开发区"}]},{value:"512000",label:"资阳市",children:[{value:"512001",label:"市辖区"},{value:"512002",label:"雁江区"},{value:"512021",label:"安岳县"},{value:"512022",label:"乐至县"}]},{value:"513200",label:"阿坝藏族羌族自治州",children:[{value:"513201",label:"马尔康市"},{value:"513221",label:"汶川县"},{value:"513222",label:"理县"},{value:"513223",label:"茂县"},{value:"513224",label:"松潘县"},{value:"513225",label:"九寨沟县"},{value:"513226",label:"金川县"},{value:"513227",label:"小金县"},{value:"513228",label:"黑水县"},{value:"513230",label:"壤塘县"},{value:"513231",label:"阿坝县"},{value:"513232",label:"若尔盖县"},{value:"513233",label:"红原县"}]},{value:"513300",label:"甘孜藏族自治州",children:[{value:"513301",label:"康定市"},{value:"513322",label:"泸定县"},{value:"513323",label:"丹巴县"},{value:"513324",label:"九龙县"},{value:"513325",label:"雅江县"},{value:"513326",label:"道孚县"},{value:"513327",label:"炉霍县"},{value:"513328",label:"甘孜县"},{value:"513329",label:"新龙县"},{value:"513330",label:"德格县"},{value:"513331",label:"白玉县"},{value:"513332",label:"石渠县"},{value:"513333",label:"色达县"},{value:"513334",label:"理塘县"},{value:"513335",label:"巴塘县"},{value:"513336",label:"乡城县"},{value:"513337",label:"稻城县"},{value:"513338",label:"得荣县"}]},{value:"513400",label:"凉山彝族自治州",children:[{value:"513401",label:"西昌市"},{value:"513422",label:"木里藏族自治县"},{value:"513423",label:"盐源县"},{value:"513424",label:"德昌县"},{value:"513425",label:"会理县"},{value:"513426",label:"会东县"},{value:"513427",label:"宁南县"},{value:"513428",label:"普格县"},{value:"513429",label:"布拖县"},{value:"513430",label:"金阳县"},{value:"513431",label:"昭觉县"},{value:"513432",label:"喜德县"},{value:"513433",label:"冕宁县"},{value:"513434",label:"越西县"},{value:"513435",label:"甘洛县"},{value:"513436",label:"美姑县"},{value:"513437",label:"雷波县"}]}]},{value:'520000',label:'贵州省',children:[{value:"520100",label:"贵阳市",children:[{value:"520101",label:"市辖区"},{value:"520102",label:"南明区"},{value:"520103",label:"云岩区"},{value:"520111",label:"花溪区"},{value:"520112",label:"乌当区"},{value:"520113",label:"白云区"},{value:"520115",label:"观山湖区"},{value:"520121",label:"开阳县"},{value:"520122",label:"息烽县"},{value:"520123",label:"修文县"},{value:"520181",label:"清镇市"}]},{value:"520200",label:"六盘水市",children:[{value:"520201",label:"钟山区"},{value:"520203",label:"六枝特区"},{value:"520221",label:"水城县"},{value:"520281",label:"盘州市"}]},{value:"520300",label:"遵义市",children:[{value:"520301",label:"市辖区"},{value:"520302",label:"红花岗区"},{value:"520303",label:"汇川区"},{value:"520304",label:"播州区"},{value:"520322",label:"桐梓县"},{value:"520323",label:"绥阳县"},{value:"520324",label:"正安县"},{value:"520325",label:"道真仡佬族苗族自治县"},{value:"520326",label:"务川仡佬族苗族自治县"},{value:"520327",label:"凤冈县"},{value:"520328",label:"湄潭县"},{value:"520329",label:"余庆县"},{value:"520330",label:"习水县"},{value:"520381",label:"赤水市"},{value:"520382",label:"仁怀市"}]},{value:"520400",label:"安顺市",children:[{value:"520401",label:"市辖区"},{value:"520402",label:"西秀区"},{value:"520403",label:"平坝区"},{value:"520422",label:"普定县"},{value:"520423",label:"镇宁布依族苗族自治县"},{value:"520424",label:"关岭布依族苗族自治县"},{value:"520425",label:"紫云苗族布依族自治县"}]},{value:"520500",label:"毕节市",children:[{value:"520501",label:"市辖区"},{value:"520502",label:"七星关区"},{value:"520521",label:"大方县"},{value:"520522",label:"黔西县"},{value:"520523",label:"金沙县"},{value:"520524",label:"织金县"},{value:"520525",label:"纳雍县"},{value:"520526",label:"威宁彝族回族苗族自治县"},{value:"520527",label:"赫章县"}]},{value:"520600",label:"铜仁市",children:[{value:"520601",label:"市辖区"},{value:"520602",label:"碧江区"},{value:"520603",label:"万山区"},{value:"520621",label:"江口县"},{value:"520622",label:"玉屏侗族自治县"},{value:"520623",label:"石阡县"},{value:"520624",label:"思南县"},{value:"520625",label:"印江土家族苗族自治县"},{value:"520626",label:"德江县"},{value:"520627",label:"沿河土家族自治县"},{value:"520628",label:"松桃苗族自治县"}]},{value:"522300",label:"黔西南布依族苗族自治州",children:[{value:"522301",label:"兴义市"},{value:"522322",label:"兴仁县"},{value:"522323",label:"普安县"},{value:"522324",label:"晴隆县"},{value:"522325",label:"贞丰县"},{value:"522326",label:"望谟县"},{value:"522327",label:"册亨县"},{value:"522328",label:"安龙县"}]},{value:"522600",label:"黔东南苗族侗族自治州",children:[{value:"522601",label:"凯里市"},{value:"522622",label:"黄平县"},{value:"522623",label:"施秉县"},{value:"522624",label:"三穗县"},{value:"522625",label:"镇远县"},{value:"522626",label:"岑巩县"},{value:"522627",label:"天柱县"},{value:"522628",label:"锦屏县"},{value:"522629",label:"剑河县"},{value:"522630",label:"台江县"},{value:"522631",label:"黎平县"},{value:"522632",label:"榕江县"},{value:"522633",label:"从江县"},{value:"522634",label:"雷山县"},{value:"522635",label:"麻江县"},{value:"522636",label:"丹寨县"}]},{value:"522700",label:"黔南布依族苗族自治州",children:[{value:"522701",label:"都匀市"},{value:"522702",label:"福泉市"},{value:"522722",label:"荔波县"},{value:"522723",label:"贵定县"},{value:"522725",label:"瓮安县"},{value:"522726",label:"独山县"},{value:"522727",label:"平塘县"},{value:"522728",label:"罗甸县"},{value:"522729",label:"长顺县"},{value:"522730",label:"龙里县"},{value:"522731",label:"惠水县"},{value:"522732",label:"三都水族自治县"}]}]},{value:'530000',label:'云南省',children:[{value:"530100",label:"昆明市",children:[{value:"530101",label:"市辖区"},{value:"530102",label:"五华区"},{value:"530103",label:"盘龙区"},{value:"530111",label:"官渡区"},{value:"530112",label:"西山区"},{value:"530113",label:"东川区"},{value:"530114",label:"呈贡区"},{value:"530115",label:"晋宁区"},{value:"530124",label:"富民县"},{value:"530125",label:"宜良县"},{value:"530126",label:"石林彝族自治县"},{value:"530127",label:"嵩明县"},{value:"530128",label:"禄劝彝族苗族自治县"},{value:"530129",label:"寻甸回族彝族自治县"},{value:"530181",label:"安宁市"}]},{value:"530300",label:"曲靖市",children:[{value:"530301",label:"市辖区"},{value:"530302",label:"麒麟区"},{value:"530303",label:"沾益区"},{value:"530321",label:"马龙县"},{value:"530322",label:"陆良县"},{value:"530323",label:"师宗县"},{value:"530324",label:"罗平县"},{value:"530325",label:"富源县"},{value:"530326",label:"会泽县"},{value:"530381",label:"宣威市"}]},{value:"530400",label:"玉溪市",children:[{value:"530401",label:"市辖区"},{value:"530402",label:"红塔区"},{value:"530403",label:"江川区"},{value:"530422",label:"澄江县"},{value:"530423",label:"通海县"},{value:"530424",label:"华宁县"},{value:"530425",label:"易门县"},{value:"530426",label:"峨山彝族自治县"},{value:"530427",label:"新平彝族傣族自治县"},{value:"530428",label:"元江哈尼族彝族傣族自治县"}]},{value:"530500",label:"保山市",children:[{value:"530501",label:"市辖区"},{value:"530502",label:"隆阳区"},{value:"530521",label:"施甸县"},{value:"530523",label:"龙陵县"},{value:"530524",label:"昌宁县"},{value:"530581",label:"腾冲市"}]},{value:"530600",label:"昭通市",children:[{value:"530601",label:"市辖区"},{value:"530602",label:"昭阳区"},{value:"530621",label:"鲁甸县"},{value:"530622",label:"巧家县"},{value:"530623",label:"盐津县"},{value:"530624",label:"大关县"},{value:"530625",label:"永善县"},{value:"530626",label:"绥江县"},{value:"530627",label:"镇雄县"},{value:"530628",label:"彝良县"},{value:"530629",label:"威信县"},{value:"530630",label:"水富县"}]},{value:"530700",label:"丽江市",children:[{value:"530701",label:"市辖区"},{value:"530702",label:"古城区"},{value:"530721",label:"玉龙纳西族自治县"},{value:"530722",label:"永胜县"},{value:"530723",label:"华坪县"},{value:"530724",label:"宁蒗彝族自治县"}]},{value:"530800",label:"普洱市",children:[{value:"530801",label:"市辖区"},{value:"530802",label:"思茅区"},{value:"530821",label:"宁洱哈尼族彝族自治县"},{value:"530822",label:"墨江哈尼族自治县"},{value:"530823",label:"景东彝族自治县"},{value:"530824",label:"景谷傣族彝族自治县"},{value:"530825",label:"镇沅彝族哈尼族拉祜族自治县"},{value:"530826",label:"江城哈尼族彝族自治县"},{value:"530827",label:"孟连傣族拉祜族佤族自治县"},{value:"530828",label:"澜沧拉祜族自治县"},{value:"530829",label:"西盟佤族自治县"}]},{value:"530900",label:"临沧市",children:[{value:"530901",label:"市辖区"},{value:"530902",label:"临翔区"},{value:"530921",label:"凤庆县"},{value:"530922",label:"云县"},{value:"530923",label:"永德县"},{value:"530924",label:"镇康县"},{value:"530925",label:"双江拉祜族佤族布朗族傣族自治县"},{value:"530926",label:"耿马傣族佤族自治县"},{value:"530927",label:"沧源佤族自治县"}]},{value:"532300",label:"楚雄彝族自治州",children:[{value:"532301",label:"楚雄市"},{value:"532322",label:"双柏县"},{value:"532323",label:"牟定县"},{value:"532324",label:"南华县"},{value:"532325",label:"姚安县"},{value:"532326",label:"大姚县"},{value:"532327",label:"永仁县"},{value:"532328",label:"元谋县"},{value:"532329",label:"武定县"},{value:"532331",label:"禄丰县"}]},{value:"532500",label:"红河哈尼族彝族自治州",children:[{value:"532501",label:"个旧市"},{value:"532502",label:"开远市"},{value:"532503",label:"蒙自市"},{value:"532504",label:"弥勒市"},{value:"532523",label:"屏边苗族自治县"},{value:"532524",label:"建水县"},{value:"532525",label:"石屏县"},{value:"532527",label:"泸西县"},{value:"532528",label:"元阳县"},{value:"532529",label:"红河县"},{value:"532530",label:"金平苗族瑶族傣族自治县"},{value:"532531",label:"绿春县"},{value:"532532",label:"河口瑶族自治县"}]},{value:"532600",label:"文山壮族苗族自治州",children:[{value:"532601",label:"文山市"},{value:"532622",label:"砚山县"},{value:"532623",label:"西畴县"},{value:"532624",label:"麻栗坡县"},{value:"532625",label:"马关县"},{value:"532626",label:"丘北县"},{value:"532627",label:"广南县"},{value:"532628",label:"富宁县"}]},{value:"532800",label:"西双版纳傣族自治州",children:[{value:"532801",label:"景洪市"},{value:"532822",label:"勐海县"},{value:"532823",label:"勐腊县"}]},{value:"532900",label:"大理白族自治州",children:[{value:"532901",label:"大理市"},{value:"532922",label:"漾濞彝族自治县"},{value:"532923",label:"祥云县"},{value:"532924",label:"宾川县"},{value:"532925",label:"弥渡县"},{value:"532926",label:"南涧彝族自治县"},{value:"532927",label:"巍山彝族回族自治县"},{value:"532928",label:"永平县"},{value:"532929",label:"云龙县"},{value:"532930",label:"洱源县"},{value:"532931",label:"剑川县"},{value:"532932",label:"鹤庆县"}]},{value:"533100",label:"德宏傣族景颇族自治州",children:[{value:"533102",label:"瑞丽市"},{value:"533103",label:"芒市"},{value:"533122",label:"梁河县"},{value:"533123",label:"盈江县"},{value:"533124",label:"陇川县"}]},{value:"533300",label:"怒江傈僳族自治州",children:[{value:"533301",label:"泸水市"},{value:"533323",label:"福贡县"},{value:"533324",label:"贡山独龙族怒族自治县"},{value:"533325",label:"兰坪白族普米族自治县"}]},{value:"533400",label:"迪庆藏族自治州",children:[{value:"533401",label:"香格里拉市"},{value:"533422",label:"德钦县"},{value:"533423",label:"维西傈僳族自治县"}]}]},{value:'540000',label:'西藏',children:[{value:"540100",label:"拉萨市",children:[{value:"540101",label:"市辖区"},{value:"540102",label:"城关区"},{value:"540103",label:"堆龙德庆区"},{value:"540121",label:"林周县"},{value:"540122",label:"当雄县"},{value:"540123",label:"尼木县"},{value:"540124",label:"曲水县"},{value:"540126",label:"达孜县"},{value:"540127",label:"墨竹工卡县"},{value:"540171",label:"格尔木藏青工业园区"},{value:"540172",label:"拉萨经济技术开发区"},{value:"540173",label:"西藏文化旅游创意园区"},{value:"540174",label:"达孜工业园区"}]},{value:"540200",label:"日喀则市",children:[{value:"540202",label:"桑珠孜区"},{value:"540221",label:"南木林县"},{value:"540222",label:"江孜县"},{value:"540223",label:"定日县"},{value:"540224",label:"萨迦县"},{value:"540225",label:"拉孜县"},{value:"540226",label:"昂仁县"},{value:"540227",label:"谢通门县"},{value:"540228",label:"白朗县"},{value:"540229",label:"仁布县"},{value:"540230",label:"康马县"},{value:"540231",label:"定结县"},{value:"540232",label:"仲巴县"},{value:"540233",label:"亚东县"},{value:"540234",label:"吉隆县"},{value:"540235",label:"聂拉木县"},{value:"540236",label:"萨嘎县"},{value:"540237",label:"岗巴县"}]},{value:"540300",label:"昌都市",children:[{value:"540302",label:"卡若区"},{value:"540321",label:"江达县"},{value:"540322",label:"贡觉县"},{value:"540323",label:"类乌齐县"},{value:"540324",label:"丁青县"},{value:"540325",label:"察雅县"},{value:"540326",label:"八宿县"},{value:"540327",label:"左贡县"},{value:"540328",label:"芒康县"},{value:"540329",label:"洛隆县"},{value:"540330",label:"边坝县"}]},{value:"540400",label:"林芝市",children:[{value:"540402",label:"巴宜区"},{value:"540421",label:"工布江达县"},{value:"540422",label:"米林县"},{value:"540423",label:"墨脱县"},{value:"540424",label:"波密县"},{value:"540425",label:"察隅县"},{value:"540426",label:"朗县"}]},{value:"540500",label:"山南市",children:[{value:"540501",label:"市辖区"},{value:"540502",label:"乃东区"},{value:"540521",label:"扎囊县"},{value:"540522",label:"贡嘎县"},{value:"540523",label:"桑日县"},{value:"540524",label:"琼结县"},{value:"540525",label:"曲松县"},{value:"540526",label:"措美县"},{value:"540527",label:"洛扎县"},{value:"540528",label:"加查县"},{value:"540529",label:"隆子县"},{value:"540530",label:"错那县"},{value:"540531",label:"浪卡子县"}]},{value:"542400",label:"那曲地区",children:[{value:"542421",label:"那曲县"},{value:"542422",label:"嘉黎县"},{value:"542423",label:"比如县"},{value:"542424",label:"聂荣县"},{value:"542425",label:"安多县"},{value:"542426",label:"申扎县"},{value:"542427",label:"索县"},{value:"542428",label:"班戈县"},{value:"542429",label:"巴青县"},{value:"542430",label:"尼玛县"},{value:"542431",label:"双湖县"}]},{value:"542500",label:"阿里地区",children:[{value:"542521",label:"普兰县"},{value:"542522",label:"札达县"},{value:"542523",label:"噶尔县"},{value:"542524",label:"日土县"},{value:"542525",label:"革吉县"},{value:"542526",label:"改则县"},{value:"542527",label:"措勤县"}]}]},{value:'610000',label:'陕西省',children:[{value:"610100",label:"西安市",children:[{value:"610101",label:"市辖区"},{value:"610102",label:"新城区"},{value:"610103",label:"碑林区"},{value:"610104",label:"莲湖区"},{value:"610111",label:"灞桥区"},{value:"610112",label:"未央区"},{value:"610113",label:"雁塔区"},{value:"610114",label:"阎良区"},{value:"610115",label:"临潼区"},{value:"610116",label:"长安区"},{value:"610117",label:"高陵区"},{value:"610118",label:"鄠邑区"},{value:"610122",label:"蓝田县"},{value:"610124",label:"周至县"}]},{value:"610200",label:"铜川市",children:[{value:"610201",label:"市辖区"},{value:"610202",label:"王益区"},{value:"610203",label:"印台区"},{value:"610204",label:"耀州区"},{value:"610222",label:"宜君县"}]},{value:"610300",label:"宝鸡市",children:[{value:"610301",label:"市辖区"},{value:"610302",label:"渭滨区"},{value:"610303",label:"金台区"},{value:"610304",label:"陈仓区"},{value:"610322",label:"凤翔县"},{value:"610323",label:"岐山县"},{value:"610324",label:"扶风县"},{value:"610326",label:"眉县"},{value:"610327",label:"陇县"},{value:"610328",label:"千阳县"},{value:"610329",label:"麟游县"},{value:"610330",label:"凤县"},{value:"610331",label:"太白县"}]},{value:"610400",label:"咸阳市",children:[{value:"610401",label:"市辖区"},{value:"610402",label:"秦都区"},{value:"610403",label:"杨陵区"},{value:"610404",label:"渭城区"},{value:"610422",label:"三原县"},{value:"610423",label:"泾阳县"},{value:"610424",label:"乾县"},{value:"610425",label:"礼泉县"},{value:"610426",label:"永寿县"},{value:"610427",label:"彬县"},{value:"610428",label:"长武县"},{value:"610429",label:"旬邑县"},{value:"610430",label:"淳化县"},{value:"610431",label:"武功县"},{value:"610481",label:"兴平市"}]},{value:"610500",label:"渭南市",children:[{value:"610501",label:"市辖区"},{value:"610502",label:"临渭区"},{value:"610503",label:"华州区"},{value:"610522",label:"潼关县"},{value:"610523",label:"大荔县"},{value:"610524",label:"合阳县"},{value:"610525",label:"澄城县"},{value:"610526",label:"蒲城县"},{value:"610527",label:"白水县"},{value:"610528",label:"富平县"},{value:"610581",label:"韩城市"},{value:"610582",label:"华阴市"}]},{value:"610600",label:"延安市",children:[{value:"610601",label:"市辖区"},{value:"610602",label:"宝塔区"},{value:"610603",label:"安塞区"},{value:"610621",label:"延长县"},{value:"610622",label:"延川县"},{value:"610623",label:"子长县"},{value:"610625",label:"志丹县"},{value:"610626",label:"吴起县"},{value:"610627",label:"甘泉县"},{value:"610628",label:"富县"},{value:"610629",label:"洛川县"},{value:"610630",label:"宜川县"},{value:"610631",label:"黄龙县"},{value:"610632",label:"黄陵县"}]},{value:"610700",label:"汉中市",children:[{value:"610701",label:"市辖区"},{value:"610702",label:"汉台区"},{value:"610703",label:"南郑区"},{value:"610722",label:"城固县"},{value:"610723",label:"洋县"},{value:"610724",label:"西乡县"},{value:"610725",label:"勉县"},{value:"610726",label:"宁强县"},{value:"610727",label:"略阳县"},{value:"610728",label:"镇巴县"},{value:"610729",label:"留坝县"},{value:"610730",label:"佛坪县"}]},{value:"610800",label:"榆林市",children:[{value:"610801",label:"市辖区"},{value:"610802",label:"榆阳区"},{value:"610803",label:"横山区"},{value:"610822",label:"府谷县"},{value:"610824",label:"靖边县"},{value:"610825",label:"定边县"},{value:"610826",label:"绥德县"},{value:"610827",label:"米脂县"},{value:"610828",label:"佳县"},{value:"610829",label:"吴堡县"},{value:"610830",label:"清涧县"},{value:"610831",label:"子洲县"},{value:"610881",label:"神木市"}]},{value:"610900",label:"安康市",children:[{value:"610901",label:"市辖区"},{value:"610902",label:"汉滨区"},{value:"610921",label:"汉阴县"},{value:"610922",label:"石泉县"},{value:"610923",label:"宁陕县"},{value:"610924",label:"紫阳县"},{value:"610925",label:"岚皋县"},{value:"610926",label:"平利县"},{value:"610927",label:"镇坪县"},{value:"610928",label:"旬阳县"},{value:"610929",label:"白河县"}]},{value:"611000",label:"商洛市",children:[{value:"611001",label:"市辖区"},{value:"611002",label:"商州区"},{value:"611021",label:"洛南县"},{value:"611022",label:"丹凤县"},{value:"611023",label:"商南县"},{value:"611024",label:"山阳县"},{value:"611025",label:"镇安县"},{value:"611026",label:"柞水县"}]}]},{value:'620000',label:'甘肃省',children:[{value:"620100",label:"兰州市",children:[{value:"620101",label:"市辖区"},{value:"620102",label:"城关区"},{value:"620103",label:"七里河区"},{value:"620104",label:"西固区"},{value:"620105",label:"安宁区"},{value:"620111",label:"红古区"},{value:"620121",label:"永登县"},{value:"620122",label:"皋兰县"},{value:"620123",label:"榆中县"},{value:"620171",label:"兰州新区"}]},{value:"620200",label:"嘉峪关市",children:[{value:"620201",label:"市辖区"}]},{value:"620300",label:"金昌市",children:[{value:"620301",label:"市辖区"},{value:"620302",label:"金川区"},{value:"620321",label:"永昌县"}]},{value:"620400",label:"白银市",children:[{value:"620401",label:"市辖区"},{value:"620402",label:"白银区"},{value:"620403",label:"平川区"},{value:"620421",label:"靖远县"},{value:"620422",label:"会宁县"},{value:"620423",label:"景泰县"}]},{value:"620500",label:"天水市",children:[{value:"620501",label:"市辖区"},{value:"620502",label:"秦州区"},{value:"620503",label:"麦积区"},{value:"620521",label:"清水县"},{value:"620522",label:"秦安县"},{value:"620523",label:"甘谷县"},{value:"620524",label:"武山县"},{value:"620525",label:"张家川回族自治县"}]},{value:"620600",label:"武威市",children:[{value:"620601",label:"市辖区"},{value:"620602",label:"凉州区"},{value:"620621",label:"民勤县"},{value:"620622",label:"古浪县"},{value:"620623",label:"天祝藏族自治县"}]},{value:"620700",label:"张掖市",children:[{value:"620701",label:"市辖区"},{value:"620702",label:"甘州区"},{value:"620721",label:"肃南裕固族自治县"},{value:"620722",label:"民乐县"},{value:"620723",label:"临泽县"},{value:"620724",label:"高台县"},{value:"620725",label:"山丹县"}]},{value:"620800",label:"平凉市",children:[{value:"620801",label:"市辖区"},{value:"620802",label:"崆峒区"},{value:"620821",label:"泾川县"},{value:"620822",label:"灵台县"},{value:"620823",label:"崇信县"},{value:"620824",label:"华亭县"},{value:"620825",label:"庄浪县"},{value:"620826",label:"静宁县"},{value:"620871",label:"平凉工业园区"}]},{value:"620900",label:"酒泉市",children:[{value:"620901",label:"市辖区"},{value:"620902",label:"肃州区"},{value:"620921",label:"金塔县"},{value:"620922",label:"瓜州县"},{value:"620923",label:"肃北蒙古族自治县"},{value:"620924",label:"阿克塞哈萨克族自治县"},{value:"620981",label:"玉门市"},{value:"620982",label:"敦煌市"}]},{value:"621000",label:"庆阳市",children:[{value:"621001",label:"市辖区"},{value:"621002",label:"西峰区"},{value:"621021",label:"庆城县"},{value:"621022",label:"环县"},{value:"621023",label:"华池县"},{value:"621024",label:"合水县"},{value:"621025",label:"正宁县"},{value:"621026",label:"宁县"},{value:"621027",label:"镇原县"}]},{value:"621100",label:"定西市",children:[{value:"621101",label:"市辖区"},{value:"621102",label:"安定区"},{value:"621121",label:"通渭县"},{value:"621122",label:"陇西县"},{value:"621123",label:"渭源县"},{value:"621124",label:"临洮县"},{value:"621125",label:"漳县"},{value:"621126",label:"岷县"}]},{value:"621200",label:"陇南市",children:[{value:"621201",label:"市辖区"},{value:"621202",label:"武都区"},{value:"621221",label:"成县"},{value:"621222",label:"文县"},{value:"621223",label:"宕昌县"},{value:"621224",label:"康县"},{value:"621225",label:"西和县"},{value:"621226",label:"礼县"},{value:"621227",label:"徽县"},{value:"621228",label:"两当县"}]},{value:"622900",label:"临夏回族自治州",children:[{value:"622901",label:"临夏市"},{value:"622921",label:"临夏县"},{value:"622922",label:"康乐县"},{value:"622923",label:"永靖县"},{value:"622924",label:"广河县"},{value:"622925",label:"和政县"},{value:"622926",label:"东乡族自治县"},{value:"622927",label:"积石山保安族东乡族撒拉族自治县"}]},{value:"623000",label:"甘南藏族自治州",children:[{value:"623001",label:"合作市"},{value:"623021",label:"临潭县"},{value:"623022",label:"卓尼县"},{value:"623023",label:"舟曲县"},{value:"623024",label:"迭部县"},{value:"623025",label:"玛曲县"},{value:"623026",label:"碌曲县"},{value:"623027",label:"夏河县"}]}]},{value:'630000',label:'青海省',children:[{value:"630100",label:"西宁市",children:[{value:"630101",label:"市辖区"},{value:"630102",label:"城东区"},{value:"630103",label:"城中区"},{value:"630104",label:"城西区"},{value:"630105",label:"城北区"},{value:"630121",label:"大通回族土族自治县"},{value:"630122",label:"湟中县"},{value:"630123",label:"湟源县"}]},{value:"630200",label:"海东市",children:[{value:"630202",label:"乐都区"},{value:"630203",label:"平安区"},{value:"630222",label:"民和回族土族自治县"},{value:"630223",label:"互助土族自治县"},{value:"630224",label:"化隆回族自治县"},{value:"630225",label:"循化撒拉族自治县"}]},{value:"632200",label:"海北藏族自治州",children:[{value:"632221",label:"门源回族自治县"},{value:"632222",label:"祁连县"},{value:"632223",label:"海晏县"},{value:"632224",label:"刚察县"}]},{value:"632300",label:"黄南藏族自治州",children:[{value:"632321",label:"同仁县"},{value:"632322",label:"尖扎县"},{value:"632323",label:"泽库县"},{value:"632324",label:"河南蒙古族自治县"}]},{value:"632500",label:"海南藏族自治州",children:[{value:"632521",label:"共和县"},{value:"632522",label:"同德县"},{value:"632523",label:"贵德县"},{value:"632524",label:"兴海县"},{value:"632525",label:"贵南县"}]},{value:"632600",label:"果洛藏族自治州",children:[{value:"632621",label:"玛沁县"},{value:"632622",label:"班玛县"},{value:"632623",label:"甘德县"},{value:"632624",label:"达日县"},{value:"632625",label:"久治县"},{value:"632626",label:"玛多县"}]},{value:"632700",label:"玉树藏族自治州",children:[{value:"632701",label:"玉树市"},{value:"632722",label:"杂多县"},{value:"632723",label:"称多县"},{value:"632724",label:"治多县"},{value:"632725",label:"囊谦县"},{value:"632726",label:"曲麻莱县"}]},{value:"632800",label:"海西蒙古族藏族自治州",children:[{value:"632801",label:"格尔木市"},{value:"632802",label:"德令哈市"},{value:"632821",label:"乌兰县"},{value:"632822",label:"都兰县"},{value:"632823",label:"天峻县"},{value:"632857",label:"大柴旦行政委员会"},{value:"632858",label:"冷湖行政委员会"},{value:"632859",label:"茫崖行政委员会"}]}]},{value:'640000',label:'宁夏',children:[{value:"640100",label:"银川市",children:[{value:"640101",label:"市辖区"},{value:"640104",label:"兴庆区"},{value:"640105",label:"西夏区"},{value:"640106",label:"金凤区"},{value:"640121",label:"永宁县"},{value:"640122",label:"贺兰县"},{value:"640181",label:"灵武市"}]},{value:"640200",label:"石嘴山市",children:[{value:"640201",label:"市辖区"},{value:"640202",label:"大武口区"},{value:"640205",label:"惠农区"},{value:"640221",label:"平罗县"}]},{value:"640300",label:"吴忠市",children:[{value:"640301",label:"市辖区"},{value:"640302",label:"利通区"},{value:"640303",label:"红寺堡区"},{value:"640323",label:"盐池县"},{value:"640324",label:"同心县"},{value:"640381",label:"青铜峡市"}]},{value:"640400",label:"固原市",children:[{value:"640401",label:"市辖区"},{value:"640402",label:"原州区"},{value:"640422",label:"西吉县"},{value:"640423",label:"隆德县"},{value:"640424",label:"泾源县"},{value:"640425",label:"彭阳县"}]},{value:"640500",label:"中卫市",children:[{value:"640501",label:"市辖区"},{value:"640502",label:"沙坡头区"},{value:"640521",label:"中宁县"},{value:"640522",label:"海原县"}]}]},{value:'650000',label:'新疆',children:[{value:"650100",label:"乌鲁木齐市",children:[{value:"650101",label:"市辖区"},{value:"650102",label:"天山区"},{value:"650103",label:"沙依巴克区"},{value:"650104",label:"新市区"},{value:"650105",label:"水磨沟区"},{value:"650106",label:"头屯河区"},{value:"650107",label:"达坂城区"},{value:"650109",label:"米东区"},{value:"650121",label:"乌鲁木齐县"},{value:"650171",label:"乌鲁木齐经济技术开发区"},{value:"650172",label:"乌鲁木齐高新技术产业开发区"}]},{value:"650200",label:"克拉玛依市",children:[{value:"650201",label:"市辖区"},{value:"650202",label:"独山子区"},{value:"650203",label:"克拉玛依区"},{value:"650204",label:"白碱滩区"},{value:"650205",label:"乌尔禾区"}]},{value:"650400",label:"吐鲁番市",children:[{value:"650402",label:"高昌区"},{value:"650421",label:"鄯善县"},{value:"650422",label:"托克逊县"}]},{value:"650500",label:"哈密市",children:[{value:"650502",label:"伊州区"},{value:"650521",label:"巴里坤哈萨克自治县"},{value:"650522",label:"伊吾县"}]},{value:"652300",label:"昌吉回族自治州",children:[{value:"652301",label:"昌吉市"},{value:"652302",label:"阜康市"},{value:"652323",label:"呼图壁县"},{value:"652324",label:"玛纳斯县"},{value:"652325",label:"奇台县"},{value:"652327",label:"吉木萨尔县"},{value:"652328",label:"木垒哈萨克自治县"}]},{value:"652700",label:"博尔塔拉蒙古自治州",children:[{value:"652701",label:"博乐市"},{value:"652702",label:"阿拉山口市"},{value:"652722",label:"精河县"},{value:"652723",label:"温泉县"}]},{value:"652800",label:"巴音郭楞蒙古自治州",children:[{value:"652801",label:"库尔勒市"},{value:"652822",label:"轮台县"},{value:"652823",label:"尉犁县"},{value:"652824",label:"若羌县"},{value:"652825",label:"且末县"},{value:"652826",label:"焉耆回族自治县"},{value:"652827",label:"和静县"},{value:"652828",label:"和硕县"},{value:"652829",label:"博湖县"},{value:"652871",label:"库尔勒经济技术开发区"}]},{value:"652900",label:"阿克苏地区",children:[{value:"652901",label:"阿克苏市"},{value:"652922",label:"温宿县"},{value:"652923",label:"库车县"},{value:"652924",label:"沙雅县"},{value:"652925",label:"新和县"},{value:"652926",label:"拜城县"},{value:"652927",label:"乌什县"},{value:"652928",label:"阿瓦提县"},{value:"652929",label:"柯坪县"}]},{value:"653000",label:"克孜勒苏柯尔克孜自治州",children:[{value:"653001",label:"阿图什市"},{value:"653022",label:"阿克陶县"},{value:"653023",label:"阿合奇县"},{value:"653024",label:"乌恰县"}]},{value:"653100",label:"喀什地区",children:[{value:"653101",label:"喀什市"},{value:"653121",label:"疏附县"},{value:"653122",label:"疏勒县"},{value:"653123",label:"英吉沙县"},{value:"653124",label:"泽普县"},{value:"653125",label:"莎车县"},{value:"653126",label:"叶城县"},{value:"653127",label:"麦盖提县"},{value:"653128",label:"岳普湖县"},{value:"653129",label:"伽师县"},{value:"653130",label:"巴楚县"},{value:"653131",label:"塔什库尔干塔吉克自治县"}]},{value:"653200",label:"和田地区",children:[{value:"653201",label:"和田市"},{value:"653221",label:"和田县"},{value:"653222",label:"墨玉县"},{value:"653223",label:"皮山县"},{value:"653224",label:"洛浦县"},{value:"653225",label:"策勒县"},{value:"653226",label:"于田县"},{value:"653227",label:"民丰县"}]},{value:"654000",label:"伊犁哈萨克自治州",children:[{value:"654002",label:"伊宁市"},{value:"654003",label:"奎屯市"},{value:"654004",label:"霍尔果斯市"},{value:"654021",label:"伊宁县"},{value:"654022",label:"察布查尔锡伯自治县"},{value:"654023",label:"霍城县"},{value:"654024",label:"巩留县"},{value:"654025",label:"新源县"},{value:"654026",label:"昭苏县"},{value:"654027",label:"特克斯县"},{value:"654028",label:"尼勒克县"}]},{value:"654200",label:"塔城地区",children:[{value:"654201",label:"塔城市"},{value:"654202",label:"乌苏市"},{value:"654221",label:"额敏县"},{value:"654223",label:"沙湾县"},{value:"654224",label:"托里县"},{value:"654225",label:"裕民县"},{value:"654226",label:"和布克赛尔蒙古自治县"}]},{value:"654300",label:"阿勒泰地区",children:[{value:"654301",label:"阿勒泰市"},{value:"654321",label:"布尔津县"},{value:"654322",label:"富蕴县"},{value:"654323",label:"福海县"},{value:"654324",label:"哈巴河县"},{value:"654325",label:"青河县"},{value:"654326",label:"吉木乃县"}]},{value:"659000",label:"自治区直辖县级行政区划",children:[{value:"659001",label:"石河子市"},{value:"659002",label:"阿拉尔市"},{value:"659003",label:"图木舒克市"},{value:"659004",label:"五家渠市"},{value:"659006",label:"铁门关市"}]}]},{value:'660000',label:'台湾省',children:[{value:"660100",label:"台北市",children:[{value:"660101",label:"中正区"},{value:"660102",label:"大同区"},{value:"660103",label:"中山区"},{value:"660104",label:"松山区"},{value:"660105",label:"大安区"},{value:"660106",label:"万华区"},{value:"660107",label:"信义区"},{value:"660108",label:"士林区"},{value:"660109",label:"北投区"},{value:"660110",label:"内湖区"},{value:"660111",label:"南港区"},{value:"660112",label:"文山区"}]},{value:"660200",label:"高雄市",children:[{value:"660201",label:"新兴区"},{value:"660202",label:"前金区"},{value:"660203",label:"芩雅区"},{value:"660204",label:"盐埕区"},{value:"660205",label:"鼓山区"},{value:"660206",label:"旗津区"},{value:"660207",label:"前镇区"},{value:"660208",label:"三民区"},{value:"660209",label:"左营区"},{value:"660210",label:"楠梓区"},{value:"660211",label:"小港区"}]},{value:"660300",label:"台南市",children:[{value:"660301",label:"中西区"},{value:"660302",label:"东区"},{value:"660303",label:"南区"},{value:"660304",label:"北区"},{value:"660305",label:"安平区"},{value:"660306",label:"安南区"}]},{value:"660400",label:"台中市",children:[{value:"660401",label:"中区"},{value:"660402",label:"东区"},{value:"660403",label:"南区"},{value:"660404",label:"西区"},{value:"660405",label:"北区"},{value:"660406",label:"北屯区"},{value:"660407",label:"西屯区"},{value:"660408",label:"南屯区"}]},{value:"660500",label:"金门县",children:[{value:"660501",label:"金门县"}]},{value:"660600",label:"南投县",children:[{value:"660601",label:"南投县",}]},{value:"660700",label:"基隆市",children:[{value:"660701",label:"仁爱区"},{value:"660702",label:"信义区"},{value:"660703",label:"中正区"},{value:"660704",label:"中山区"},{value:"660705",label:"安乐区"},{value:"660706",label:"暖暖区"},{value:"660707",label:"七堵区"}]},{value:"660800",label:"新竹市",children:[{value:"660801",label:"东区"},{value:"660802",label:"北区"},{value:"660803",label:"香山区"}]},{value:"660900",label:"嘉义市",children:[{value:"660901",label:"东区"},{value:"660902",label:"西区"}]},{value:"661000",label:"新北市",children:[{value:"661001",label:"新北市"}]},{value:"661100",label:"宜兰县",children:[{value:"661100",label:"宜兰县"}]},{value:"661200",label:"新竹县",children:[{value:"661201",label:"新竹县"}]},{value:"661300",label:"桃园县",children:[{value:"661301",label:"桃园县"}]},{value:"661400",label:"苗栗县",children:[{value:"661401",label:"苗栗县"}]},{value:"661500",label:"彰化县",children:[{value:"661501",label:"彰化县"}]},{value:"661600",label:"嘉义县",children:[{value:"661601",label:"嘉义县"}]},{value:"661700",label:"云林县",children:[{value:"661701",label:"云林县"}]},{value:"661800",label:"屏东县",children:[{value:"661801",label:"屏东县"}]},{value:"661900",label:"台东县",children:[{value:"661901",label:"台东县"}]},{value:"662000",label:"花莲县",children:[{value:"662001",label:"花莲县"}]},{value:"662100",label:"澎湖县",children:[{value:"662101",label:"澎湖县"}]}]},{value:'670000',label:'香港',children:[{value:"670100",label:"香港岛",children:[{value:"670101",label:"中西区"},{value:"670102",label:"湾仔区"},{value:"670103",label:"东区"},{value:"670104",label:"南区"}]},{value:"670200",label:"九龙半岛",children:[{value:"670201",label:"九龙城区"},{value:"670202",label:"油尖旺区"},{value:"670203",label:"深水埗区"},{value:"670204",label:"黄大仙区"},{value:"670205",label:"观塘区"}]},{value:"670300",label:"新界",children:[{value:"670301",label:"北区"},{value:"670302",label:"大埔区"},{value:"670303",label:"沙田区"},{value:"670304",label:"西贡区"},{value:"670305",label:"元朗区"},{value:"670306",label:"屯门区"},{value:"670307",label:"荃湾区"},{value:"670308",label:"葵青区"},{value:"670309",label:"离岛区"}]}]},{value:'680000',label:'澳门',children:[{value:"680100",label:"澳门半岛",children:[{value:"680101",label:"花地玛堂区"},{value:"680102",label:"圣安多尼堂区"},{value:"680103",label:"大堂区"},{value:"680104",label:"望德堂区"},{value:"680105",label:"风顺堂区"}]},{value:"680200",label:"离岛",children:[{value:"680201",label:"嘉模堂区"},{value:"680202",label:"圣方济各堂区"}]}]}];export default cityData \ No newline at end of file diff --git a/yudao-ui-app/components/w-picker/date-picker.vue b/yudao-ui-app/components/w-picker/date-picker.vue deleted file mode 100644 index c0154d57d..000000000 --- a/yudao-ui-app/components/w-picker/date-picker.vue +++ /dev/null @@ -1,742 +0,0 @@ - - - - - diff --git a/yudao-ui-app/components/w-picker/half-picker.vue b/yudao-ui-app/components/w-picker/half-picker.vue deleted file mode 100644 index 0fdfb3355..000000000 --- a/yudao-ui-app/components/w-picker/half-picker.vue +++ /dev/null @@ -1,345 +0,0 @@ - - - - - diff --git a/yudao-ui-app/components/w-picker/linkage-picker.vue b/yudao-ui-app/components/w-picker/linkage-picker.vue deleted file mode 100644 index 290422d9a..000000000 --- a/yudao-ui-app/components/w-picker/linkage-picker.vue +++ /dev/null @@ -1,274 +0,0 @@ - - - - - - diff --git a/yudao-ui-app/components/w-picker/range-picker.vue b/yudao-ui-app/components/w-picker/range-picker.vue deleted file mode 100644 index 7dd8b5b11..000000000 --- a/yudao-ui-app/components/w-picker/range-picker.vue +++ /dev/null @@ -1,344 +0,0 @@ - - - - - diff --git a/yudao-ui-app/components/w-picker/region-picker.vue b/yudao-ui-app/components/w-picker/region-picker.vue deleted file mode 100644 index 34c1f402e..000000000 --- a/yudao-ui-app/components/w-picker/region-picker.vue +++ /dev/null @@ -1,183 +0,0 @@ - - - - - - diff --git a/yudao-ui-app/components/w-picker/selector-picker.vue b/yudao-ui-app/components/w-picker/selector-picker.vue deleted file mode 100644 index 6ce2ced89..000000000 --- a/yudao-ui-app/components/w-picker/selector-picker.vue +++ /dev/null @@ -1,129 +0,0 @@ - - - - - diff --git a/yudao-ui-app/components/w-picker/shortterm-picker.vue b/yudao-ui-app/components/w-picker/shortterm-picker.vue deleted file mode 100644 index d133cf4b0..000000000 --- a/yudao-ui-app/components/w-picker/shortterm-picker.vue +++ /dev/null @@ -1,250 +0,0 @@ - - - - - diff --git a/yudao-ui-app/components/w-picker/time-picker.vue b/yudao-ui-app/components/w-picker/time-picker.vue deleted file mode 100644 index 2fc57e47a..000000000 --- a/yudao-ui-app/components/w-picker/time-picker.vue +++ /dev/null @@ -1,218 +0,0 @@ - - - - - - diff --git a/yudao-ui-app/components/w-picker/w-picker.css b/yudao-ui-app/components/w-picker/w-picker.css deleted file mode 100644 index fb42e7867..000000000 --- a/yudao-ui-app/components/w-picker/w-picker.css +++ /dev/null @@ -1,26 +0,0 @@ -.w-picker-flex2{ - flex:2; -} -.w-picker-flex1{ - flex:1; -} -.w-picker-view { - width: 100%; - height: 476upx; - overflow: hidden; - background-color: rgba(255, 255, 255, 1); - z-index: 666; -} -.d-picker-view{ - height: 100%; -} - -.w-picker-item { - text-align: center; - width: 100%; - height: 88upx; - line-height: 88upx; - text-overflow: ellipsis; - white-space: nowrap; - font-size: 30upx; -} \ No newline at end of file diff --git a/yudao-ui-app/components/w-picker/w-picker.vue b/yudao-ui-app/components/w-picker/w-picker.vue deleted file mode 100644 index d8f7d768a..000000000 --- a/yudao-ui-app/components/w-picker/w-picker.vue +++ /dev/null @@ -1,340 +0,0 @@ - - - - - diff --git a/yudao-ui-app/components/yd-address-select/yd-address-select.vue b/yudao-ui-app/components/yd-address-select/yd-address-select.vue deleted file mode 100644 index 795dcad18..000000000 --- a/yudao-ui-app/components/yd-address-select/yd-address-select.vue +++ /dev/null @@ -1,106 +0,0 @@ - - - - - diff --git a/yudao-ui-app/components/yd-banner/yd-banner.vue b/yudao-ui-app/components/yd-banner/yd-banner.vue deleted file mode 100644 index 6f6d38145..000000000 --- a/yudao-ui-app/components/yd-banner/yd-banner.vue +++ /dev/null @@ -1,58 +0,0 @@ - - - - - diff --git a/yudao-ui-app/components/yd-cart-product/yd-cart-product.vue b/yudao-ui-app/components/yd-cart-product/yd-cart-product.vue deleted file mode 100644 index 634afb243..000000000 --- a/yudao-ui-app/components/yd-cart-product/yd-cart-product.vue +++ /dev/null @@ -1,116 +0,0 @@ - - - - diff --git a/yudao-ui-app/components/yd-order-product/yd-order-product.vue b/yudao-ui-app/components/yd-order-product/yd-order-product.vue deleted file mode 100644 index e6f06eba1..000000000 --- a/yudao-ui-app/components/yd-order-product/yd-order-product.vue +++ /dev/null @@ -1,100 +0,0 @@ - - - - diff --git a/yudao-ui-app/components/yd-product-box/yd-product-box.vue b/yudao-ui-app/components/yd-product-box/yd-product-box.vue deleted file mode 100644 index 04b216ee7..000000000 --- a/yudao-ui-app/components/yd-product-box/yd-product-box.vue +++ /dev/null @@ -1,173 +0,0 @@ - - - - diff --git a/yudao-ui-app/components/yd-product-more/yd-product-more.vue b/yudao-ui-app/components/yd-product-more/yd-product-more.vue deleted file mode 100644 index ab9a3a91a..000000000 --- a/yudao-ui-app/components/yd-product-more/yd-product-more.vue +++ /dev/null @@ -1,114 +0,0 @@ - - - - diff --git a/yudao-ui-app/components/yd-text-price/yd-text-price.vue b/yudao-ui-app/components/yd-text-price/yd-text-price.vue deleted file mode 100644 index be32b13de..000000000 --- a/yudao-ui-app/components/yd-text-price/yd-text-price.vue +++ /dev/null @@ -1,73 +0,0 @@ - - - - diff --git a/yudao-ui-app/index.html b/yudao-ui-app/index.html deleted file mode 100644 index 03e5fc6e1..000000000 --- a/yudao-ui-app/index.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - -

- - - diff --git a/yudao-ui-app/main.js b/yudao-ui-app/main.js deleted file mode 100644 index 942875b87..000000000 --- a/yudao-ui-app/main.js +++ /dev/null @@ -1,26 +0,0 @@ -import Vue from 'vue' -import App from './App' - -// 引入全局uView -import uView from '@/uni_modules/uview-ui' - -// vuex -import store from './store' - -Vue.config.productionTip = false -Vue.prototype.$store = store - - - -App.mpType = 'app' -Vue.use(uView) - -const app = new Vue({ - store, - ...App -}) - -// 引入请求封装 -require('./utils/request/index')(app) - -app.$mount() diff --git a/yudao-ui-app/manifest.json b/yudao-ui-app/manifest.json deleted file mode 100644 index 0f85730b8..000000000 --- a/yudao-ui-app/manifest.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "name" : "yudao-ui-app", - "appid" : "__UNI__CA099E3", - "description" : "yudao-ui-app for ruoyi-vue-pro", - "versionName" : "1.0.0", - "versionCode" : "100", - "transformPx" : false, - /* 5+App特有相关 */ - "app-plus" : { - "usingComponents" : true, - "nvueStyleCompiler" : "uni-app", - "compilerVersion" : 3, - "splashscreen" : { - "alwaysShowBeforeRender" : true, - "waiting" : true, - "autoclose" : true, - "delay" : 0 - }, - /* 模块配置 */ - "modules" : {}, - /* 应用发布信息 */ - "distribute" : { - /* android打包配置 */ - "android" : { - "permissions" : [ - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "" - ] - }, - /* ios打包配置 */ - "ios" : {}, - /* SDK配置 */ - "sdkConfigs" : {} - } - }, - /* 快应用特有相关 */ - "quickapp" : {}, - /* 小程序特有相关 */ - "mp-weixin" : { - "appid" : "wx48d7c38b46f2e81c", - "setting" : { - "urlCheck" : false - }, - "usingComponents" : true - }, - "mp-alipay" : { - "usingComponents" : true - }, - "mp-baidu" : { - "usingComponents" : true - }, - "mp-toutiao" : { - "usingComponents" : true - }, - "uniStatistics" : { - "enable" : false - }, - "vueVersion" : "2" -} diff --git a/yudao-ui-app/pages.json b/yudao-ui-app/pages.json deleted file mode 100644 index a25d3f5d1..000000000 --- a/yudao-ui-app/pages.json +++ /dev/null @@ -1,156 +0,0 @@ -{ - "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages - { - "path": "pages/index/index", - "style": { - "navigationBarTitleText": "首页" - } - }, - { - "path": "pages/category/category", - "style": { - "navigationBarTitleText": "分类" - } - }, - { - "path": "pages/category/product-list", - "style": { - "navigationBarTitleText": "", - "navigationStyle": "custom", - "navigationBarTextStyle": "white" - } - }, - { - "path": "pages/cart/cart", - "style": { - "navigationBarTitleText": "购物车" - } - }, - { - "path": "pages/user/user", - "style": { - "navigationBarTitleText": "我的" - } - }, - { - "path": "pages/login/social", - "style": { - "navigationBarTitleText": "授权登录" - } - }, - { - "path": "pages/login/mobile", - "style": { - "navigationBarTitleText": "手机登录" - } - }, - { - "path": "pages/forgot/forgot", - "style": { - "navigationBarTitleText": "忘记密码" - } - }, - { - "path": "pages/profile/profile", - "style": { - "navigationBarTitleText": "个人资料" - } - }, - { - "path": "pages/setting/setting", - "style": { - "navigationBarTitleText": "账户设置" - } - }, - { - "path": "pages/product/product", - "style": { - "navigationBarTitleText": "商品详情" - } - }, - { - "path": "pages/checkout/checkout", - "style": { - "navigationBarTitleText": "填写订单" - } - }, - { - "path": "pages/order/list", - "style": { - "navigationBarTitleText": "我的订单" - } - }, - { - "path": "pages/order/detail", - "style": { - "navigationBarTitleText": "订单详情" - } - }, - { - "path": "pages/order/confirm", - "style": { - "navigationBarTitleText": "确认订单" - } - }, - { - "path": "pages/address/list", - "style": { - "navigationBarTitleText": "收货地址" - } - }, - { - "path": "pages/search/search", - "style": { - "navigationBarTitleText": "搜索" - } - }, - { - "path": "pages/address/create", - "style": { - "navigationBarTitleText": "新增地址" - } - }, - { - "path": "pages/address/update", - "style": { - "navigationBarTitleText": "修改地址" - } - } - ], - "tabBar": { - "selectedColor": "#333333", - "color": "#bfbfbf", - "list": [ - { - "pagePath": "pages/index/index", - "text": "首页", - "iconPath": "/static/images/tabbar/index.png", - "selectedIconPath": "/static/images/tabbar/index-active.png" - }, - { - "pagePath": "pages/category/category", - "text": "分类", - "iconPath": "/static/images/tabbar/category.png", - "selectedIconPath": "/static/images/tabbar/category-active.png" - }, - { - "pagePath": "pages/cart/cart", - "text": "购物车", - "iconPath": "/static/images/tabbar/cart.png", - "selectedIconPath": "/static/images/tabbar/cart-active.png" - }, - { - "pagePath": "pages/user/user", - "text": "我的", - "iconPath": "/static/images/tabbar/user.png", - "selectedIconPath": "/static/images/tabbar/user-active.png" - } - ] - }, - "globalStyle": { - "navigationBarTextStyle": "black", - "navigationBarTitleText": "yudao-ui-app", - "navigationBarBackgroundColor": "#ffffff", - "backgroundColor": "#ffffff" - } -} diff --git a/yudao-ui-app/pages/address/create.vue b/yudao-ui-app/pages/address/create.vue deleted file mode 100644 index fccef1bc4..000000000 --- a/yudao-ui-app/pages/address/create.vue +++ /dev/null @@ -1,148 +0,0 @@ - - - - - diff --git a/yudao-ui-app/pages/address/list.vue b/yudao-ui-app/pages/address/list.vue deleted file mode 100644 index e81409ccd..000000000 --- a/yudao-ui-app/pages/address/list.vue +++ /dev/null @@ -1,116 +0,0 @@ - - - - - diff --git a/yudao-ui-app/pages/address/update.vue b/yudao-ui-app/pages/address/update.vue deleted file mode 100644 index b8c70d46f..000000000 --- a/yudao-ui-app/pages/address/update.vue +++ /dev/null @@ -1,178 +0,0 @@ - - - - - diff --git a/yudao-ui-app/pages/cart/cart.vue b/yudao-ui-app/pages/cart/cart.vue deleted file mode 100644 index 00a190767..000000000 --- a/yudao-ui-app/pages/cart/cart.vue +++ /dev/null @@ -1,225 +0,0 @@ - - - - - diff --git a/yudao-ui-app/pages/category/category.vue b/yudao-ui-app/pages/category/category.vue deleted file mode 100644 index 6d2624d84..000000000 --- a/yudao-ui-app/pages/category/category.vue +++ /dev/null @@ -1,205 +0,0 @@ - - - - - diff --git a/yudao-ui-app/pages/category/product-list.vue b/yudao-ui-app/pages/category/product-list.vue deleted file mode 100644 index 2ec12d19f..000000000 --- a/yudao-ui-app/pages/category/product-list.vue +++ /dev/null @@ -1,164 +0,0 @@ - - - - - diff --git a/yudao-ui-app/pages/checkout/checkout.vue b/yudao-ui-app/pages/checkout/checkout.vue deleted file mode 100644 index 97e18bba3..000000000 --- a/yudao-ui-app/pages/checkout/checkout.vue +++ /dev/null @@ -1,219 +0,0 @@ - - - - - diff --git a/yudao-ui-app/pages/forgot/forgot.vue b/yudao-ui-app/pages/forgot/forgot.vue deleted file mode 100644 index 2dc8ffa19..000000000 --- a/yudao-ui-app/pages/forgot/forgot.vue +++ /dev/null @@ -1,157 +0,0 @@ - - - - - diff --git a/yudao-ui-app/pages/index/index.vue b/yudao-ui-app/pages/index/index.vue deleted file mode 100644 index cf455ceb3..000000000 --- a/yudao-ui-app/pages/index/index.vue +++ /dev/null @@ -1,149 +0,0 @@ - - - - - diff --git a/yudao-ui-app/pages/login/mobile.vue b/yudao-ui-app/pages/login/mobile.vue deleted file mode 100644 index e58e6527d..000000000 --- a/yudao-ui-app/pages/login/mobile.vue +++ /dev/null @@ -1,197 +0,0 @@ - - - - - diff --git a/yudao-ui-app/pages/login/social.vue b/yudao-ui-app/pages/login/social.vue deleted file mode 100644 index ac09a095c..000000000 --- a/yudao-ui-app/pages/login/social.vue +++ /dev/null @@ -1,117 +0,0 @@ - - - - - diff --git a/yudao-ui-app/pages/order/confirm.vue b/yudao-ui-app/pages/order/confirm.vue deleted file mode 100644 index 878737284..000000000 --- a/yudao-ui-app/pages/order/confirm.vue +++ /dev/null @@ -1,63 +0,0 @@ - - - - - diff --git a/yudao-ui-app/pages/order/detail.vue b/yudao-ui-app/pages/order/detail.vue deleted file mode 100644 index 32324d2d4..000000000 --- a/yudao-ui-app/pages/order/detail.vue +++ /dev/null @@ -1,252 +0,0 @@ - - - - - diff --git a/yudao-ui-app/pages/order/list.vue b/yudao-ui-app/pages/order/list.vue deleted file mode 100644 index 9501a6984..000000000 --- a/yudao-ui-app/pages/order/list.vue +++ /dev/null @@ -1,195 +0,0 @@ - - - - - diff --git a/yudao-ui-app/pages/product/product.vue b/yudao-ui-app/pages/product/product.vue deleted file mode 100644 index d9d3a9dd2..000000000 --- a/yudao-ui-app/pages/product/product.vue +++ /dev/null @@ -1,576 +0,0 @@ - - - - - diff --git a/yudao-ui-app/pages/profile/profile.vue b/yudao-ui-app/pages/profile/profile.vue deleted file mode 100644 index 0ada1e327..000000000 --- a/yudao-ui-app/pages/profile/profile.vue +++ /dev/null @@ -1,128 +0,0 @@ - - - - - diff --git a/yudao-ui-app/pages/search/search.vue b/yudao-ui-app/pages/search/search.vue deleted file mode 100644 index e936481b7..000000000 --- a/yudao-ui-app/pages/search/search.vue +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/yudao-ui-app/pages/setting/setting.vue b/yudao-ui-app/pages/setting/setting.vue deleted file mode 100644 index 33cf94352..000000000 --- a/yudao-ui-app/pages/setting/setting.vue +++ /dev/null @@ -1,62 +0,0 @@ - - - - - diff --git a/yudao-ui-app/pages/user/user.vue b/yudao-ui-app/pages/user/user.vue deleted file mode 100644 index 8221e19ae..000000000 --- a/yudao-ui-app/pages/user/user.vue +++ /dev/null @@ -1,203 +0,0 @@ - - - - - diff --git a/yudao-ui-app/sitemap.json b/yudao-ui-app/sitemap.json deleted file mode 100644 index ca02add20..000000000 --- a/yudao-ui-app/sitemap.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", - "rules": [{ - "action": "allow", - "page": "*" - }] -} \ No newline at end of file diff --git a/yudao-ui-app/static/images/empty/address.png b/yudao-ui-app/static/images/empty/address.png deleted file mode 100644 index 15014020a6836d6af2d20d1ede8f6b60d11451d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19443 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 H#H9ZN%``$O diff --git a/yudao-ui-app/static/images/empty/cart.png b/yudao-ui-app/static/images/empty/cart.png deleted file mode 100644 index 7fda8e8e5ec20251a639c3c2973bdeaa0d30dcf0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28547 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 pMOG9RC+7c~|3@6UBw^nGf&z+2 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 rwr%@=vbFnv_4)tc3y(+f8gGC_eDL` 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 KiE1&U!2bcM2u4!? diff --git a/yudao-ui-app/static/images/empty/favor.png b/yudao-ui-app/static/images/empty/favor.png deleted file mode 100644 index 23d7dfcdccc953d5544f26c55ea81b33ca36af82..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16647 zcmeIaRZwL;6fTII#+}C9Y24ju+-cmcad&rjcWtC`celpf-QfTScW3zT%+x&ITQzm7 z=3yRE$<9vpUV9~3S>KnPL@3HjAj09ofq{V`N=g1y1_J}9`!B#iedT!g#JYS%;7-aC zB4E{1_$OZ%KYwdTnaat5(R`(0z`(;SzySXh`3ksS0SpW>9~=zwD+d2BFCXInz6(y5 z5BdM3|0}p+5C{YV69SX^DXiiSe(vKHt+VX0-By#aibd4n9dVGTlR!KACtDJt0$bWT zBXu4?qf;nO#wnz9hYTICTLPoZCj0@b(ny^MWgY-HA!0!I{!Au`{g+{!Bd3jZJYzLyGbiIcc98#Z>$Vm6HpSob++{msvw3}7{ITA( zfO8T>j3Sm$3}r?LPv$j9$a4+r!%%yN03o8m&zd}kN_sW4&MBS(_i)7({g!aq!+*;Z zM{x)Bb-Rl>b`GBS>IJ0kmi9*kLwHq*iRZd-92$_nB_sq>!8zox{%B-rNuxbhHVgtc z?3g06>vA!Z=wfSI(uILBbXj(nvH}rb&B-MA?B}}8DHo_yX@&?JV4XcvNm|~|9cn!i z69+Hy8&lBhehZk_?{wu0{{t9yKB_13G( z0KNluyE(Tq_}jH|9J?A&S1^N%iO!6k=!^d__ITR9_&GnsOM)_m4UCNXyMAf;_BRV@ z(uW!;Vtbu8m37f$CY=%Z3ylYDg4@`(!MX+Ya}sOv_XQ?I`tGN=mGrDRQYhy)pkU+s zOhl?|YvExanGj{Ace1xG-6-2yp&Wbkdmg^s*(ueRhjPA+$_b zF3b^KUOS>jz)#Wl-kUfuF|BfuY@3wG{|jriw=rS1d+`Qsp+WMyEfwSa5Sc;8ZuBFe zT4IWmC?LWq&F%O3gogG7e)+~naX^xDl(~$L@@Od8Oamml!|s})%r`$_$MP_v?`68a z$9}JqqZzxNCyrIDsP+(`UE-_thdJNUKRMG~_P_Pb9@Ml_#Pg|Ott@HAv<$D*iHo5H z!fUN!u%h}nr^S_Y!v@$i9J}vf0A#ZY$yGP!mQv==tbg-xI##P+igIJbzN&&=`tOK> zqH`^vc;eSiLT=~%=4ACo8}4DU3Gv1&3|+S1s`@>((RpSMfeJDDI(GcZzPBjH-2Itc zZilqQ75Y}+M2_;f-0nHGe~@{!Ab}^UQQ9wwX=zU9cz&FO)!6DX9!yyY=L2EJm6x!V zApof(J%GJaZoZ{JG0tRz-Yq?dW&^SnF`LWkvFz>ef`!KzbpUl znPUOsGS(mk!sq3`bQKHKHAQZe5O&?%^XkrlRAjtbE}T%jks@}zuVH2iv0LX8dXg2H zUqX`8xq5nU(40-;zhfyP_q-FM2&w7&U5t|T(3sp4C-Vqa(OGccBVJ>=Uc+NmxrJ2n z_|f4t)lyN=&7X{pQae>}`G|`t#psSVS8ab)E9|klk=}TRF_)r+mZH^2XvF`Wc2@A= z=C@ndb-TGOdLpcVjv1CFpau`Dl?hVTXBn{3JZ%wtU8oae1EM`5L8KJ@mQZ8Po78}|-@B6k>5c(>yUXh-pH2AMUQ}3hQd|QkbLh=rh(Eeg3id zZ|kD!u9^y!*rLnz;&l4a1X%Rzf0KPTKuJ%}<_@r<`rvjIc9~$0_!e*;E3~O#VB@CP z-2REhuz{aWi`gB5$dc!Nzi~(32;8=F$vXH56rv)YNy2+_fv5#p3~c6KAxf$#)FQ<% z*>&Db-Kj7C%1g!oczy#XsYJpXRi9G$#56x0U!08mfH~a-R@97Y{w2A3=}>o5kd+Nz zst8=JxGctN+vU))xYbE15s&WJTE_)G?HL|HIDqU?DlY zZj{$nC8P&qMXOljG#vrIjHFHT1fTdT$K>p$()GFE^PH2)EEH5c-c%(D2Ka3}&^uoM z_ew^~!*f0L?{7;rdzX*dmu%SjzK6qbK|K&Z&b<_!n3#v6{_SLKJUk0OliN6V&W(}SS!`j5 z-Dij^zBJL^YOs5M8hAeeId%&Gf@_z;w%cVCvO8`t;umY0lu>WL(l1$6$qAk35(ax` zXSvk-zU6w8hTqqo-{yebw@VALUlzp1=F7lWA+|K9^tYf}2?#IA9%2fVg6}0>TR~MK zj<7mBJ2KSY3LFu=I3_mXqEOPl8no#oU?5_0d&Ay*)RB<1+9Tyb$jnDx^ovc1H>a({N+No7% z6kbw3kMnr~Jj=PfQuIH+rp$p{$QKRz>;VQuX`fLx#M3=HzlSnoKl3Sy3p#)vuh(Hg zZ+)&h&4PT7684n#yC`FxK$~4bgVx%66>9%!FLQRUdU@5CRfWo{U|gknxd-M7Jj5Vb zm#~#VfWPR_W8L;(hxEPcjJ{qpOvf^)laCh=&#c45H|p`a-2=Tk(z+HqF5fqs5?GUx zGPX`r?!-}0003}dq5nzbi3aXqbzEThesXsn6q~{wllDg+rqCQkn|>fC3f!*iUxEPW zNDx#1skxGOtbW_U8pto$xb5ZK`02^{D7Ci5_vK7X8ZXvyw}BfZcYUtMTKU=33U&yB z`loRjqvEUIh*c;A7aUN;X=FbrWYs9^gXegf;|@c2Bbs)ltaxK@WGFBIySjJxHg_P# zvw*9t;jpmFl-n`k>Hj*!p(qb4>wF6~(#J{eZqBD8N>;i_*J4<*i7G?@hD-s?v0s3| z5qAwVI1D14*#Qe8VmT{&AXPJ8Ev$Q*GB>fwaC0)W;{yv0y=ZFWzcMBS-_OD0>QDMh zZQEx>8%ao>9n_6@Uz;rH?GA6CAORoKo0ljtttfSJIcAzqymCGT&9D?DhbcEzYZUe+ zrJCW-lc+=u)K54uG_8E87+_s6ri_^)=k-Zl@StKy>V&h7>Sk!JigXw`L)`m7kL-|W z53$E{u^onVNDaTQ^<@mAO}I+;35<$hQS}7DBkU3B!jwNb`sf0< zxFI53;ooTr#YKrT1J9ty;=nYoD{4}WE<*#G!Q927cuMn}K-oYVPKPXFEX%Sln3ss7 zD#t8sI@BHswbUUNE>SdT&tX>N z?PI;3)Uy_&(Uzvn2@|EJ$~=YTuq^XBnA<81)T4CIJ@xG_L}ofNheA4S-2$rA-?v0T zA16<{309zL4Vq(^FRR33guS#BZbdZJ<7>XX!&rM))%Kg6GtVxv5_fa*3a)GdMz#^p z!q`p3lp&m?Fv41l$I0MbUPdLkyOBJ#G+lf%nxY|nLc}^qLNzJiQEGX%v@7MLQcOk@ zM^ek@-O|J2q(kkxkTE(g4vXe?)WMBZ@e$8`b2a6B`Lxg1F1l+hxczDlIiXIb! z{-L;D9aHx{-Ho~+MlC`!wUqETIw6v-odzDegE%I&yL4buZ^U- z+d8>!71p4JVmUGEv5#}zOt4yW7I%a*6fbTun+|6bSaSRYW9q_vT%G$0 zn5Uv<(E9lE&Pg5t)}lQPLM@L4o0c^^Ip%v%65|V-U5kdNas4oTxhzl5LvkaB+NY#+@(|Q3t0fTZ)5DUuMO3$~&Hr2Qk+tK!XA+~>Sd$Ms6H~3aSkxz` z$A?Upw_}wTN@;Vxt3pR{F$Roc(`l#>3)!&pn$d(4R5cTWC}JmjOOdH9y*Wl2ZTc`0 zLitCf_Bj?Nmc=Qf;SU3s1{E5X&$JVRbrs>!g}VO`!r6>7-#&v)c zXePIt9a31Jh`&PRrp(b-#N$!Ex{c+>3hI9q2AL$u5FnB}k16|970MHN^9dh*=djCY zRt8mLWXLYTo*y^1#SLyo_@k(~#cC_GWEM3gKVH`q6;}t~FNmBQ%zCzz(K#tK1V197 ze#n8?B_rfTzU*?6xagX)xIdr?3=0~Hr@A_!rqLmfqaF;(uQXfmS9buuGsTw))8)4A z+BUCdwe+jua89u#338B+nLe=NB>gf%F@?=?Yt}H7nzB0THHa2f6=**?55FX~c}9_h z^NRFwYHquHcp&Y%8A749{abT%4hxR~(> z1TkOVAb}jmX3Gx~U)kE5es67i3e=9h-(LFiV>Ug%21&CoLeV!of3VR=ZMXa1){EPM zLM@?!M1qZ=H>eHi@{ON>gF~PkK-;#78)ioDAAg-A4m6{{V@2`5;+AaXYr)>c6fQ1n zdENtta|t2x$_HZ_c3V^kl}~D=bHcH*-5kjH+Oy)r!^2Mu272G!!3fBf=2A_^bq-Qu zG&Q`wDkd0TmGD5jkmmdI>o8YYTe*sZYPc{GqDZ9wnj;8GG*dZ7$Zu*M zt2O4v@)dpVcR+JF69OcoPU&1Uc88W)bqwG{8yp@os_U;mJr-aBwnz%d<1!@I4i=k=Llj|>L z=+f&}KVtp|ui0~T7xC80pI~b@MSU!R1|^*|?$h2!v^AWYRwW7*tXiza6bj4#p z?fnZgZt{;&UB9iZ^r()4MIEvXTtEoE(iT6Qp?=`sX_Vtq#aAD_KOJ$k?=jaQ8UnH2 z$pSe>u*?iA0zv(r-8UP3n<*ttsNk9u)@13*s!lLmC^hB{My;W$LL?PO_DMRm9&j*$ zy{4o>>ncMojmF0;Dt&Fwfs$%j++e!Cj3ku|M7!UQK{Ab8=d6fwOz`zoPcyppHFVp{J@N}^n<@<&bih)8ka|xh zD>G`_!%VS4@a_C%j)2daJ~Yx7?d1>ehU4uUx{j{xUSQ{2xANxY6ZnU?whzX+Dma8c znU0<7Rs(yL>|rKC;rJF2%Bn*pZ+ytB49H^ZF`jll=XPRdMmEzFeE)y(Cn#G?Hxk{S z4-*49h%UgESYIW=gUo7!>*5)#m(YUMKML!@6qya z$2S2sOr|y<(nZ0=oHs5=lJBEg+xG<#HNRvQTM)m%R+2ck`zlLyWoNO5o5c4zN z3I^n5r@Kb<@=;LITYKIIN#%PnTXJK&FZ;H&{bp2P0g!b5c2?WVqBMX!!l_$j@*R*V zo=*z{>JQ0+Os&!)%_oL=?7E&hn=MIL3B{2T+Sof3fE@`}K<@qOXMPbT6v8MgxB#Bq zT1raF4c_8IswI?t(y%j4%=-&RG`moVmah2Raiw?}zO7dVG4h;$Wr>`(DIFROC1ECA1$ zOF?vrJ7`R1EQ`asv4jm~@6k~q+OOcykuwqSEz1zlMB{-BAj-}m+~1q4r}4fyTWxUh zLFX+jKDQDZMpI)#dj}AajJH%&6dX=x`tvM1xxg^f_D@(~}98f6# zLJ3_1p6)+)>M4EiK8;QQ8YR|~HB{%lyi zF1O-$pQ{TNtCZ5p=+(rs_|5Nj`uvxudo9R#d5J+O)AIXif@UF0;+7uZ_^9FgVP3dM z#gSZWB8|Y^XL5l+On)x!plj6Lag59=5A814KHBl2r{lsHRh~9 zl~2Io;oYUG(v78rKtTggqdFIO&gGcBQM6LY^ZYfFH%0btcRQSzv)T%zErZkJYCU-UPT>*4d z+bv@`PmPyd#FNwrL!Z7|aE~#xL5czu@(5pBmHtxbq8wuaTIG~UuyO`vvgz%FhN{v( z9xh8N)X_VN_bVD3Krm77l1Zrqn*R=EAKn=Gn%#U;e8+wZ=hLFD_`PLFsGwA?5*~8x zc1IBD2`r`L)XX1OlhZv6#AE7VwgI1~+Vo#mA){PgsL}ud)nW#FRb>NLUh6#K9k@d&X`XFH4h} z@wxH?0dVV{#$mqQ(Wv&Ffnkf`-Q=FvRU-1sD~$f7(5$>AqvNAdx0WNwx0mNcFV-;J z9%!uj2z}mm%h<`(eevkHyco~%9rHiDuN*>Liwg4}P&jgX0T#N%ry6&-+3E3k?k<%5 zDvmMVH(mY_+_V}#{tgJhL~#c%O6fVwb5m(t5Mj>2z+>2Y`Dj7@9Ef7nIu+bihqE!R)fjr`JEEluZ>k3=YnWq$bR(>%;jdAANT)q0d9_^x4&S1 z^%Eku6PC{U(&g0Y`*!O4=yW!ZYatb{&g>78N;sy2uXz>|AgT57PKKpJm3a&I(2@5% z@zlKXSyi!3ah4h;v-ShV8UXQEL0jOos}|M8%`!(sBZr4&vT`L8 z0;@V&Q`o}LP;&F{rE<-^(hEA-m!I=b0YZQvFXY{5J&YIzX;-G^FFhw7B3=5V|Xnp-?8fK zTcw$l>QUGl^)g>wGPgZae;yCDI?_xQo|6l=7;eSwb)^Ivp%F{Xa!SAytI5f`zD@vj zq{1D=vtfz(xHSki_+2Fbz8|chJ@0S)1^SPJNdSk{6nwhAV_2^bt?L`9HRkR3LyVo9 zqwXU=G{gzjzvZ#~NA78zn8u*U8k(_=*tC`oT5+#XBisY&4{6(e3`Uds4>v|~*6b&m z&x=OS{r-tS$13iggXy-6iA~)EFW|wb4|_Far9}VI7rD{ovXXWgJ-O!SGq9CA)AS%h zx^g=(y2?-dW7=e<16QNDp8jl(03MZ6%7_?jH&I_JoNl9(YK-fYi8%%kY^;O2ZDwZw_%5h*-!;W36cH$a*5#RRWT*$iA&4Q0QB^yVw<8A9d zSBPyFD1znTVg+s24}ec>o|)d_X(H2BC-`lB-?6_V6HA zXK{_H#Ez)AQW($jjg)I}Le_>ATc@3e)Do@jm$T(>dD@x68oSR=wsKbX?HrW_L1+02 zYcBur)A|pPP_$-_d+#1i2F%%j{OzET4KL0f;bq>N;SrJdFt%D-n2hfLGrwT{uvvo@ z)wwdTZ}IPfjb#(z0{Z*M-{>N=|^uiE2`aZ=iBe{?9e}|gw>mS|)TPl0%$wemg zP4mbyu{Cd!-^S!2i5|>0zXsG1On~bcX9Gs`X#w9}nJE!&hJ)4i2JO$@+bSzk;Z5jt zV}7j7GkcvM; zmX_$y1d#$8b;4+{F?UJEO$!inYpaXw(THRJOsMi=L)+Hl=2l?yJ4_>V_ozqe*x}2< z-rioEPmg7WGM$!*QC>=7rcy3Ka)?oLuLx5V1WXxE4s!1Q51 z+;e=C&J2>>t|{TO-SJ3u+nc%S8UMXurV$#<4$WSn5oi+nxd(oM4?$+AguBsEp)l#& zSb4#il9>o6)$2Yf-d0_RzpNS}vb$y^@aYns{mYbZ?y2axYt|j52Rh`=z38^t?rorr zxW1%8%uI{C#xgmi7L9L8x4V;;u2lkG@)wg!vQ#-512il+b~Ll7CxnLLGHIzzv`gp$ zx-6t8%y<}cQC2%P>%tPz_IOd@+zRttDP8Hbh|d#?wCUN-l>Yg2d!7Wl7VRjODE6LA zO?zl*y@8_+uK=wUWrOv|)B2V!AM3oAQ*lPn z9!tU-*fLJ`xxIy}YqMWC%CGC zJk%9m8*_V6erGh6lEuN@tzoTtJGr|K8wL?@*4LEx+eqqBMbXl43rKjYHLLbAcHSn* zIE6v*Vh_l!=&yQ=$i@5bz>ARpNP=I%ydCmgu#FTZ{c#D3>YI6nEpkXzyN^Dkv{y=a zn(7kP%%{^&-1|__2+fi4v&Pp%gCJK?ryYZeGaED1tSfW$=^s84b#Qt`=`Hy$XO z2|uAC5I!4!mPAC~q+9g9sK_ii*-!hYR_|EuOm940DFe`(mtaL*LkI$izx9jg4d&mB zcovt|*BETT_^Jx!w!c#$@fg2A|0#DqmqPp?;Q7F=nQ6$j683wzL4Sp^wV_gvXh$z_ zrSA9~JD8ZL#W;xFMHLLxw`iAS{{WX4y!z2yE=+L<6wNEIzeHx`l&&eOeGz$iI5|=U zR`Wa6`2+wxMc=vI$U&>nb?qMbwCcty@ZLR#8lv%IYz!sjX){ICtc~ zXf1ub3|iLslNT4K8R>kTy)L%s;{jVK0cw&_JS(sW-vyHrT#CQ1eR76p$H{svt^56o zi@;k-gW}TdRWaEU-(RQRTxgKa?&i>|5mY zCIo#=F5z)bKAQe}{&^Su!1Q&)5WD)(u-HcMXS(olAW{)7GUMvK8NSzy!#P3j{+T~$ z5M^QCH(nDHP4m#QEAWRbZ#ib8r4$~HiVO!+`! z#nek+%~q%5j#fRMg{qg=Zqe6Y5bvw6UX}Uo_{ckkYx(rF59Dz`Q-4@Ah2uLgmb}pc zHm6Rl59jBHym_x29mA~-=3&*hx>K9gyy&#^+YNhco~3ZmY6sKK3ig;|encIbtsPj4 zCw!#Ife6;nJU(-VByof9vV&u@@oynVRapdxxraIk6`7Tw z+H$jsZaO{OP$~g-eyC`v-G|M%8V2C47|nJo+*b6W@NwuRRKgH@n%3~f1m7e^-&L&UsMAf9sNSoSRrOD)ej%dKea@e@=qqSm4R~q zLEtu3vx*Tu7RMN(@rQ^L#1QlJ{Ii_qkgNit%UM%5Uk&7@ECp?5_)M@pH4y+k8;t@(Co2=Zy_o%+LU z=C*9~*Yw!DL4sE$_OE=?=T4|W`HoM}7Kn$xzz+w!3$Cs=y>2;YFVRkg#4?AjEQ~<5 z*sI$NAs2_~*~?pgtdyNy+@?B=>2<~v@l$z2S;^2aV84N}JtsjY3T45%6gr^2!a^_G zyTGan5UkbBQkC#u6n<-Mdx`LVgk0(mo#k_^V5lNPT*~!^bmJj>gI}r4(=n)C>}0lb zzTcUbPnXi96%??Icg!Yk4zOno&>DU@tk0kSi_A(3AU|+_0DGbd`*HY8j2ABd-EqYN zddLRr;`_$o6eKs7dlzboQ&`7Lh!a5HC>VRtIUaLtH$)E$0vCos$cj24LC(-Buq#5` zvlekeVPQv+H||&_^mS*mLv{!`=Na%JxAz;iZ-GYH8lp+W1ly@Wcd}x@;>Pnf)K0I`kEU&Pkc`>`?R{m zEI*H?#?wfwv5d0tk1}Q=B006J%F^QdBPLCD8blo+e}>=_)1l#5 z17CQ`Ahk&3PV&)D@v;*4QvQMR8p@HoV)pdV9LOEzkSWRREM`^Cq=3 zWT+(Ewqk}0y*?We)T$?$61EfP z5n6_|p1{p}&%E#XZ~T$t{_m-_0*^`^!eCK!mP7J>;!LCn8t2+MppgXdNU)B6kc4HT?EabCBSY zl#)-f-pvuTCI%Fxsg)KGEzqk%^lde?^B2i`b}S-jRpA{CP5V8QP!hRKv&YI6<{t|W z|LGWqI{Tc!DrOOJ(8I8TJ2P`oKobEb9_jS+<~b{G!*oo@W$n`u7iS)PwhKE$TnDC6 zaJ=D*#73!`HFvv-v%wym*O5qxI<|!zf?uE&>}?tXg@PYFQi2dO)Df!Ow;Vx4q0rfe3RPtqo5G5Z2BmFVd~>QcB}nyXuvhB2cQjvv{DF% zO&i5W%B6YNsoVaZzoRPkh~P~}8T?~ph{09uSX|(3(m*xPJxEos>d3*32RSj8lCc_2 z`Q2ErHiiHfEy($wwlYDmH^2gZ4x95Na13T{b}$4lX`&Qrjy>l*(E49^t?0%8^Gjfl z*2oK2_*svzOIqVb+D_C4GNHnf8Y=G5<OWcRIo;j3MU5_sU%VHh%^ZfNgD zg7)??6YR@rcZA9dpPIAk3V?*9ji6jZf9L$?v(2Bcqnc)qJW#({)6s2FgY|W0= zUPz?YgVmI2m`B`(vS$l`a#Fg0;vYqCUpxHcu@IKO7Ropt$yyszMdS#hEIKaT6ju!Z$3xl}>Buau_3x0fYH|FK@P~q={C?FDh3`UIld(un=Z!JrZa| z%ypIZN_Hl4rG?$s#mp{%YZip_nwIFloYgZw-1F;|=-C}Y#D(4Jyqk;1vZ@moUy^vmmA5)(m(-?-P=5!QeO1&i&9-WJGjvTohzy&Uod60*rXQS!akS*&Ph9 zXbqVrVrGV#*^&^s6OSC)So55RRU^n!&_CKR9mby(B2O}0Q|$VyjD@T%a-UWyy=)&b zLk%6nJ?k%VL==4d7uG$ed221xr{M~@84;sE>v4z(IJGp1S`~Jq)E5x@P!UcHeKGh> z+U9T#Tky9*gf9pr+TPi{(x12XdQIriRXK#uYMQT;>_o7PELwTgH_OtPAG_NlorOL6 zqi!~NoK>OzUvxF~bK!a%+X#K8fr~Gb$fPSB+FFIqMtG6zM}c~+VL+w5(*kO5uGqfs@t&^C$S-omgYZgH zK*w_J=nMBlp5ovQ2{ID{ew2y#9D3`sb+uY?k6kEF`qA_%+-z7Kf9Hl>20qyF`AEc|}6cv7l8 zjdXD6qd_S9GXc50@K>O8xJe~ZV5@gLLJ>voJPI$)xJ?wo0jA& z#-bQcy0UI?JG4vupqK@G9+8*;k4nJf)^LZPUzCfKjfx$cKrh_YpmFu?Nx(JdG~jhU z>D?^{^e8Pul)cfyPL#2U*5B@Sxph^4Gb9r-2Xi(-9G@=S%4VuI$F=pZuZ+i@N=K^C;e1c@)gvbE@%nk#-+YdTQYqA9WD zN!Ct@Dk85)X9Bgi?hE<7#|Z-+m~kd+2;nPF#88(9e0|o6(NLYSZ*8%oeCS zGUi#G)HgVs#pGN|C8fk=sBz9EPyaVe42A=zlYQdtEzFpJHII2^Us^d@2Qsk`u5@0t zy|b($JJy<*SyE*t*Fg2g8ro+--@W}8O<*LnG8pVNc12{Z?rMGoad44X8WaaFH?;#9;_F~^kaaDjlPdpI zo~tqS_PFFvL{F_>L>CGzWbRnAjA)sJ3w&Jm$_cZo*PFW1684mFqA`o1PxXwR7gk1d z5b`3zWjDk~lClP2KmP<4L7l)tAnv7jYUH))doPnC?%_!?Rtpj?JHDgnF;nDhTHMeu=|oT@>RNk&F#lPi9=T_7biOpPkTW{= zh&F_crZ)z({I#bG${bpF^pMkw(YL!z2r|+8puul0$a~n)7Pb0)t|5BQ23$MW#+@p> zVt;jleq2I&c>=uJ|D^+u((B|UUT21?as1{vZ#!#|Q%K(5tY1I&`}%KLZ)Zkk#NI?~ z!->*-<7uD^2!@{uCN|m{?D_1wl=zxdUK1^UiDvUu8CKqXyR}Mv6Dhp@4Y7-8F4t$4 zWX`aJUP3}voHyd^rAX!fcP~i&Q3sjU_HLx8k9r94%s^7qjcJ$Chn}Q}MJfRTB9>${ z3TGdN4q}plTOsj|Jyk*v&W>E*3hJhyQxjK|Myie_zSG_A1DQ(E2k)1kY%4Jj?q~sl z^0%LiwZ@RbC0Km=!+kCK&ql~KhTr0se>lueed|Dwoa{bH`{PCeIn?tf=4!t+i+LVV z4m_Jj4%ux|A-&8BeYgj0JJa~&bF4<7Pilyj<_A&5ewypWgq-mQIkFp~r&armTK^s< zW1Qgqf>OFzY=P0+&LEWS5Q0S^=Mk3gzA!^H&II#5Pl1vT`w6j(JH}4|DfB*k*6LsU zdiPcgg0Kh=^iPc62-P7-c4lOB(8DPsiyTD>L-S~0Lo|g{+CN92vFMV4>w%-}^W7TC zQNuduBs8}>vr~!?;F(^vd^Kq`Bm~Q~F+o@09#dSHZ{v2M!S3=FmCAwAX@B#0I!Ba{ zvCwd?B$I2dv&W1p6L09MXLUrm4?>#Zn$RstAdk^_Lnw2vm>Sn-Fb)3(l7ADq?HgsA z3*)@H&KbXJ)#xLoeB*KF!0u^PJ+cEGB0l7>f1E+TCi{BMxo7xhxv$@CH)FA=Z7+ z<)^5*fu+MaoDV%F4Bno&Y!h`d0NLT+X%4^d6-107rzrg0{PDJxknk2Wvq(sGO*RDk zbJ!|r1($?F_Zmqy%#J4lp@osiDkbwIGms6oo{ya2U|$RYTbVzuoMP#-Q4m`{dq_Or zT@zXmYuRUg=wqiBSrgo;EzVl|H zuMat&viYryg`b;-s8@X0Y+8JaOyT=brLr?NW_s#4XZfe_N%q^QXnsS6@el$^@J``3 zKbt{5&f#bey(M+UI3!p+inkOUoe11bI|`syY%Q9^3H$|`LC#=4QO%z^4mpi*b|ngQ zuwjHVJo4h;Ui;`y9-`0M9k_rpmPAKQ_+epPosn#-Karv4P|6b@<^Lp%L{N;&% zlFcz^d}+>j4+|I#A`VF_fwbKTTa-+UM^CA(2%=;<_CGuixvxuY9}|R<4caNXjqlyr zLpnruWcELBLCV*MNv+dA<~wCf)9y2{dhOX9_T#-L>gI5Rg6jMssXdC7q?X%1RtSxT z8BWtuTWb%I#Ibb|^0R-mM}+#?K?LTojR0Pw6*(fzBmqV7nJb~S90*xoe5$ZOr1HIm zRm=eKb~q{iH%L|-F-WRHzh_GMnrc%Z=pW_1eh=Cp|3(wN>?_9=XV6*UD|BF>FhNl; zS2sSP!)R51QTO zxj0R)-Vf;J3uMARpiboaaThFv=&df=0Z|+N<%!(hvC!A3LhT0)aKX}A-#v#|!7<#_FyAg*NS{Zl6uq-%B8pZn7Fkg_N zF?q604gXBJ!zW_V1=FN2S>FzM_uILxM;z**dW|ERMdN^d2D3$JNt9^D&xp|Mw#T}B z{|)UH7ZxBWq*a!AaRN`7z$_Yc=lsw*Gq&w~?d-!2ff<>}qZ!4`zzL0!$@0Q*g7C68 zmgnqP_^_~5`vL)Gxq`EY1dsqi(Uo5@rX2>gwr5o$?J4R>iOS{(hZ>Eer`4*n{< zA<;o>uo&w6I(NU^RWLeuI>BrlsuEH*&!zD1f4ph(ZhN86vg{;_<%I(gH(s9Ot0R&4 z6etC#c%CjSXvNMi+C6?iyK-^Hk1ER1_2g+#RyMeQ+fNWNL>L!?MhLWsC|#24J&@gF z+dDxmmy0{sjo5~RDjkDL_1&3=Oqb_mK#0cCvbCE-M8B8()TQ&ZPXOR{k7aeAaPbqW zMjYfVWWlAsL+z_9J+bNLMSsFYpciO)A3Sq92@L(+dP8PT`0Lb`ttYp@isxGX{!sr} z8*-UIMV_x({X~_>emy!54v-L}tm3)ety;VI1}JFpHOxM!p)RNLf3W1F$#F!_qb4Au z4Tsl3XEF7_pC67~R#OqutLPLwGqQ%h{d=iDFK{;?D{?e^5=4~l*wfMe>8u&I`Muff zQ#}{?#E(ZbnoqcY{9iGwI#%28BU>u;up|HAH| z|G&upXB3%VtkC#%B*5?g&I0(KZR+}e)ojENpG1Gfzx|{z$>jg<5CSPN`JdGy27&(v DTR#dV diff --git a/yudao-ui-app/static/images/empty/history.png b/yudao-ui-app/static/images/empty/history.png deleted file mode 100644 index b3b6985eb04bed03704d302c88830f1f2da9562b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26607 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 diff --git a/yudao-ui-app/static/images/empty/message.png b/yudao-ui-app/static/images/empty/message.png deleted file mode 100644 index 033d7b7378ce1b5dd907b87be4d347514b086ce2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16362 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 p_Wx7Y diff --git a/yudao-ui-app/static/images/empty/news.png b/yudao-ui-app/static/images/empty/news.png deleted file mode 100644 index ac743d3919d77d6734bb562edab4b458f048cdba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16711 zcmeHv<9B62ly8#0=@^}K?2gTjjgHa5jn%Pj+}O5l+qP}nwmNy~c{6MNfte3)t@oi; z)v2>jRjplH^{Z1AEGHw10E-O^1_p*8E+#Aw1_n;^FF}9(ta0&(aQMu??c_xT!73(j zk3S!T4OGMprKQ2BKFiQx;DIJ!fPW;P3HvjFfqlsW2mA7wga50`g7~ku;51oZ{=58- za7oAK5DbhTOk7w%(HZ>Q!!1l>(PN{zGI<%JdGCfaq?JUZTsT=#syJ+is=;K%6150A zEU$hxPk_K{_6PJ#fp`=PBCBIT)XAnm^=qe(*lsB8|*zW#{Do_57`Lp`>75^ie zT=Eaek|DG`f^K-YEHCfF!aQHUp5?Q@MXgASn$u)v=d#gq2^|EikM*RPl{B74xlFK? z1)#;J>aJ(PA5^S(H@nHrb?sKpLpsx{hKz}WV^??^I%okGr&Kr!x!k+?vf#h&fF65B z>&3qwyAI(|(F*tIb9P9mif7ao5=ROyrIO)oT_K+VL@yUE` zD;LT|TmWZARfmn`jxvR6d@s&l@P@!ln#kBvM}aMBBf1ERedFD!`v(r#FQT;L1RxW4 z?)nYRytM`5scFBTj*d5a3{LOoBxO-G8lxe+A1BYJ4##{k_e1v!#0-uPH##dac$Q+L z*&}C~M_j*Zg97Hr~Q-HIv~d>t~>#IK6dJcT$a!2$uRdM)|D0G->0W`s32%2*9!C_e$&Fk3F)`rv@WEw zx8K-3o~~k6iYHXFP>w1*{oYusE&;)WcCL#B%jc4lhAu#eH!{X!H2sCF(6?=PK zbqZIg0(RUBCG&bhzUN=PN!%AaJ6g{}LOBUFNB#YTndDo(hi;GCbmpE5eDOh4^g<_^ zo>KNhvUenVH9mvVBfd1(hpEFBw-qk8JCgD?4BY#hiN|Kmv$N@uBTf|Xn1#mA`I(Nu zO@o&}Mg{=D1^EA`Gk6HS-Pp+8)nHJFf*c+yc?aRtIke&%0NCg|b9SA{2dcFqOZ+Q| z8|CtrYD8|C%lA>e>=E+-=?&!1B1XD0gVbT033L;9u!|~-s6~ugp!e7<57u51^N

3J>4~M~}rKB@8R+~S5Rjl9ETubq} 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 F{tqIXiw^(* diff --git a/yudao-ui-app/static/images/empty/order.png b/yudao-ui-app/static/images/empty/order.png deleted file mode 100644 index 47695056b5d33d347679aa10299609afe4be564f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16135 zcmeIZRZv|`)Gdm;6Ewg^gS!TIcX!xGaCdiiw*+^0cMT9ExVvp6=*H#povL%?@jjfl z|DmgwbanNbJ;#_mN3V`jR+K_TB1D3KfIyXz7FUIUfMocuAi#Y-@$!pz`>Y^cRHZ~A zYNv@npEu&>+A=>B6d>q6uMr?1Bdj1`{%i7C2tNx11av+m1oUSO`QNjAsQ>*Ik|7`Z z|GECJ;fitaF$9F5lZ?2Cx+mm?pI5BGvfq}$woj8IaZ;hUlMzFfI%8$5Els+aBqC9{ zV;oK7Jj@$AG76;#1}P#GM};njW$+i&L{b{#g%bemocL-WK5OOL^-40;BpOw6GOZqo zQ_k);)t|dux2;`wFVlXXHnY2BtWAb<1ssfqi? z`V{jMTuA>4_7b-e^E)n8m9yuN(9q2l_2kfjy*kF@+PF&>>X7DW!A0wL6yNpV)g*pT z=d0pf=F+|I6f8@joB`G#b{3EKeV*#XMxuF?kE3;q+UDYq$P9{yH!0)yg|I0Z`i44s zPI$@FftD-^j+hf!FIDLoO#JnrY$2B?%=xR2>;rYw5f%VIhW_iUnP_}l2xc_C{z%E-l`3(OxebbJekQN; zE~n-osX0U}usH4NB3_yv#EU#5)bTO5<4wld_GwSdbgRrf2Y3YAq&|c_LO%Yr0h2E` z{BL))uIt4(ghIa0Q3hI)1$lF$&M>3@AW^w5-@gyB7|~w-DB`O=Q-5TIqKOapFZSiFEa6<2WZF==DqF<(oRY!)d6ta5i?QL@ zqMrX%Rscg-)5!Z@)Mg*4nFe~vZUVimuDhE=ca+*|u*NMhS=BCJQj(EK4pGkI`Fxed ziK6YX5i=aen{krutB8Nywx7p3&|Xb-jovW(0X&C=H}z-Irq90z9qhLju1I#L#k;7;kTH8?8aR{RluX#)f80u29Pz0R_Sb zPi}%y9oN*AL$BY_#Mqvbvk(!&6-q6s!)s~>aGO0bo_g`>}&CADl zwl3SCk;IC1{QPL+zwa>QjXGn7+V*|fQwzeu9h>GjA3NTD-Z2i)VQ8{`FKy2MN9%bpZtN(KBAAKS}x&r7zy) z6LF7nq*X@tC8VW!LT(^#y>SYwu7v*A@hbFC#ACHZS+v3a39}{ty($ML+v-mOxgaAA zT_mwLm<)5E*7Oao&KgwkRfZm>+FwS|7LaBS*cGMYU>6FyY+B+tA332cGkAEa^LHya zf;aS;ZEj#v{q`Cd!M)M_a*Q(MThj6)v+mD7#{fb=Fskk(bwyX0aJwyk1Rw__c?iTd zpTFaJS(OA)_J042N!ddc78Q!;?Cc4)D{o%D^w(8W>QKqvUPBF=d3^6zLpD>z85}(# zq?m9*_3~9w0F+6&_J2M-RwD;#bob<9Y)7xM;HmSy?LE9FmzHdp#^*T~rStbfY0Val zQwJUem1_Ne)KDy1E!n{Mv`LGex`6vJ^cygplYy`>LKQNpdlf?RQryPgBui)Itc_0k zlhlkr!|_9>Mn>v9F--5<{oYV6rXXP1TqnHcM-73I&ry~D{bq%XEE$xjwip+><^PRN zxA}Vg*IzS4>o3&LhOfJ#JBulJfE$HduOWogzYh2?4}UbN&M=mlm_G~+Pu=GY=-!xdB%TJ zjFq^_6kcqeXZU*1GTIEt6j;hBz|>C52}bUaWfGgvFAY7 zXb(CqW| z=O=E{`dr9FQ(U&ehxD`q#HnX3p%xh(nXd zPAkwPb92;X`HhK$T11_Av0!<4R!-&PQ~~$2_wT%FcNZqxe;oI=JVy&Xtj@IgNai$LDYP?_*^D zus7h7U%=>R@iw~cZZ<^?N3RKHY)>&yzSH^YRJ8&yG@)BFOUc!Aldjl^6nT?xzZJFf z_*)$&FDAZV&7s3o5_W@&Oe%^vVWycjSFKAg`tq`~pGV}sF`6wB`kGff(f%FrgS6cOFMVnipyTBw%`Vj=N<7iRJ?Hwx zLs*$fgefBdFMF?f%6;zNy~sdRthaAxhPN3XES#L+;6#m-Ku+l+Q-PJ~-q2$&Nw%~# zY|kwv?sCyWpU^-I&4j=U%?9Kc55X9N{%z^9LxW>`W7&%6A1I8~aFbOft07h&wqE%g zVC2u$p+DKCq=1~9oSLW9Mc*L8T_@zTnODKwfs!MC-Nb(TLk%MPEw zevb1*2AjvmF_)IAj#>88)cPRIYSw7HrPco8Yiiy9mpLAuaK>`|67e~Xk9zxxZ_?_x z#Z^X_x7H@+cj4!wGW#@~;GS zCn3@*M=3RY+%4cgY@koqESqHK$&{30kpo-M42FmmhKG>KXc zx?wdHciPt6X|y+E{O-?`j{GzaDc(vIwzgo1 z3{d@ute01S5B(FR-SKBbw|L;PTxJ$45kK}LQ4a%R7a9{%vF{>nWBl0;OoXu>^BT4J zlH}(Xb8%r&AS{UY4<@nmfGlc%Kt-J(ev*zrkOmU52aM+gts;d0|Gzh)*7wg?u^uVy zBMB80Y&F!7WOgnnwRjaHoWzLb)G2hCir$i5G zSBrE&|7Sy$P<%o3ImgqiM5kEN47H{NO=`7Cj*M=Wo4Vf|s?EDw*QSWsmK!v(-bk@p z^8k@op8gsUluNY*{(A)W^kpsYtIU~spG0Z7v8+4 zLaj&GKz5^(q8B3FD6;_x_>M{!hX@>o!a*?8VMuXbNo#&k;$f{r=aj|Pdb~-bM+`CJs12co-a+ZO##5t081fvb*iU>9g;SG)0zBLxulw`74EgPj-p-wM` zxN^1mOjat{((SDc1j(zUo9S^$X3~Xr%eyS%zOD4P>mAik2^Z;PPjH{ky0lY&X*Gpg zoTxrns|Qb&Mj08&Tlo8DqolL679~UacWEh^n2Y@Pn$6Pk!+g_C9)GjjJ<=C)x3-A> zPLraZ*JK+}415NSnvjjc2|EGPaSePJa8@^EjXoOQ=j;w~k{H;aDlPsoI}2z_v}#PP zC5)nvoFOHiN1s!9%Dr_|9jvcECLPF}?F_3Qb=~QJcmLXD4ZaibxI89*(||_#jqZi9 zWOu%RI>%V#pJ$Ya!QJrbba9|rHKYQzx91uSic1Z_0}m~iQ7Mn?buvovg}05)92GAb z(A|8)8@J}t0-VSgU+9}{`@*6dj5uh^O**1XIC;r>jXmA@A$HXYKYnm0Ws;Y!W?e&{ zd3zi`^^Yb0T0#lI6s788qpI62Hf0w)aV&Wm#i0S7GF)Zci!QNBR77r` zhCQx5@$+_;3tNV5ViN$OPt%1A^_Fp}VKvAJ@~c!e(kMWW1{X%lzKHNGmXTSGt`3|A~P@kj*?*FF_JjR;qD7D{u1TZ>m46JG_{!Bnm zxl!)^AtWpYIvP4`IgviJhP~%ufNt#e@~QdP#^${NL+g)#QC^ou91JIm&HI@{4!f*# z@1+>3H_r2u#X-NOI|*u18gS~ONrKfT_7F=m95%Qg6~xwni!Y(t7Bz-53VaN*?ypz$ zy=cr`p=Y!52Wc2fFeoo}zP@*8D9jZ+W!}H$a17Y*wdjDm=rS=dgE!9?E1FBp_Klz3 zmmPS$JX|a!{TCEcH<<%*QXC@|-Y<>4^y+(}{dHOhcSG-WAPSrM+2hA$B5EOr6h`J3 z7)ebKngI#}MFt6~sLk}6;}xr$5N*-7w=Xc?z62#vRWEOMwj!@(!t>aRoJ{%c*Oa_r z^M=pai5Qz;;L8kpU$n^S-2hu-^Q&jKIX`-k`M&))C@u=_haqQi4sEHgPyACBo1pcT z{{JP=$bU+6l7OHj^6Csjq#7HK4T@6C>bwk9Hn^ZmJ)N^Hm1JF+dVMHJLjO59xwkVc za*p^Da32$=Ml=C7jAV4ZqVM|+q!7xPta1>+HzsDigud6C$@|P$6{$^9mA?ulL~d6k zae@YJiAGJ-ntpQ> z+g|#TKFe%R>2U^nHA-{n+)xx`z+c~8{6?Emu$1SgA3`qb`uyCK<_Shw3ZQ9EcI}$X z%|`51t-T;39+EtphZo9ULBH)V&x&>W=Q70cTm^uI<=wnZKNK>>Y~UrC%+{ zS?)qPg@i6QCdv}_Y;V%nvu~ST4E@}I>y~H=7BxpvMLACQyxV~4!&ZBFg7^^VS8FO7 z#AB~3mmF0pvbUaMH$j=^#`NBEyu&D zC9c$rcxnxaF#7Rx>U#Y^`_xK?zjD6_hu=fC`nmL7`WWP7dv0(EJPeLpq_EZdR$f-` zUG?%-3FPjKH#HI>n#5Z0`eWH9#=njGSYDETWfgY|csbY;v}Y=bJOAt~x7s>~M||o+ zRxLce{(?trg zX3CjdTL}(A^7JRE{?)xWQH3{pf6MRX|JLypOr=Ikkt6f5x4WtLq159Y@jYIy|K-P# zQACi=526dgD4V?ZhF_QHF6(@DdT(~cigK4MA5nfUY!2NGu7n9o*cZu~b8fh~{wB+5 zXgO?+t51oy(g&^sCv0_Ez1C-Aac6~K|R%QVDf~*JcQ_@DGic6Fb z8GDwlYn~ZGy4>C#mk}FU*Xoj_(b)mNvpLhwgR=No0&d>o-IpQ=A_}M(f|u#6M4}Pw z_}tu+T{VaJ$BXSYMRxLxg!;+|*a7oDy>0#9&$ZV`;$eVJ?KxD8^e7<=&v zEgOIOWeG)$zhDHCc+h1bROUizRlO}dZOP6EFLN5UMo>s-6A?-15}Y)f6o=Iv9RA8e zEmQir;?cE4D%(!VVvTT>S!_$kZxSjp`PGa+8kE=9^>|Va?lAO`imzYE;`vV!lcP>9 z6M8#o^#SwJI|cWblU?lum7(p6CEJ}9+48Lje*8lAk*e8lS>sC%9htVAYecz?KU*#P zUn*J)FYRt{KMgs{$I&1~eU4B4eksU6rv&7*J+LU^&dmNoqK zR(s!l`UKw(WFwZYk}ii9L<1$}&_y?CK4zAFtB_wA3Tr%&Kfb(B+xz20;n{oD3pi4+t;1+>H>b7{%^u43-=kf<)-+Fg$<{B8dJ!g{lu_|Dl#>J^I^mkBbx7O0`B}`hvT5z_Pv7c+8M1& zmqjrH;xPKZMyOy6REho1M4KN)1VbN>wh-yWm_Y|qb3h_^0wa+MNI=xn$I58)9pUs6 z=A0D#_WG7a*+T?fucxS?Co+w63Yt+vy?6af6N6ArC<~;NU1`g`+ z(aIT?}NVywkS3&3$PY_RTb%rjwNsL>e}+9|a$2pg@Gm$<-3fJ&6VBoEb8+|uAj-srExXHv>QwsuJ-rjcjEk)b;9!F^XBlN#2$jR<#rELe3 z%`~5iXnkw_l$MxK1U!GgPbV;4I-*)w>_nhjIKZ>RJtBToQH95Bn`^3ha*1vuY#pC{ z-&?{Y74sCX5IxsXn!8Th=au}H@+7hoD%(tj{`6S%gfLMf-A<7QNY9{Qj|BUVk4&QZK9o%r@6%#(oy%ibFmxu@w8IlaNf1H~B>caza+9jtV$0ti!`j@5QLW@fNnYbDo}t5toR2DE*%}*bO1W-h;1hlVn9N*P?nh`1 zhXx~XyIUI*Qs-=Zq2BI$4z%g$DyUn5{dMJPA#E8Jl|VfpV69iNJye0p21k|eoRQcS zw&`w94lHKR5}G==`B3dT2VY0c4V#y)eb0%B%IM2QHfrfGUHxam+ucUPmvGiTTz3GB zq6mIzvdCyX(syZt%^{))Brn`Cwm<+Oc%x5u(J=}3?9Zzmm!N~Y_F*eNQl;BpB=R)S zj$8*h^ocfS8EI{-t=F{m4EWrbGu|BR5kxAK4M3i$ZTZgz++%s1!Yf=Nvt)i-XEy6d zny<6^@<-K=&r0Q6sNdi!<9Sbm)oH>}GH9t18wob>4W?&>q;#s821GG#jYyuqh;vVt9W zeV?XPUO5r#KtgtX-NSKJR4#v3E?31KPXs3uBhk_4O`5&?Y$0!Hc9A`6l~%W&ly2{%=OCu=rA%00-)&T~ z<^{8~ABHYbQTSjdFDFH9{K(}&jQNIe`O9b(r1vgpiz%SZ>u^0}SQ0P% z<(ci~8D-O>NW)mZ)S_6moccR&h9Ckc{S05P;0pXuqdy)Fb16&gWU&3$a_ES{2{-en zY@vO) zCv|44if?!KieI-k7k&L7&h=a7FrBkK%9AeLJXBVUh$nY4l$5QsgnQ2pV`l#u?Y=6$Ov&om)BL`dy!;l-c?^%?%8-aIjz|BpE z*L-u2=2+9>9nJ;F8zL_Hi7lFoX=xd3q&xug5V%4$k30?FkVtR2{6dO-*=eNDg`O#-BSD@c+|K(jBi&Y3R@2Gc6}HVf2m{ z8hvAz3c#dud++Ff*RehQSSP(x^F?4(S9M98{qnALdPNuY+yfS{w2%J!SVGI&SG)Dq zz<#mz^!HjR5}ls8VYuV6Bi9HZ_oNy2Yu@s1$72VP;XHC2jMQQqx2`Ago+zB=L<|3iZTy8c&q1Fa|9 zgoG1>jl3Qw)1~R~7e?$OghW-AfiySgmePGYtznVD;2FR0{u>WzQ8|^mUJvs zl}IQ@-xj2%gU!_N>i)5cOC?5ctm;&0(x2USwb&`j`*fUO)HBy9L zJDN}z$z!^e;mC5r2SEjMxXvXZM(5B1O$Eva7^|>Kg&<%$q-Ge77&1PR8FNTv#abR=e(h8q~vDwg^u%xb2pj7(0; zV6u#sP6X+hmW&lEW=t$&tu9`KfDsDK_QQ5JYD8czALc+@XPVLMDH`}~x=1?K@ad7Y zdSUTQXny3jE!x4#V6k?8|2xXQ!vF*0A1^KT{;S`$3X_X#0)K#?d7ZB?lb@%B2h$k< zWy-PCMD$ATr#2G7UDbDDslM!(!!fbaVWemIX=<4WjY-35y$k?--MlB$Z97q+(z5kO z4XJd0qyGd-55bsospB*%0^FE=b`a{i1iZSb7}OpTiYl%&@&*(i$9Z|OwX`fLb1`g0 zU~}SFL;^G#>BA1mF^RDZGDr@SfF@cy=(E8ovFyrZA&joutx&Iwlnxrgel)xWnYzMQ zWHCnRpb7y|SlzNq5SVey&FQCx&nKS<2}U+t&zTA^?E@}_BoT1Iqk}Yzcv8Xj)8Rmq z(^ILJ>i#W&?l;PyQ>NNN4zj5oB7Fu>A(hbxvwbyw@gR1T7S*Hh0LbRKq4<=`5HNy5 zJPLDtvxhEh?tRis+WZ)%0OhA(q_MJ-P@5z83+J&lN4_)tvV>twv0dB7laypRtfdfd z4@c%vWT*dqvVaY>7nzES2hL1_7ZG|LT`W6rN5Ci%Q=BL~g!M|ptGDNjZ{jLX6_1ju z6kh7PG0|7aOk0leaN`^F?#SVOL6+IW8eKy+T@{?Q;ANQ1Ps%1qJ;{h;0VgCr68h6{ zY<>CswfJ z$2iUIJr$RqBm~q;f?^0gYQo~kuOmPaX91?-o?ZR>1Jdyv2O4#K-A| zb&$TCv*2nYneYulcCFE@4|peBld>igqd_41;lU`}#86T##itR!kJVp+DP^ky<*X*Z z*wPRxmW=sXnhn?(q1PJ4Zk_bu}nT8V5NNTI6PEn&Ev;-T>YirvJ(`!Hg2I<7vhNsk~s@naV_1asG8rW z1}vYJ0bJ5*^-H75v}Rmoo>X$deK_FVpjjYY+O!-%u`NvS^6O&RWZ|~0cjhkNcrmmy zOG-X*ZZw+B8v=8p=wIi&ukfi{t4NNhGBLw2QAo?*GF(Y%XIyQi4Me70MAY=hf`(C& z33`_TsmPR?pp%kjm7C{uu8CLx!(k;PJc+9KZU(U-b?)4b6JM-D{E=tGj8``}`e{Le zsVcu?FzM*l(o)0RgML>x_5SjOwbPx)$4Yp7{x*dDHa1v zzK_;3jXi9B5D68%zR$=Zu(*yKlQq|&FQ{2xR-2RJ?NswmF@k^CHI6Qo7oBG>y!|h z(skBO0-}HT&#L*+yTSX5BW2$kd7;efTrfCS{IFvb_~+_-&!SNcB(I{}c^XzvL|Oc? zyOb``XJBH=?b9U&57M0#rQ)Sc`aWk18pxB1L#&Ooeo-P|%oDzTRiV{yB0$T1hH>3| zMAAr99!uJxg>MKodiBgV5Bd8c4>Cfyp;dLq>b@@@Au zQ<sM)P%hk4c2^ zPS2*C&)NQbwLmY_wFn&ZEFj&>6iX!AH~a}y0rsd?s&VQ{KQ0nGFd57ve_`qG$gmd^ zel@(oXu(L7PKux2(Y%E`<*Nf~p0$hEsMGm6Q1nBcSlf!ONlSwneyQXnRWK)Y<I=qZyx9L9yc}sqE*4nggN2MPA{eupN9XRWi$fSxg*<+FT`$35z6lg^sPbpTMTbzHOjs(3f$+XT4Wyhw)CHF0?7S@6k-uYdN@YF5DAk9D&IRv`b0kKv z+|&grsWUktxD#=IBl5@C2}+wKW{B9=HLb zj*d}~2r2F-KvrdL4{ZdT_ZbnxI8{U`)j#j13#&_R@xXk|uc;J7N9W2_CEhRQ&n2wsHz#f0ooSMHNO`G81Q@+Y$FU>(Vih6+44;&>zYmq@zW|a#qt%fWIqFY=;qC7f z535ld@_rU=4PI`4eFjaM(w~LIVu@ZN_sA~@T}8wx?NZgt%ZgM-q8I|T(acrFai4kT z*yg#SLQ6uwErr<-OZp~CfdR`Z{icBd%Go3(H}5 zvlfSosu=V_Y`?^E;7{9wA+T^b4IuI)OCP_h6c@Y0T2V$94AsHyXiOclVa$+>z=Xmk z)|PK`Pk9VjY!9L3bJKoi_fUR&Q~oZs33eX^c2_;dpn?w6W0oy}hJ96GtUva=@+-qN zdJpK2@ml%cE0WO{)6GZult)Za>^-lA1n@@v}1yO zR%+ImGmzBI%lcY~F;d;WuPY4#k4~F0!Pm`_NcPXJ>h5POIQh2tB20Ina#_31Wx~c1e`kl{DCjF8Rnc8BGQ`{kd(+kF*S<|&eJ8$8M72(`3Hm4@&HHlBSys> zZLoU#U@HgRwnBRtv1la!?}SZJ4KzRA()~eHInfLUT*s#fEb<;)LNS?`QVeN@Ne>A{ zPqA!3p$IQ>GA206pM*|>*Gi4Xv zMNLghL|-GX!@7MDIff+Fn>IT#MBJRQY@RQqIsgJ&px}^}|Hks56N}aG3$Jdix)jt~ z(btl=<7IOR7AH zt5^;mDeQxQ9I=t(Kso`5zl3w@Xg?__dUi*8>KC?#Zx0J%wFG+xjghJ=Y018)|Niid!b?S|g@ z-SU=9;l|vOqo1wz#qbd=zhBFQGrYQCBW-Ui^X9KAnWdJMzn?;%H9wRaEgea~-OnA3 z5#O`5N3Eq&QIiXcmCmZU+~g&;&67U?i@L8mQeDMw>25+mMMm2dV=iAnYR75EVE?k5 zs?fh@u+KX7{5_d1iNeV8IX+{He$kAovd$`&eUA_3KdLoPB@ z8k&r{F^#U7pACg^rwoP^!R#&zpbixk^+diYP3a{8RPj&7HxN(FMh3ChXKKl`Pkci$ z$D6o?CPD%3V~?|hqc>`&hz|$X3G)N>%FGc!03+RN2z5jUC zeTHuTjj_C2!-uS%#pRT>085?A%&of@7ndLFW%<@jq`8b8UwL?#S(~2fGtgUa3|M*5 zlq-x@U?4xrEp3yHC{QjI{2A)`PYwt#c4Y*as#&5Cw1I_*HB9w^ZI!M_|lg;Z6C5#cDb9 zfTtp9F`f(?`L}Q4#J0`_?ce@iF_ zD@KRBF}z(r0g`j>T59*#l8@_abneyhbG5dAn_Zo5?)T6P*n02k1mB!&{vC|Z3ixt# z&HRZ-5N4lqeqXYtSDJz^U_n$5?JZS;7eVk1gs$1WH8h$(_ERxr#Ly2zD8s7xuu|Xl zo^Y=-7D614;fuU0;E(8~nd43}mKH4$wBDWcd4;G-u9U4Uf)h6@p`<>dpWnrsFcoE# z0NJ!O4x^r#;uGIe5F<C9dX&=U ze)0JEoIpLN^u6M?BGrjt7>8CR2cpnwFerE8ld^a^mpAi9&IlJLS_g<;y-JkIYC1tx z5W3YV2T18>bk%nW@$=&Nax?H>W)l5-msaJLwaU95vA4^+;Vw!fI{!iERJ>?1srS+2LjHWX=LY;F^|JXfYS53)$z^Tb)foy~D7)Dg@Ii_|%KI-&d@v&5mvZ45 z6q!0x1L3)I>gQjwLuqLMOaj1Q`7c%|wF??MC4Rr=Vc^zY2vLaWm@dV8Uufd}9v zfs^?HvwWC3Dk%$_lw?sT5#xYVmsosKRvB^73ss1`93L%`9!LZ@!r}VEpswA08BGJc z%AML8;S2k#LIHgea4i*n5i>J}i2uQQDP-7mRY#dJ9z$9yEgLyCbRrT5+j}=Bw{-db z?@}V=kjyXr ztAi4Mk2NrAc!a-%Y0G~Y)M}}J+RB_8p!^0OMJ22`8={hhKJk}4L6;0`T{Q4pjT=BE zG6Y`&zHw+93yxmD$hPueIlrtkL2%!Wm>^(}lVQJZ%vAqK=!meF@!S`JJ+iPf$a5Y9 z&)zw-ZQlKm@pID|A)AbyoRB3d{g4@RPmvsXRv~aiNnF~GN@~JTr3yd#CvwVzN0#vA4JB&N73=4fIQ?g z%A<8oDx`w3G@&rMCY*SUTtgy~3}FjBY`E*1lu@q}#oeaqE%u}HdR6Kcy1vmp>7(-w z9t&W2zSJ9-kS8B7H@SWrCI|i+CbNrZTJ>A0Tq~ef)hDmyz@DW=_V*nfv9L7vExw#{ zS7RlXeho@c+VSk>0!C`eQdYI=h=ts1ijOgX^%xyIpX=Nyu3uoV)HDlHf0Mfx!vEM4 zpklx=?1$v{U8Lmupm{-J#^@U}cy)#9iM1#W zHahx1_!E#zt`;ZQHidv28mi->Euv{=&Z47o#TDTs1L9 z&7o(lP{|mp}gN%K`m=Pk&J7fc^jae*;(a{Ek3C z_(3Fu1(aQXoO?lJ=!m&pO_VlU*`6AcRxVnX{~Ka$0w=qcWe|tWMmf+qHvfr8z z1v3R%Qu)0tmFGYjcrU__t4`un-W0P&{Z za?m3v_!mRV^pU{4(;wzaUtC2E&XmK{D=lx!@yv-z7G0~`$m73hMv*A~^sV~b_eoxI z1PACj?KwpPH;pjIWY}zV7MXOh-E{t2uI$e+6Y-S=66wp$V3!L7wf-ywLeZ*kD!@6Ic5$Ji_z1eEP;N@7I1ysr)-6>R^oBS8V-N zzw&l+F)Z5=!M}FHNsQtQITLke$nz~a=ED046Wi&hVl=k=5C}m>Tvy7dZ$3 z?FtT2BAN(6@jPFusR`uv#&$)4Q#^TsMWJKA$(N^z$k=*)1iymkM4rI|PsB~O3>?g7 zeO%#dc}~DnQIcGdE;S^#eTg-ip$*)_GK%a&HGE^07PS}Mk~jKbOiT}H;oD#?@C)i= zK_}i9F3!DX|8?~W*5 zCPC@H7P3HM5E#s_fP~&FR-oekaq2;z^f4W4*EjYNZQJcVnH||d7EKEJ5AwY8t@R9)*kf?^BFc6jk?|m38AR?*k#L6Z!f@6&Zdn_$pC6&uN>^L#!Ase&pK09yeT0tit1Fl(0r~|{B0qNhHV9RM=+{IK82JS+eqb{(m5xucA+tCN=<&xHd50lL%1?aK*X%@)=E4X|8Y zeM(TBHR!xSUWq6^-kH|W;#Us#9@yz|_J)o_J2(U2Ajv2$W?t*+98-f;Y3X}gsB1g^ zi0XTqGG;?yc1p%GKW#q>tQXqicCGmE4?LvWAiyWf4N()D#xIkuZ8SRp##J2NTBmC2 z#MKl9sp%?B7ui;ywc4vyH6Mn4&}V#&@xD} zWi-RKRr~0(+ntmywn;YPn~#uu%bPs1hnuL!%0`=)y@@s_vbnyleeNTNiSK7Wd>+ZL^CV~idLJ*@4T(gF_rvg~&Zi}N4l&OAq z!KPz5ZPYZ{=z0~SnCrVfXH>SQJBsnxzrjgCF=0Vt{-D&Cx!akcKk9+GkkU1as&;=D zHa%euzo|#dx23xWxV;BX>D0E|Wt*_SMyh3>dL9^I#^}m~>}xsBzti>4@Ok9aT1$7I z#wW&4zX@wLUuk#*?0P0qji=##%aaV!GO?ID6@2#jdq1%ZPcVxPPpYF~B+^tg9_Ql6 zB6&1mlXq}8C?3Upqsed*r5^+O9mJ3u35wEwDnUR*Wm)L!ZkBl1V_A0P+-!JLoZ{Yj zYB4d(E*Nz_roS5MM?70SQcOT%(2Ar%@L?bSY>~O~5gUW_+1HD5v3e;Z_31tE0q*8XcSIZ1FZMg@4Qm`75SB8# z{P<5t3`OYN11%9>&k&Rg*R9&!LoReTV6*IO)zWUqmC^WP98SvufmU4JsMrMUKYoGI zomfO=oUiI*t}f#)zv#~INZI~tt#TmIcp+U6^g`*EeZW9gz2#Mzwa9-l9IUbd)j9!p>ui|%dw31{;$xB@T-q+5KbwpV zI6-3C_Y6(Bk~7T-GzF(kIE_cR2gCn*ZpU-Co62feIAVG9+;tFtVEpp_+Vp6SN_)Ug z&7448NO?o3@p*+pdB2luYLXofejZ^A-+4ZaWWnHx_TosCe1~OrZZ zr*Sqf-#u%<;>fjSxyDdk`dDpfvN3OX)0A&{YneCfYXy~k+?6tIv=?bbO{ir+iua{$ zx5lz?8osupiD(R4J-O)1vzOWy>a-`329$e4@Am&PB)kuT3IoVD|Dq${$*MuN#S@41 z%qi+9h)QjYW?$+V{V~1*z*o>ou5W&Tcl62tP!;W2bbn>?IRf;b@%bjy%PSASfF`fPO?kCHop z`;t%@_Ple+>03Tom3d*o`QUrXm*6-zSMIBtkw#F;EX-SDp07u}j)6D+++R6~3bJE= z#nMsRiV-Ktu@5%J0upQod4B~J7UH!Uuq(8QKC8-+G=*%mxAG{oovioM&%5p;9bRmV zXP)dQyP074ib$zP^LghncNAReVD@zoq{CYEghP-2X>mu9R#Gk;zZ-Z8B&T&<{~%t0 z+n`U{wCE7?k6S2?cIi^wIX|OLY!QMIb1Bz;$szBc$vXO@t$_E;zeHcZGTi#Ol_dVL z5s8zGi&x!Y(B@rMxaY3I)E#6@x4f1#Ntnqfv)DzW?y%K{)<_Q1Nk^{L_Bny}u2+ih zmZIV@w_7-RROJV~WZvo?` zx3i)l?|dFwDJu(FV|EQJbj%p+W131k@}$t1udgneP7e}@I`B*u?6$TIrw7BfkghZQ z1_KFL4rabP5=(RE>#*JG%Jad;XM1fO!*<#r#KlxY4W7V%rK#+k>85713KVYvpEeR< z#F~Za>;~udC7%)yVbKW@1z-W*<;l?qxwP}pmr^^b$#1p97LgW<^D)YwIljtyQkwX z1r;8KZ{C*(L9?mhy6c%1L^-$C2RZCy8cHUfEv|n>5OBj$>7gg;Au+pR=Iqn`c^4HP z`RLVp$8D?TeBo?}uzV-((O`&rHr=zwNr_;-<#BB~PvM|@ch z$vRUCCxh|VwjzV$FpE?dY$71X(QBr~NPPPq>b8&;bASkw_lNE-kNj$-3eVdI+r~o7 ze6=aqd3n*@`ej==QKPBU1{j--<|?Cxx8^XJ@`XoJ=Bt`W&6ih;d5v=&cc7OKNSQON zCro>6zNSmX%Pp(U;wDP;u&Tl0EW8NQro^LeKJsY1o0#4##RftaZV8g^>9Tao)<(VY z$ych&emyq-pReL*olV&Md4lbwqerW%kKqaua1TjqpMrWOO%#M`$s%OSTB{RmnPuI< z)?3D5NuJ@;ib6j|89_FD89huHkz;gDL(8b z#HRVfMn-<92w9xg|JhS%XIn&XfWz=Qm&3o(!kX(y7T9~lNl{)2Ok}5rQ|M1YGg|3E zmHLH8v7u6A&gp-csb9#CjDlBred?x8e}Lh~)xEkQ?_$#xl2ck*I>A)V+Y9cKuAe4l zHLj>fc+O|8v&_&RYK}QI)l&8JVg%S~ZnpV$qadn%D-1w?qND1^ZlF@lZVBHxM)dOX zKpF|=V6nMH)svssW-`?_z=vf-KAVcsiCGG+dR&ix+9y+HE2J>3mf>$9JBwm6Dy>FW zbvEU>u&&Z;q`qls3ZjkHWvZjz>B7ETDl$8@R{15+C$X?h36kLfSrMDnr}e@T1L0Ja zundweY6}kP5@=Gu=ro$(K!F+KWo7S}0oO9^BrlFb!OKQ6BWGT5@Y7k5G__7gPs}22 z-G=Q>e_s9n?S<1jyg05acfW0Pe`%AO*v(5PEw38uD~ad{Od@j@wc&P$X8X>wqh0Ml zQqz-xz#~4Y$U`FzX`J#|JUWt z62StqZ1vas=Ibmpp0r$z`p1(lo@53z0?H2#8BFa=4|laJzGb!4Fb&&z*u7|G866x& z9#t(Q15$dG-^kFQ67rRJLWIA^n|lQTb}&ts;)*)>22$ny6EjtgFqSa?2U~NWM0#tNS>(haOazqQj18b^) zCF(v_TTpQQ>xgO^5PaIZq2T)`d|L%A*SP znMS+38$o+vGnJO%WSJID!3FL4v|y|yN2i+M(_-g_Si+IDqsn0RYqELHciF`mdR%wL z9vuQr|+HO ziH=9$3Ai_usyy->E4Yd0C!aBub#{U}$CKk3>bkP+-8fMByZ-SEc5cy6xFq%FFW03( z;$YUTw2lj5g8s2uj6+t%4?N1$fQ~w=ecU8DyKLsZ%?(7l{b;W$<=~ZC95o1s^fidB zF@c*)Lf3aDB%&1#e^2mFiI^UKKbb~20hj^=A5_4|N_^ZJR+8h@{Ns?GU=lPUNa8?GqC z{ER6)j@y{}n;|pggS1aY z>Wn9!Bft%>cGhM5G-rKA!&zdxMsbCEojAM{cu+f_(k{p0WEuG->=`{I4TA=>v&sxH z!~6`tdM*b!)v1{Iz~3&|pyG_~pSrBNQAFHDAV%sH-Vxwiln!IK8wbpvu4LZE;dsZoh;hl-~Jj+UNDcY+UR_d zO)+-M(S|`^7!NdzGY(bCFGI={dWw2ZVs_nhQC;#nYN%eUl00n~twy{CY`uLiw+>gt zn1DvttcMmJm4tCLQHr*4=EgE{OiR$*V!uHSsTJCA13W#~tb+2KUS>w(D zGpZ)ta_GxZS9>BtC`)^uD+UkC;0?(N)=l$c>~O)j+(Jf5&5j86h@BN}s?}kO0;soY zJ4_f~WosU_NEO4v*kyEH(6}1(PbU24VCIHCzR5emMC}&1hO!`Z@^~mP3H1gu4%k2s zqMwYwoI-xY&m^jdYKj2XQPv5b@AnSz@7zjbo%e|xEPVOOKk)EKrBLM>0t9g9GUqs_PDfKC0uadTHBmKuC$^=pP{zt<*{99-Q7r zdSRXDX&)%vzsP~OOHjcyz9)Tkt0mQTSEq9PW5`w(p zy=o!Pae527hMyLZROGp9@3EnetKJ9H=91t#Kb6q>@Ng@wpD@_^n`5q^sQ%611`vqg zBbhD96%(N^{X)jNha=S(9~AI>_Y2IaFZ+w}OLHC9w+}Di2xVOx88dCaIo#1);(6mV zI2p3eRjx;g@}DtHFseF?c}zz-nO*j0tPkxBRiOAbV9Me38Bix3AAUd#O216hJXDLBzly*Y`F?9dN(;&2P?A|V8_)JkZGa# zB@o-kIg)@j90$(@G@r@FB8fzsM2?#ZxlQPqAd)6AEy2Xj!)-~rF@@{Z%O4xhh-gbv znWiY}8NKGfgF%SHPxy#=j7!OlAh&)eCb(Xi038s%Ob*qSX)pwbq*`l)+wgBzMpYkq*l!Q(@VS5)YJ25lj>~cCT z8*?kdF9)4{!h|2HXeMh$Z-|<`TJG(j}j)>~7>0 z_-wgiI>wcL8=+FQ@@_@GBYvPauqSzcwl#x3W6KRz+o<3RxhH349q?eJ!JK0Fgh_Pb zMfy7lecDp)w_s!80AmHYciS@rzve)YD>oXs2KA4P2vkTq(mr-Fqd<3 z#mHl`%V2}}53X0ZuXloYRcSadZcB%Gs03Ic)gx+aW21_VEqaAQud3;0&HSyGME4l> zm^48RTUHEX+!|~CAY@ua(h21zn`mE$fXebdsyjS9Zn-YhS9IBkl`6Z!a#qyPMMj9T zo)AfJqVwu9VzUrVCK!l^R34E}BxfN7g!W&5+xinjW8zK`asq}2m|xhGo59=p;pbH& z9YjC(BDFyqeN6}?ZZ>C=e`@rqz-5IJXK-v?Mtb+uFim$#SC{euO^(MO9uyesbI8VG zz(8NzlO0Md7)X%b*IVz<7>e)b%T8IKtN8IQmH((-@SZPmTP$a$=G{E^&X*GxqVe@s ztfH^^CUOSZN!8d3Vcqj|3CHinlZI0MLhd=mJ+8iOMuAV{`e`0AAuCnH0OUaDC21sO zU?w$>iU3G}W>CZki`>NvJ6sT!_4cAh7>*{58)fZzfh+EQv^T3}W|u^GZgI{2(-p{eZK{sKeMbDgfSH3)|ohL}PO_SR& zwu&9@Kt`^p=6kP&?e|=>i`!Yu&*d0W zsxrQ4eUO-|wYuwtVb5XOw_2m`?{sVQ)vRQ3>sCc+E2)|36VT}Omc{PIsEkqO#)muA zxlIz>rKO7Rrhgi3c8;5cU5A#NQP^(u8xfR}A_kxP{m%5ZhOni5OMe55a-v6I3yiCX zq5vh$ONy@k$08BJhnPO7PP30sna>DlSKDvyMJtpd@=;1iqwIqo!R(GaGWu|d@o=** z;adT@D2PxBFJs;j?Q!*OCEcy|y6fF_d0MslvJUup|E5vb$8S3~vDf*@#wMG0<4*qQ zAXn-+*4z6}jHx$^R!s51{mFbZF#psy?$*hcR)qnhFvPw8%x9}ir5ss_5?I%eXd`AJ zUdlB<9SeGsg3l}e8&8t~vv&d~bKbxNhk#CX{>42*fVwj`$4}a9R7!l_^EdIZD`x>B z%F#1HlS<4GqvC9hRRRYlZ+3;RQU~9J2z!fzbbSmV89gHslEzNFxd{CS{4!0`nD|MC79ImV%7>CqrtV>{^zKO~0tR@rb-K3-k}xt5?+JmmvYaP%n$xcipKDziCsNgGlzx)U%~_G$lj z#H1kcd6-Ll#_&d=6<-r>sHU8O(oWeeoLjduqup-qf;p!Qv)WN9Tu_~{@d zCbGe5DM4d!fe7;?0;+KtE-(4G+nPvvOPZj4w%vMe^?Hk&u?uJLyB0O1I26^i95g}o z^2&<6A_XX!BsYhak;vrdViep)wOg)rHfcv;5LOq5KKZ@;P!=WA9L}d*sQQRtCJFg# z3U~$5@!l}V7=a*?`3x*JjkGMu=qtC3Q3Ct(b7+j&(zGe;zz+q5e~wsc@0g~J`@w{^ z{K}58Bf)*wEDMRP2~)|V(iabFk$fabifi-BbIbmm6!51vvj2QYBLsr~~6RQT1 zjUOs>#$IPb7jYGHglNkE3HAExj@LIO8*B4XB)QrXQ{EWjwdSjZbiQlyD=h4g zjcUr%bn0BpKKr0TnmAEWn=mxbmHSwTpThN~m{PyCn&q?|1rtP0ycmf<^DRFgq%}DO zpnr2gJF@CRjs#+cijR=9xxa-Zc%}(TM~dXUd2@cX`5Xff#zv}47hXb8;z%Uwkk@l+jvgDG{dfU!D6r^dopY6E-JBCVKv)+gBaIEWK5u3t%gsRgLt1Pl6zgcIzzo&IQTrqo)h z1%G?qfC7KyiD7*-OFQJh?L$QPDcTj#3bEnjPH{+8S07?!G#@NM)51Q_c2ovB4<1d; zDvms`-<|1b$t?Up4o43TbHJy35_ZH1Pxh&elUD#!_vt&f(M_{#5xu;8$I;vfO&IrW z-C@3X?{_~;|I51?tRIw2@eW&8ELrpt3D)9;)QRQW&5pe>sHYCY>ursGCa?$PfL z*y!R`q<(251yly`6@i}T7UQvUa+t+!b z@0iRMDXZ9J+NP!-8fZ`cwX=1iU;P`3!qYajS8rB(e}6e5F3F+TAoMRu5VEGeKMx)E zNV-Wov(6W5H94Zn>bLv4zH~|i1EKM!CF*GLBdGxY?09>lD{)t8L1j$H6xX-M>)Y(~ zFt4SVOlaKOW4AlUoJV0Gt4YpwIbY#-tD{yqfOTukBDKJy(>N;a_@#=ys8556&YqnciEq2@$Wejr>;y}9Z!AU-O`(?Lk2pMCx zz!$pCcd(|1z>T?#iWMkD=u{A(=&%Ukd9VEBpyhO_(6@_xG>-ohmnYR{5=9V9;%u9! zh(^OffN3)EbTHgYQ-$X!c`XQ)MRh3g7Bf0;t~U(%@BtwNnO@V(e8HOQ*FkEWBW(W0 z%WSlB>)WHuMZXXOZrm``|^!4$gNP;5c;?{ABh^a?+uGBN;-A)^>zi0k< zy4~7pGoRN3IiCuelXXRUsgbwr3Y)#Z>agqjQfgVoSqD(pRx9aHXX-?JFtbD)*5L6t z3i}s^u9ibe6~g@hZ}L{VJ*u|csN#}R^cvk#CO*VSPY*7;jpBO8F&s(t6SQ8aDG6pJ zLFL|of*2=u!mdL%azz|-yuB8<4C-p?CKc}I7nhb)cH#@uzp1K?p@RPOLXhVZH zcp+!#=q61JvCf4;!^UT02}LsIf!s?B#3=}9w9BsCVxq$GKS|X1t?golfbKf2;u2^n zl+D|`H5G(Sv&af52U}Jo1R*N<SQl(K$d=mW4;?PY`~wCALRkKOAW8H_%2VDq-f0_Y zMk)l0b@H#;E(}gedozg6Mjsv8d6_F_y)78i@u{8aed>ILf!Hvyu1S;q^QI$$d=a#d z5wr>AMyfb?yYqzueAaPh*i6+ikXc74*roIQW` z51IP^Ta*Z+30qSPW| z0qFY2Bg1$m(uD?TD!BW}TWVdN!xu`UY`U7id-}=SZJ#7Lx9s;_x5{qj4jeYfL3)w* zEkz%ogKIRkMAR1(<)9M3@=SA{zHGJ-&EZDEUcr67z_{3yeY%W+8{JpBUAWGsD8VxA zs!p1<1GWHVcfRg=eGOB7)r7OA%yCW^mIY63yQd>Ewa*q$4YiGdLbPQa33Vk;-Fsgi z_gx3Cz_L#`?adForGWE*#93%LC%(ChkT3P_ivy3CB6+)m-xdKiKZko}i0POl(Vr~z zt(=;VG*d_>qzLQhbgru&_~F zEh2k|8*6MTO^Qe}7{Uu-SqPdFAGf)CI#)x5{Yn(>s&SWVOTkk~=%FV!KJ#s-^5LM+>0mmGefH!_??E4$47Yj1KnGTrBCd!2ky+*K zxOaZdyv_O9z!#U>rKwt5DzrNQ>#4LWe7ZAQ_$|j=-e!m{G^=|s{KZ!N{_!6{2D<|G zdb&Amo^o-0{B+VArrhJ86vKNCDKqe~cA}x1Y3%BT9sRRMSt#_pA3v7qk0o~M+xe|a zMU~E@^+xG?tA*P07ysqeeal*#k;Gy~n~^i#hyBI^AnfMG1tRc?{(~v?6)2|m^%)F7 zhn5gUr&aOw^b$@y{MzblQFLPV`hrg}PmC0#gFjU_cWLt^ z?TR5s*0vdNKp+)Z)#*YV$P{{vkbU{`Cb{M{$f){8*05)J?0-uaoxyUc9_~akrD?wd znsAreXxrLQUsy=$c?3{RP71qM5%ByIScPVy<|Trjd0 zmZAs}%~`WzKd8A|C)mHg+-lln^)d85A!zqwY|j~mE#=2NboU<$$n~-~@xA4*op_*t z`a8xjoiYsrRfBJruZa%RCob*vxaXE&ipRh?3A)maujX30dr@tE1UBYic-Cj zLCFk;ItHpfk9`T8q*`+jf4~jk|Du8Wcg#7n%WHgm3?&9jFDILFw^q%`Rn=M!?5jJ@ zk5!lMezTgmk?Z!-oofJCsu~pkX<@nKCwKoqIJV`QS@_uKA6~6mtF3!aq8+bPagzf) zSa=_g4t;`^M)iXk#_Brr=`>d?!CGclQ-mh1Tu9u)eMvi~-Ar+fjVF>yC>-{tMp)M9 zm!I6s(FL5P84PIa_y0{0=~Lyv6{zn(MyH%v`^CxDw?xIcG`#1UG)_|y-Eh%Trt|>m zYX15f=(6SY1SRhES@`eOpP-TcO6`l&SYz#G)9!rQES}Bkx$hCoogq^Esr>>@KBj+R7lU6Mc~eh(L`^xP+^+>ccYLB|YH_#7 zYpcIf38;BVK2Yfa`Wd&CmMSjbQkTwjja32F^aR6%Doq~ewd1%qEKiwFE7Q7hlw$^ zUg>4J&@(9B$X@LeN5|Zq63URB{G8n$jaU5_cJVc>yg~7vGpmb7>^D_`>Y1xBVn>O` zY1f1lns%|Kwv5(+s*4yP5;nHP+ca40A!sKo&-{=E2GO?1wxP_Eu6LV{(Uy!8_Bd_# zX9g>*ta_`i<57DC_MD-_i^FcX$aC?%HD4!(17WAH`_AO8GSiUa9E*_MpG{Kj zW5~1Qk|qqK37QxT4E>I->F#{x>Xl`+O5gL39hCEvTTmoJJYX^ zN;;lMB7V)-*wGdbo~z)m2cIRX2=C}p0-w6V3%7M_vSID9X%?9k^)fx%a!KD#(R^7s z-C$9aMgfApLtmnLw73%@IVVwl4uvky_4-;6O?p>rMBUW#wC^yt$JGPhBbG$DYjlFp zFxS?YK?U#|dZf&_|wjt(QX7a6q>+Zz668%V=`Mk~@I?K#mG%4R? z+Nhi)wE zQ2LM^OsZ|VkyZe3+3N>@8E70%x(bp>HZAtVbNJ(wAMBxKfu7T$;iSI5UI&v>Ov;9+ zYV>vPCYNc80nHpx{>h3$J7|Z|%*!7=2)bqf2oQ-9dGePkT> z!d=&!KNV;GcU)WMTPpt=ESfnMOFb7xFtv3Pb9!iJqD2kIXPzpB-;){SvO4*U*r+S?_+sNSoVHJ=7kqYh; zIKB9hOT6BpXGgt?fOq<=qYQK>Q{hm>g~?uItPt!v?S~(mJeJahoeC$~)C35AVAac+ z66nj0B9p`8B@Llg>Oqxb+R+ZMPQmEMDws8AuKe=nlrEK~QMW1ktQ}6q$q&=E}W}!(?!6 z_Nma%{6{+$KUO~<{LuV&U?K0=9yw>S5}0aGN=pHm5?i&V$RtxbYr zf%@|jAv=%SZv@?Y@Q3)Eg$TX{wbmj#)YGZ(o{ZCrkP|TawQ(xxdN7O^g($iU>j8tq zp`BVESPkd8H;d}iPufa8=KjFOtkhrz$vP_tGKl_{hL|bb2@5zt%AkMy)`ptNa3vpx z$+K(<<;;`{>!~cxK#ndV1~cw;A(o;Onx(YaVZ$(k6*2xN3p^ipViA@dsYR;|WeW!# zOg69*2L*0SYtsR+z~ju?CK5803U3XpOrD#Kxk*LA+rI&!-Gedxaj*PJI3E?=lYz3- z4V+M}lS=DPE`kDZZ)au(qmyiTvXJZW^9fmh>!M;n>Z z(ti#G3zu2&VcT*uNch1ULfX7nIL+$&o!&S>Wvs(8WS)S%-A8W5GYw6%bpH&~2=(!` z-?HO4>EKkV9moQrcxJ&Xv#-axN|@>y0K=qTsbaV78<`?rt|6Ny$I=51^uiU-rNJPF zF`@tukIl&g8&hm<+^=au#jD;hr8}QSet)x}DQ0Wqmw%cU*})tPFvR*7pQBBH9#b*{ z$TC5EDZQ*v65{78Kg2ZuDCaI3J{4um$)$`K=91nVtHRbsMXis3bl2!gg}Y9d`aa^4 zlJzEO+ArZ_;o6|WQL?c<0fy0lKnIN=@)G6=S(c`-;O45`&zXwa+U`G7?cQK-gFPe0 zeM|6Lu(L=Yb~-v{^7Rq0X{V%Aa2K_&uVYwJ!YPzTVzL?v$>~LX8y&6|IZb7VZ}QI2 z>9tX7hBBqU6lDkYbX5u!IVs`v`PA|-#+ByXJ7QC$k5&fV1uX%w80r? z17v>H6U97XZE4d}RaQMb4#iKla2ocx@5hQI#I4eh&LI1N3vZH86C=09NEUwf-ZwBL zZVE)#2!ePfZUX6BSY@f1r#};m%f(W~_eG*h+_?`8>P4(dF^R%&BQ6%$7cs65h7q!= zT~gJOw@Vc<*$AdqV9;%Y9n4-bkdw4%qV!Qp&xp$3{6yg|(&?eRQ?vkG#rk~+rhTA8 ztrGpxh;w{9kIA(`&dPt{wvRziBoQ<8$6q6Z_Q7Pw=#vxFl;VeGSYk zHdUdt+l%}P8UYgxUIL%6QIWlFyawVO4Da|W*8(bvS{_NiYW5`kUrKCw$9e{oD*HPY zmDvX7uX9vo@*|JLqF4{}b?SAFp2I>kO5AL{yy8@9kLZ84XyWh=zSh*bkB_^sWn>vN zWyH@13-8B%(6#^dGAtOKVoJO_zb*FA)ty2e-#x$_f?j3>tFJ#nS5tn;NC>a&N{MXD zLGscVO`)O)D-+U)m@$HKnaeGl&&Q^qhhUpUEwxoF}8{mF?jF~_S?R3()L%csL|~H+8)K4?2~J*2FBXzLWXm)s?7PxYL!@&*wboHPJmz6>xh{f z$UEsMfR9hAE3M5$1aH@GY@Aixc^&hgdU4SPUw;l13o@ zx^f#GQ)sdXT-o$&8a~sKcvDC}$Z%c)T*oqP&+#`s`(OS`_QEGIv7{(HC}_(m>oMqWMu-;s#pci`+~t{MNmiaT;IPtT{-9z|QBYB9JQ`f>tX04ieJRti z`&++Mx90;9IYg64Rkq~MU&L%FAv#eSvjUx5sKhGZHyl<6;Pvvpx7uCUp)SD%7f=rn zXEmqv(}L>vyj+rL47ZTv1=t2#m;Rx~-Y)f>M9}ZuMJKyy)tEmlpBLbuXXy_Cx_V~krTV~_k_^L|@U6@1 z@aPS$b%BENdE8J{-h z3T=?zifyd`<}L;z_!4-2Dy|%0CmogmWz|!itQ$0j18|%t$S&2zLTJuv#R3?c>jSRm zy*22M06M+XeH8{;VV27TJnr}Q^+t;iD=Yih)6N7xBk@Z#w7!F%G!D3kHCn*HvYLk% zMc$ykp&|kTGs#USC814Ko{0H-jZSU50G9Gj9qvFNyGn>bJOBk>2cz&4fhhnJ`89uz zBa_ssCu-bvGONf(hNjbnNu{Hyz&#R-K#)M0Bw00s>mhnMc(<68n!rSd z;6MhK*0dyRwhq%|5L+t)`@iaN^k)cY?b+{J1af z?(XjH1b24}9>U`8EPJ`HaqCvi19VM|bf4+-O>eG2MMv?F6rE_qU`x-qpvgAEsZ5l) zpLnjLY_jWYf5UtG$MJ|?X3%LdosqGso=zn-Fmd3l+|_B>aITZjt(7%uT&9~`kit;! zJlaSM+PjVRTQAe~3^3)fxEtKqjylMj5%3nlz!j0@|C#1RBH1uK_p3N$y)UV4r@pX7 zn6$r|Lkv?r*O2Pe$yur@)IIoq&CpmcH!??^H8v$b#Ro@orGZDD(0^kt0oBoU#_Fl~ zzXB%wfkM1M^Ea90?IOo{a9z{A?=V&N$fjGJUC}Et??;4-i@sp;(z1348yJ<((A-Z| zR(7)6vojbD`NzrMv*@XDoW_G&d%XA$1K%*z z9|j_I`!7I_)dAB6g4xb^uiYVGVX8GCWC{zhTrL)&$P^I z^-eDv53oBI2(w-m^fQ~!{}du7)|+3IUk5UjZH8HAGT+%f5MQ=k+x&(Oi^W~+{5Lph z;z;^A``GXDyde<{o~lKfD1!PLlu z>8$&_0)^%F-~Z(fdJAulT2|R8p=R^U-zCEA1sg*N*Jgo5J?NjSsH<7bkrZf0f|Cm^ z*R+tczrdicD+#W^1+W@orOpJjj7de`ujRAQI#Wf00L9}1GT!I{2 z<}z(Y)73ll1>C^d)4!iDubRwnt(iF109_Ezjh{!gndIjX8`qxO9{&S+J z77O#5wAMJSv+XdwcN>D-`%CmFrL$;S_Jfphwaflh0%K}wer4+25U|^x$(LXPW6PI8 zjn+7d@k1*5Tkd#VVo!nJ&`5}gqd|VozK4`e^FJucC1XjVDh0GF*SrYc($j1@J7EV0 zpiz*L-gA!&BWMvxk<*$GOQ&Q5KuSZNP2d~VH|m%80cvd6t8YESN-e8~N#o4ap^0%O zVSfXnx#JtO2Q#(39qOtWUPT=os&^FDdspjAJHe~lG3)abziFwe2?V;C7&OpwyOt!k zzvuajJFogLzlTCZ1gIh+ipz2v0)^CZ-D8xjsWjnm8 zq%r8$tc_HGBGV|2DfKN_{7xOhzKHzZS`o%k^a7Oo&LZL;@Z~SEf?tP>usRPVFJgws zr|;(9U^ zNk@vdlqKiimEuB>VFRZBSz^gzEVB;?YF2_bhtuM$RV&0&Zr9%`3NuWD6Y@UmP=|+H z?oFMC^sO?8w~uzaNnhH>7SK6od3Po43^FTAJ1{D!L#9?%BSA1ZviL$PFO}% zEGU% zhYY{x;D?fdsuL{zUolnV^Cm*_UYfBv&7Xfvj8de^fn01Kzn(h2*|V6c&O7uT`o}CA z-_&z$fx@WrfFI8=8+=Qg@n^1Q1<)0gqB2oS&)Z~S-z0J%!V|NMU!?Y*lDSaWpO(W= zC!9;tQZG9qjbFWZJ8lX;vm94&ku;7ub4P5h|63NW>{nONczq95`y`)$WS97%V(z9J zivsY-6%nV^#JU78x(V>!2b}*r?2eOtyGd-NV>0?WimjS?_Bt0Uw)2G!nRN?&EXEjV z{g{Tqq4CwP0PAhM1S*nMj$eQ76#srIToOjS${(1!DMIx2O27yv%z^i$D|H4_sb-eC z^a&Kps^-kBrMBpKchrGPH`%6OKdTH(V1ad7Z5x<%@jdYUJb}Y{=LOeek-^Djv3li0 z)Zd;$j#@mRHoA&*x9}nux-7&5+_YrWm^L)qeGqB#m>8xqx?7 zJu92FM%T-t{ks5~04&x0$9#;q+@D>t=Z@9_XNRBhLkjc@iaIR})u7Al#Dvwr71|!j z74R!qZPLUm#pGL7s=O@?-GA8S{k9$Aq4;t4=d^~SpJ`ndSaU3XlL1HQsHs>h;9y~fTy$Up z=6J%4`O3O6!gv;!SVpu`3;U!3PNhz7VXeFtp4l4mEQSEa^k&~p$n}0oC(j%)MAV|t zMer?}!JAA)Y%1D@lNVfN;POKJie{hBpe&(FY>DMOK{I;6WL5>{d$QdyXq2570EHD0 zVW((=8wN_(fTo_sdopysNpM0W+HCMK;t&7IlcH|?suxe2e%QDXf~xUC}FvD)pN zNNuPIyn&^`CG7>9;}|9lP8_Z2M_({JAI_92^Kfg1Q9%l=a9DiAIP#UX#0H98R>(!>~ z1+ugp$a}%YCT$j-YnqQcgSU4i@Ywea9dg#4RhK6C{&AUh=TT{HZ&i^h> zTz0)B;eAtlQCv4~yF<5rO3{z8%f z!1C#59X9z29#qCpQ2SXpLA=O05ewofr9qw9LCUT8?`+861b;@PBU?JJfs7}OeLiGJ_;;}zH_H0ma%yQmM(&VrJBo+l!3PBbF0SetMhWD+@wvIqv2GI?bj zv=}x19f(Dh?UKR-G}(Hx(tPx<9)4L|j>xsOLv4a-r6|stWE#~+>jD_WBIYJ0HT{N?f^r_URbe{hIstVbTw&cnksI;XWazgZfYZ+K$-p~f;SBa*wj|91<~ZL|#-8Y$ zJCc}GO^?P?l^ZWDj%F2r>yWdX#@V`=*#gkOduUYyHim4aNV}s=AiA$ykxT$*sFH`> zXJq@}c0{{gOWfMUaIMa0c~!UPqEkGSs8H~MZ!4D!P#{YV?} zCCIt>#Y+S6Ve^C~;R$A9jG`p*)GkDfr7In1Iz>Jqoyl9yJ$qd@nK_$1ti02>N3gqk zva7WA`^1I$heK>ihAMXe<3?74>aZH^A*1(e%&WSLWPgKQwTqj!9`ij8%BX_*YT6d) z?y;wopo2X{rqPjSU_YYYA)OCu<^TBW`6wSs`I-R{__Zutu2I4%IEkkcLBl>K9m z2y5BOcriLm`7yhC@D%Yg#eEq=>587?iK+d98v)6Lg#oXRT)vz(FtW9Qr2B{-fEXfX z6H#m&6yz&qUR9}Hbvi=7iVG@tJWA3O_x-Q?U2L@(l}n#_(3Z4PgsIp+@B-bFr6j=* zqug4}+oB69Bue={wRIZ?|8u5wv$PEo!oIaOG{A2_)Tomtn}pa}j(ECIBAcMUsf)~N z$Vpo?HT;LPBXOX96eQn}F4nF@t9oXD5DQDiu7_T$99T7l0w#R_)}-9GTJxn8#ziLa zS7zKo;*Sv}j=Zmtcc+v&=!f?vz5Yfwa&2MBk1VZ7sWZDg=g(wCe`n2?#wWyjtq4%n z6s>Zy9G`SV6CBM1xRO5y8E(anbu(*R6}%5hPcaN8ge$7oS^%xV+r5R~iC#K20{yo? zM^rHq06HZ(*9~HpL5zUNJ`bqg9B&030|C5bi1I3q9732U7-S>>YQqGoq-;r_cNUc~ zyW5EJj;iFucenm)j->cxUoaFETR-+?Z!KdRr*?nEon|z=7*>Ci{*GEmqG*t=6AMa;ZKD}(UXJdfQt;DK{;S)){oyxP|6Zu21fKF zm;(Y+YF7mo*qoW@i!|;0`JW@O{hz_rsJ_O@Y;#EXlwvH?hB!=xAey(Aifg^8NR z8Y#^F92ov0*eK8$8$EzyA2HeN9_kuIV=Q(guj$DwNLVz) z_?3vk*9Ix`Q>I-yQq1QW&?_0)uhJJt3kTTz_E9KKZi*7wX~{>dl15nUSZjfMXIN#+ zN-L4nez!P+vI=uG8|N7#eOxTZ$j6o*Qj%qqYfRp(^_N6Q0QO;Q#~onlT5tSs9-nA6 z7^9cf#z~?XEaH5hIH8;7aoS^a`0MlmiU5?T1eZB7@6vun}LNovuxD#NSGRjyFpWR1{_ z#GwJ=Kvaf`xcKDy4jXOl!W-3Gj}ii;L6pEqXTX9QD&P+eGfsSax#pkm#Q#d6Y6cBL zAdlj5qd({f*Uo9vHpCwZER z6#+RjK8`F+U7%2|%_J!s06o?)X) z$CmfU7VMN3+c$4k?Lx>GT>afLO|v2$pT_dt$GUwzHdx(_qV}ZI%Z0{} z!>Yt6HNHMd(ND5`5*l%N;pjyHz&|RF)5sdjOSlx_02rU1NyWbsk;;-PIE+agw z?_Xg6QsNmlEY6pAkr{oe5au9egB;2HaoQn4lq^!G=PW0h00u4*W4a~me&7l#2@PQy zv$EdHHih;*3yvO+)A3C4sEqd9v+~ZPnWU+V zPg|1pCHW|Cg8X+u#CM7F(%OU_g^MC=D&a}aFnRe`X3;C;dxOGS?Wym=y73{GZN#i8 zM`3q0yHlWoprrh5vWJ~ZIg;aUHSV#54S#x;Dt=h9ji8of(GxJT|!?q5?Balt%4+DQCRZ2|kC z70vre4>fBLBXX=YiNI>Mh4cJYlNhRPR!062*Lc0a+F_M_E-`NR!M`xW9g^{6wq5&# z@|GTr#&pXEI_@4m1j!I0tKv$6LMrg7?OonW+O=}8QeH3O{QxeNO4Ie-^Ng&tefD~1 zr9hcp3PP4BqJ)Gd8U4MkH}s_RR*>k*Sdz0mo3)7ZEnpBGdx_+!oo*)BkY_KCqK29J zxd9YBX{B;?35$9*kf=^X9{3B3&b+>lTOQ+S*M|ge*ze^GD6)mED$KvMOPEs@7XmoI zc9VQ>09afc@Z|jP-2pz-?Gb0mD3Jn7|1M4XFM)liApocDHepZFz#&*nqkB3XpN$;~ zXoBxnXnVa7T=VCrIDD5!WfpIF*yo$>mHXz^0ZBPY2~B99?ZZx;<2L~iIzzSp znT+ZhLzXtbk@9S2q*c2ncJMN7@VDPfzd#qFmwa#PL|4o5mubvqx&_qT;P%g(V!+Zb zjy;H7-%()M`6vwboqkH`CR>Vsnl5$~4?kuL5L;qLQDNyGAA)K7dQg&YA4zALcGULO z?Dc?$K21oWSl+=aIijS#lB3F8g`SFf z`h9gl4~T_0s~xU>t#n3!?cHfw0#)+7dNKtb83YJj@H$uUuPm%=zMa)EXhTpf5u-n& zQW_)&+E8c}()^k8(gf9o8jy=yK|T*JX?AyUK)9>L2GXM2(CYO51&vczk1wDfm9UK< zi0Fwx)}>3e{oFh?4rePrny1;ppovx^@v7j3Dz~4HfWhHq7K5j9tIR*G)nX+^=S28C z)MA+{Xkx2Uv%)vB7&Db549m*;m3|1JMW%3jz_9J@ze0l88v*wL_CrcSn6darDszFw=7=6>{Hbx#U`7WZN|MT-pAieBHz1=R6*E3@Q4R@@hqC4e%?Xu7T<(GCqPGq zy|yB=t;hx3Hz}Or(=4OCevskUnYS;zH#PIBt4oc10?v?6oI`{(4^0Dy1R!yujf0p_*(VTGcTBg*e z^dX865599ez8BxCca*{7!sx3W16|b5{Z=6*;+EIppP+g&n03shaus`GEZ^-4ww0lK z{bmS6oB}XO!K+3DDte6eJ+;kh&*&4RQM}xHd%CiighNeul;7?JjBRORI%$O`a|u>o z%I?ly6368u74DTt=W$qJ>0`WiA_dlmm)B=Jar#$iU(?Kg7A;)e zmywb^BMXkk_?ra#QT(X|NN|26U%pR-ITkk`wX}uk72AT9Bk>SrU4a0ClArIfOaFg! zq-ShrJ7wu?D(tLwZW882ZUyplnTvK`0-=#ZX`}f zk#=DKhrFoN#WMY2p`rLroR{z2a6>69R$!ih%BHcMOgFm;7J1cjr;V?b_g$GQfSIb-{S)li7_Jl$^H{|6#hJf81Pw? zIszeqB9LTqwq^A}XoR0X?jqOzeMdu&y{X4$ww5GI?&fm&L1R(x{?~F{Wp8b5ZKd0d zvk`ao-|6#>aFZJv%~9qr@pGU zsa?`5WWYUaIIh#{q|3KEWCXFEHTB>VjT*1UrddBRDrBQB+)ekCO>g00Q;^JUl8A(! zv4r~Rwn}`@t!=cMOH)WrMO-9gTrAuu2L-`@X&N0uZ1c6p2wBM~jeE9uj%iZxu2IQ52k}t1ze}vR zvV2u{zY?PHh95W5SZHdZ{Hk->bDr=EgSx)_?gGEch7c3>jOiq|OP~nk^s9{9>+>Hb zafJ$SFk)pv&3DiG+p9>F=KAVuRZ|f!_&f56&Z6t1^YOyMsqp+ajKAgh1l^cEgYr*% zqg^8Q7rRbd9+h&rO^H`gSv4&yuyOISUcLSNm}|8?&yrpunVcgm{Oo;9C)3mAkiSM4 zaA)8nKT$u~CNelRf$!F?eiR91bsN=XbxMZJHs_C!LoIN1W}p48g~R7h8^@b70|7um z9j0#2f5xvR*_Y=d{)#@7{r!Q(&mn=QZ>DZ5pr!^wQhWH0OB2HiA;n2zX*n_m? zgW8P2NKU1rk=3~}qdQbWE0FNi{P61GTB_zm$Y92MvZkK9seQp02B#-_K^5}VWknJqm<1ci}2zj#yo6We}|*lSBQLDt0^s}IzxG{43IxJPc$mzYGRLsr+BAcd`IzNC)w)sqV|6t#LMc3JC< z0?tdwfR^vlm2Vto>c*#V{v^9X;V>CLU>#8>g;%OptP1jv`$Q@fbe)x6Mgpi<>p zEyT)-KA56!_HUzo1@dZKKUX-x)Uw%TRCww))kr&Lcb2FaG$41CqCL(Z z0XjM>Y3bdK;@yefZ%=O5d{w~>q#G);m?*(|3OtB7xUH%4%|i1fHD4XhXar&IDdy^0_5^U<2HB&F^*VXzQ6A1S z!>0C{T?f=aH4UZ_z2MUdAAT<{|Fx|7r@vIS&*vt#y3%6B3-Y^9JzRbu)_%e&pSIr~ zRcdOUg}WzmxAYZK4GO68+M?9mQ7VRmWw*itILwI4SVzOupHm%U1s;d;B{cRE?ta7I zkNG@7X#jwisD$4_ZPdK;mCusmr8;IrD_aGh0#){}*Z_n%|qs^q)HZ5e*`+uG-?(RHko(jcZfv(ZH=UhP22yIZg>3enROtzplf8aE3 zxo~v*20TM1?s}B*XN@B>>{SScjm$PeDA`|J2OVMB=c_}OU^9eBuW=*h*|xd8D@p~s z5lZ(;WX0&~A6_V;U8AsZ!r`|p2n{Ng6;NUr6(L&C6FR}ty#yS2)yz7zaXzD4dia{n z2@dar6cEb80Pa)ApRbIS{;58-3IE^+P>nooMpRmh?!He z*;#a7hKe!>8;InrN%p=$)aC=shu$&RZRHIrzcRbp*8my2whQSpSqcoppax6EBq>+f zKTc;zAVSo-h=R)*lqJXOgP#Xl9$tOSr6sf#41p9r>4-G=R`O#a5W^VjL zEl^iK)8e~KF_SxkU1n%WD9P}PAdX`xE6bId4}2B9^`@Y z2Q>KK#4K=E^aXiA&uPdpSIbSZRp@)Cx?ltMTTKRDKftijtv@h zV>rM*l?Oo8q&l3&>fC`A^x#U~WKww-nRT~q<+=~Z*0p@M?KtcXcCuQfq45i*y=JKx z{C%UD121^y*WIQ6tcUM5Thr>b(?42*tm4K9s<8olSo=@!srSu~-p$$D0dA#?u7}oH zLVSATu-M6&)Bgl5%f>_>9x}${$`W=ggGy(mf5xeqS=Cyn;G$a#J1P|0KA`HntW3Yi zXSMt41zG%`HlQ907p3#Q6N1f3M?mg?_suB;~@WT61oVRn=2tM$g{G-5v8%m=o~(aF72khOD!0 zpV#3RJ@2_%j)5)702}-Brb7lF1te8uj){rW8$CF|8GUJHZ~{`qmEj%JKA4WSB|%JEl<&SXH*phQ@n4+X&fYD*1}X5Jmyfug3w?v=tPuUS5T4Xj9^(5 z+}8Y`2)0efU}lVV+AL4~&F|5xKd_2Pt8H9p&w>-ZrAj`i`$>inrYyhgc%OBS2;iyt zI}GI{|Kw~c>LjoyKpK^BLlfHO1}TaGJb1mcq6D?G1S{qcp{!v3gWy!LJ9|J4zBM&o zIL(sQ(@0Ek?fa~BA#$u)1XKSOteGjs$;^%*gkh3f zvm>zs;lGvDDqpX6-x1-9DThZ^`)%TXtI$~y^ID5MJ61kk$0z5|qAFbKl(2uZLPI;3 z93Fi;z=SQ1lX-r0x^^m2;)z^Q2l*NA8204uo*T4zYi!@zx46=JORn+A^}WcMwT_t4 z+pc^n5X~~uK5nPV9;MXql2eOC1F|Gu*@v-&FYVH5dCQ@jy071v&#*&JFT)w3b}MD` z_i6V#`nOK!T5TkrhEK!wb7e9miNEES7>FQhT~6m<`zh@dLhH{b!wf*vCKb|*VpwfJ z&Je!g+NYm@GGD0`CY7KXWP0mW-~#V&uqdY5Ne*mhHon`>!ND9fS$wbWDJFy0li(wU zp8j*PP>j<+@AX#1Lj65TWY;p=WmPc zW(-t&zg;{1d}Q_weL}ar@ol>0O1T26(Us~E`$fwC|HuE`888g*gMOMkgTnaJ;8OqZ P&u!8Y3gWe*hJpVB=W6Yk diff --git a/yudao-ui-app/static/images/empty/permission.png b/yudao-ui-app/static/images/empty/permission.png deleted file mode 100644 index 8142421c0382474a78322f5ee55fc431d1576e7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19627 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 C-aOs_ diff --git a/yudao-ui-app/static/images/empty/wifi.png b/yudao-ui-app/static/images/empty/wifi.png deleted file mode 100644 index 13cb10a3377800561a891ce91e142ba1500349de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21381 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 diff --git a/yudao-ui-app/static/images/tabbar/cart-active.png b/yudao-ui-app/static/images/tabbar/cart-active.png deleted file mode 100644 index 5e9aac700ad5efad0e5b9929873cf82470aa03d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6304 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 WJdu%}T_1;M{eYg9AylJb8~H!=pJ)L9 diff --git a/yudao-ui-app/static/images/tabbar/category-active.png b/yudao-ui-app/static/images/tabbar/category-active.png deleted file mode 100644 index d9bce99f595a0f2f5aedb89af88c2ddade95e29a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8172 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 TSzie6sR1oDeX!!r{fPeq{EyYP diff --git a/yudao-ui-app/static/images/tabbar/index-active.png b/yudao-ui-app/static/images/tabbar/index-active.png deleted file mode 100644 index c5c8352c44ef1ad1a9f323f95778159d5bd8559a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6891 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 diff --git a/yudao-ui-app/static/images/tabbar/user.png b/yudao-ui-app/static/images/tabbar/user.png deleted file mode 100644 index b5367d4cd2f835025ce4e3561832343264036b9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8070 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 OI-stigDO?Fi1;67LscaJ diff --git a/yudao-ui-app/store/getters.js b/yudao-ui-app/store/getters.js deleted file mode 100644 index e7ba287be..000000000 --- a/yudao-ui-app/store/getters.js +++ /dev/null @@ -1,7 +0,0 @@ -const getters = { - accessToken: state => state.user.accessToken, - refreshToken: state => state.user.refreshToken, - userInfo: state => state.user.userInfo, - hasLogin: state => !!state.user.accessToken -} -export default getters diff --git a/yudao-ui-app/store/index.js b/yudao-ui-app/store/index.js deleted file mode 100644 index b33c258e9..000000000 --- a/yudao-ui-app/store/index.js +++ /dev/null @@ -1,17 +0,0 @@ -import Vue from 'vue' -import Vuex from 'vuex' -import user from './mudules/user' -import cart from './mudules/cart' -import getters from './getters' - -Vue.use(Vuex) // vue的插件机制 - -// Vuex.Store 构造器选项 -const store = new Vuex.Store({ - modules: { - user, - cart - }, - getters -}) -export default store diff --git a/yudao-ui-app/store/mudules/cart.js b/yudao-ui-app/store/mudules/cart.js deleted file mode 100644 index 1efbf8211..000000000 --- a/yudao-ui-app/store/mudules/cart.js +++ /dev/null @@ -1,28 +0,0 @@ -import { getCartDetail } from '@/api/cart' - -const cart = { - state: { - cartCount: 0 - }, - mutations: { - //记录购物车商品数量 - SET_CART_COUNT(state, data) { - const arr = data.length || [] - state.cartNumber = arr.length - } - }, - actions: { - //获取购物车数据 - CartProductDetail({ state, commit }) { - return getCartDetail() - .then(res => { - commit('SET_CART_COUNT', res.data) - return Promise.resolve(res) - }) - .catch(err => { - return Promise.reject(err) - }) - } - } -} -export default cart diff --git a/yudao-ui-app/store/mudules/user.js b/yudao-ui-app/store/mudules/user.js deleted file mode 100644 index 5784dfda7..000000000 --- a/yudao-ui-app/store/mudules/user.js +++ /dev/null @@ -1,101 +0,0 @@ -import { getUserInfo } from '@/api/user' -import { passwordLogin, smsLogin, weixinMiniAppLogin, logout } from '@/api/auth' - -const AccessTokenKey = 'ACCESS_TOKEN' -const RefreshTokenKey = 'REFRESH_TOKEN' - -const user = { - state: { - accessToken: uni.getStorageSync(AccessTokenKey), // 访问令牌 - refreshToken: uni.getStorageSync(RefreshTokenKey), // 刷新令牌 - userInfo: {} - }, - mutations: { - // 更新 state 的通用方法 - SET_STATE_ATTR(state, param) { - if (param instanceof Array) { - for (let item of param) { - state[item.key] = item.val - } - } else { - state[param.key] = param.val - } - }, - // 更新令牌 - SET_TOKEN(state, data) { - // 设置令牌 - const { accessToken, refreshToken } = data - state.accessToken = accessToken - state.refreshToken = refreshToken - uni.setStorageSync(AccessTokenKey, accessToken) - uni.setStorageSync(RefreshTokenKey, refreshToken) - - // 加载用户信息 - this.dispatch('ObtainUserInfo') - }, - // 更新用户信息 - SET_USER_INFO(state, data) { - state.userInfo = data - }, - // 清空令牌 和 用户信息 - CLEAR_LOGIN_INFO(state) { - uni.removeStorageSync(AccessTokenKey) - uni.removeStorageSync(RefreshTokenKey) - state.accessToken = '' - state.refreshToken = '' - state.userInfo = {} - } - }, - actions: { - //账号登录 - Login({ state, commit }, { type, data }) { - if (type === 0) { - return passwordLogin(data) - .then(res => { - commit('SET_TOKEN', res.data) - return Promise.resolve(res) - }) - .catch(err => { - return Promise.reject(err) - }) - } else if (type === 1) { - return smsLogin(data) - .then(res => { - commit('SET_TOKEN', res.data) - return Promise.resolve(res) - }) - .catch(err => { - return Promise.reject(err) - }) - } else { - return weixinMiniAppLogin(data) - .then(res => { - commit('SET_TOKEN', res.data) - return Promise.resolve(res) - }) - .catch(err => { - return Promise.reject(err) - }) - } - }, - // 退出登录 - Logout({ state, commit }) { - return logout() - .then(res => { - return Promise.resolve(res) - }) - .catch(err => { - return Promise.reject(err) - }) - .finally(() => { - commit('CLEAR_LOGIN_INFO') - }) - }, - // 获得用户基本信息 - async ObtainUserInfo({ state, commit }) { - const res = await getUserInfo() - commit('SET_USER_INFO', res.data) - } - } -} -export default user diff --git a/yudao-ui-app/styles/base.scss b/yudao-ui-app/styles/base.scss deleted file mode 100644 index cadcbe311..000000000 --- a/yudao-ui-app/styles/base.scss +++ /dev/null @@ -1,5 +0,0 @@ -.row-between { - display: flex; - align-items: center; - justify-content: space-between; -} \ No newline at end of file diff --git a/yudao-ui-app/uni.scss b/yudao-ui-app/uni.scss deleted file mode 100644 index cc8852e5c..000000000 --- a/yudao-ui-app/uni.scss +++ /dev/null @@ -1,60 +0,0 @@ -/** - * 这里是uni-app内置的常用样式变量 - * - * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量 - * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App - * - */ - -/** - * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能 - * - * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件 - */ - -/* 引入uView主题样式 */ -@import '@/uni_modules/uview-ui/theme.scss'; - -/* 全局自定义scss变量 */ - -/* 页面背景颜色 */ -$custom-bg-color: #ffffff; - -/* 边框样式 */ -$custom-border-style: 1rpx solid #f3f3f3; - - -@mixin flex-left($direction: row) { - display: flex; - flex-direction: $direction; - align-items: center; - justify-content: flex-start; -} - -@mixin flex-right($direction: row) { - display: flex; - flex-direction: $direction; - align-items: center; - justify-content: flex-end; -} - -@mixin flex-center($direction: row) { - display: flex; - flex-direction: $direction; - align-items: center; - justify-content: center; -} - -@mixin flex-space-between($direction: row) { - display: flex; - flex-direction: $direction; - align-items: center; - justify-content: space-between; -} - -@mixin flex-space-around($direction: row) { - display: flex; - flex-direction: $direction; - align-items: center; - justify-content: space-around; -} diff --git a/yudao-ui-app/uni_modules/uview-ui/LICENSE b/yudao-ui-app/uni_modules/uview-ui/LICENSE deleted file mode 100644 index 8e39eada8..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 www.uviewui.com - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/yudao-ui-app/uni_modules/uview-ui/README.md b/yudao-ui-app/uni_modules/uview-ui/README.md deleted file mode 100644 index c78ff479e..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/README.md +++ /dev/null @@ -1,66 +0,0 @@ -

- logo -

-

uView 2.0

-

多平台快速开发的UI框架

- -[![stars](https://img.shields.io/github/stars/umicro/uView2.0?style=flat-square&logo=GitHub)](https://github.com/umicro/uView2.0) -[![forks](https://img.shields.io/github/forks/umicro/uView2.0?style=flat-square&logo=GitHub)](https://github.com/umicro/uView2.0) -[![issues](https://img.shields.io/github/issues/umicro/uView2.0?style=flat-square&logo=GitHub)](https://github.com/umicro/uView2.0/issues) -[![Website](https://img.shields.io/badge/uView-up-blue?style=flat-square)](https://uviewui.com) -[![release](https://img.shields.io/github/v/release/umicro/uView2.0?style=flat-square)](https://gitee.com/umicro/uView2.0/releases) -[![license](https://img.shields.io/github/license/umicro/uView2.0?style=flat-square)](https://en.wikipedia.org/wiki/MIT_License) - -## 说明 - -uView UI,是[uni-app](https://uniapp.dcloud.io/)全面兼容nvue的uni-app生态框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水 - -## [官方文档:https://uviewui.com](https://uviewui.com) - - -## 预览 - -您可以通过**微信**扫码,查看最佳的演示效果。 -
-
- - - -## 链接 - -- [官方文档](https://www.uviewui.com/) -- [更新日志](https://www.uviewui.com/components/changelog.html) -- [升级指南](https://www.uviewui.com/components/changeGuide.html) -- [关于我们](https://www.uviewui.com/cooperation/about.html) - -## 交流反馈 - -欢迎加入我们的QQ群交流反馈:[点此跳转](https://www.uviewui.com/components/addQQGroup.html) - -## 关于PR - -> 我们非常乐意接受各位的优质PR,但在此之前我希望您了解uView2.0是一个需要兼容多个平台的(小程序、h5、ios app、android app)包括nvue页面、vue页面。 -> 所以希望在您修复bug并提交之前尽可能的去这些平台测试一下兼容性。最好能携带测试截图以方便审核。非常感谢! - -## 安装 - -#### **uni-app插件市场链接** —— [https://ext.dcloud.net.cn/plugin?id=1593](https://ext.dcloud.net.cn/plugin?id=1593) - -请通过[官网安装文档](https://www.uviewui.com/components/install.html)了解更详细的内容 - -## 快速上手 - -请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容 - -## 使用方法 -配置easycom规则后,自动按需引入,无需`import`组件,直接引用即可。 - -```html - -``` - -## 版权信息 -uView遵循[MIT](https://en.wikipedia.org/wiki/MIT_License)开源协议,意味着您无需支付任何费用,也无需授权,即可将uView应用到您的产品中。 - diff --git a/yudao-ui-app/uni_modules/uview-ui/changelog.md b/yudao-ui-app/uni_modules/uview-ui/changelog.md deleted file mode 100644 index ca502516f..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/changelog.md +++ /dev/null @@ -1,357 +0,0 @@ -## 2.0.34(2022-09-25) -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. `u-input`、`u-textarea`增加`ignoreCompositionEvent`属性 -2. 修复`route`方法调用可能报错的问题 -3. 修复`u-no-network`组件`z-index`无效的问题 -4. 修复`textarea`组件在h5上confirmType=""报错的问题 -5. `u-rate`适配`nvue` -6. 优化验证手机号码的正则表达式(根据工信部发布的《电信网编号计划(2017年版)》进行修改。) -7. `form-item`添加`labelPosition`属性 -8. `u-calendar`修复`maxDate`设置为当前日期,并且当前时间大于08:00时无法显示日期列表的问题 (#724) -9. `u-radio`增加一个默认插槽用于自定义修改label内容 (#680) -10. 修复`timeFormat`函数在safari重的兼容性问题 (#664) -## 2.0.33(2022-06-17) -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. 修复`loadmore`组件`lineColor`类型错误问题 -2. 修复`u-parse`组件`imgtap`、`linktap`不生效问题 -## 2.0.32(2022-06-16) -# uView2.0重磅发布,利剑出鞘,一统江湖 -1. `u-loadmore`新增自定义颜色、虚/实线 -2. 修复`u-swiper-action`组件部分平台不能上下滑动的问题 -3. 修复`u-list`回弹问题 -4. 修复`notice-bar`组件动画在低端安卓机可能会抖动的问题 -5. `u-loading-page`添加控制图标大小的属性`iconSize` -6. 修复`u-tooltip`组件`color`参数不生效的问题 -7. 修复`u--input`组件使用`blur`事件输出为`undefined`的bug -8. `u-code-input`组件新增键盘弹起时,是否自动上推页面参数`adjustPosition` -9. 修复`image`组件`load`事件无回调对象问题 -10. 修复`button`组件`loadingSize`设置无效问题 -10. 其他修复 -## 2.0.31(2022-04-19) -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. 修复`upload`在`vue`页面上传成功后没有成功标志的问题 -2. 解决演示项目中微信小程序模拟上传图片一直出于上传中问题 -3. 修复`u-code-input`组件在`nvue`页面编译到`app`平台上光标异常问题(`app`去除此功能) -4. 修复`actionSheet`组件标题关闭按钮点击事件名称错误的问题 -5. 其他修复 -## 2.0.30(2022-04-04) -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. `u-rate`增加`readonly`属性 -2. `tabs`滑块支持设置背景图片 -3. 修复`u-subsection` `mode`为`subsection`时,滑块样式不正确的问题 -4. `u-code-input`添加光标效果动画 -5. 修复`popup`的`open`事件不触发 -6. 修复`u-flex-column`无效的问题 -7. 修复`u-datetime-picker`索引在特定场合异常问题 -8. 修复`u-datetime-picker`最小时间字符串模板错误问题 -9. `u-swiper`添加`m3u8`验证 -10. `u-swiper`修改判断image和video逻辑 -11. 修复`swiper`无法使用本地图片问题,增加`type`参数 -12. 修复`u-row-notice`格式错误问题 -13. 修复`u-switch`组件当`unit`为`rpx`时,`nodeStyle`消失的问题 -14. 修复`datetime-picker`组件`showToolbar`与`visibleItemCount`属性无效的问题 -15. 修复`upload`组件条件编译位置判断错误,导致`previewImage`属性设置为`false`时,整个组件都会被隐藏的问题 -16. 修复`u-checkbox-group`设置`shape`属性无效的问题 -17. 修复`u-upload`的`capture`传入字符串的时候不生效的问题 -18. 修复`u-action-sheet`组件,关闭事件逻辑错误的问题 -19. 修复`u-list`触顶事件的触发错误的问题 -20. 修复`u-text`只有手机号可拨打的问题 -21. 修复`u-textarea`不能换行的问题 -22. 其他修复 -## 2.0.29(2022-03-13) -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. 修复`u--text`组件设置`decoration`属性未生效的问题 -2. 修复`u-datetime-picker`使用`formatter`后返回值不正确 -3. 修复`u-datetime-picker` `intercept` 可能为undefined -4. 修复已设置单位 uni..config.unit = 'rpx'时,线型指示器 `transform` 的位置翻倍,导致指示器超出宽度 -5. 修复mixin中bem方法生成的类名在支付宝和字节小程序中失效 -6. 修复默认值传值为空的时候,打开`u-datetime-picker`报错,不能选中第一列时间的bug -7. 修复`u-datetime-picker`使用`formatter`后返回值不正确 -8. 修复`u-image`组件`loading`无效果的问题 -9. 修复`config.unit`属性设为`rpx`时,导航栏占用高度不足导致塌陷的问题 -10. 修复`u-datetime-picker`组件`itemHeight`无效问题 -11. 其他修复 -## 2.0.28(2022-02-22) -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. search组件新增searchIconSize属性 -2. 兼容Safari/Webkit中传入时间格式如2022-02-17 12:00:56 -3. 修复text value.js 判断日期出format错误问题 -4. priceFormat格式化金额出现精度错误 -5. priceFormat在部分情况下出现精度损失问题 -6. 优化表单rules提示 -7. 修复avatar组件src为空时,展示状态不对 -8. 其他修复 -## 2.0.27(2022-01-28) -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1.样式修复 -## 2.0.26(2022-01-28) -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1.样式修复 -## 2.0.25(2022-01-27) -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. 修复text组件mode=price时,可能会导致精度错误的问题 -2. 添加$u.setConfig()方法,可设置uView内置的config, props, zIndex, color属性,详见:[修改uView内置配置方案](https://uviewui.com/components/setting.html#%E9%BB%98%E8%AE%A4%E5%8D%95%E4%BD%8D%E9%85%8D%E7%BD%AE) -3. 优化form组件在errorType=toast时,如果输入错误页面会有抖动的问题 -4. 修复$u.addUnit()对配置默认单位可能无效的问题 -## 2.0.24(2022-01-25) -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. 修复swiper在current指定非0时缩放有误 -2. 修复u-icon添加stop属性的时候报错 -3. 优化遗留的通过正则判断rpx单位的问题 -4. 优化Layout布局 vue使用gutter时,会超出固定区域 -5. 优化search组件高度单位问题(rpx -> px) -6. 修复u-image slot 加载和错误的图片失去了高度 -7. 修复u-index-list中footer插槽与header插槽存在性判断错误 -8. 修复部分机型下u-popup关闭时会闪烁 -9. 修复u-image在nvue-app下失去宽高 -10. 修复u-popup运行报错 -11. 修复u-tooltip报错 -12. 修复box-sizing在app下的警告 -13. 修复u-navbar在小程序中报运行时错误 -14. 其他修复 -## 2.0.23(2022-01-24) -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. 修复image组件在hx3.3.9的nvue下可能会显示异常的问题 -2. 修复col组件gutter参数带rpx单位处理不正确的问题 -3. 修复text组件单行时无法显示省略号的问题 -4. navbar添加titleStyle参数 -5. 升级到hx3.3.9可消除nvue下控制台样式警告的问题 -## 2.0.22(2022-01-19) -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. $u.page()方法优化,避免在特殊场景可能报错的问题 -2. picker组件添加immediateChange参数 -3. 新增$u.pages()方法 -## 2.0.21(2022-01-19) -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. 优化:form组件在用户设置rules的时候提示用户model必传 -2. 优化遗留的通过正则判断rpx单位的问题 -3. 修复微信小程序环境中tabbar组件开启safeAreaInsetBottom属性后,placeholder高度填充不正确 -4. 修复swiper在current指定非0时缩放有误 -5. 修复u-icon添加stop属性的时候报错 -6. 修复upload组件在accept=all的时候没有作用 -7. 修复在text组件mode为phone时call属性无效的问题 -8. 处理u-form clearValidate方法 -9. 其他修复 -## 2.0.20(2022-01-14) -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. 修复calendar默认会选择一个日期,如果直接点确定的话,无法取到值的问题 -2. 修复Slider缺少disabled props 还有注释 -3. 修复u-notice-bar点击事件无法拿到index索引值的问题 -4. 修复u-collapse-item在vue文件下,app端自定义插槽不生效的问题 -5. 优化头像为空时显示默认头像 -6. 修复图片地址赋值后判断加载状态为完成问题 -7. 修复日历滚动到默认日期月份区域 -8. search组件暴露点击左边icon事件 -9. 修复u-form clearValidate方法不生效 -10. upload h5端增加返回文件参数(文件的name参数) -11. 处理upload选择文件后url为blob类型无法预览的问题 -12. u-code-input 修复输入框没有往左移出一半屏幕 -13. 修复Upload上传 disabled为true时,控制台报hoverClass类型错误 -14. 临时处理ios app下grid点击坍塌问题 -15. 其他修复 -## 2.0.19(2021-12-29) -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. 优化微信小程序包体积可在微信中预览,请升级HbuilderX3.3.4,同时在“运行->运行到小程序模拟器”中勾选“运行时是否压缩代码” -2. 优化微信小程序setData性能,处理某些方法如$u.route()无法在模板中使用的问题 -3. navbar添加autoBack参数 -4. 允许avatar组件的事件冒泡 -5. 修复cell组件报错问题 -6. 其他修复 -## 2.0.18(2021-12-28) -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. 修复app端编译报错问题 -2. 重新处理微信小程序端setData过大的性能问题 -3. 修复边框问题 -4. 修复最大最小月份不大于0则没有数据出现的问题 -5. 修复SwipeAction微信小程序端无法上下滑动问题 -6. 修复input的placeholder在小程序端默认显示为true问题 -7. 修复divider组件click事件无效问题 -8. 修复u-code-input maxlength 属性值为 String 类型时显示异常 -9. 修复当 grid只有 1到2时 在小程序端algin设置无效的问题 -10. 处理form-item的label为top时,取消错误提示的左边距 -11. 其他修复 -## 2.0.17(2021-12-26) -## uView正在参与开源中国的“年度最佳项目”评选,之前投过票的现在也可以投票,恳请同学们投一票,[点此帮助uView](https://www.oschina.net/project/top_cn_2021/?id=583) - -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. 解决HBuilderX3.3.3.20211225版本导致的样式问题 -2. calendar日历添加monthNum参数 -3. navbar添加center slot -## 2.0.16(2021-12-25) -## uView正在参与开源中国的“年度最佳项目”评选,之前投过票的现在也可以投票,恳请同学们投一票,[点此帮助uView](https://www.oschina.net/project/top_cn_2021/?id=583) - -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. 解决微信小程序setData性能问题 -2. 修复count-down组件change事件不触发问题 -## 2.0.15(2021-12-21) -## uView正在参与开源中国的“年度最佳项目”评选,之前投过票的现在也可以投票,恳请同学们投一票,[点此帮助uView](https://www.oschina.net/project/top_cn_2021/?id=583) - -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. 修复Cell单元格titleWidth无效 -2. 修复cheakbox组件ischecked不更新 -3. 修复keyboard是否显示"."按键默认值问题 -4. 修复number-keyboard是否显示键盘的"."符号问题 -5. 修复Input输入框 readonly无效 -6. 修复u-avatar 导致打包app、H5时候报错问题 -7. 修复Upload上传deletable无效 -8. 修复upload当设置maxSize时无效的问题 -9. 修复tabs lineWidth传入带单位的字符串的时候偏移量计算错误问题 -10. 修复rate组件在有padding的view内,显示的星星位置和可触摸区域不匹配,无法正常选中星星 -## 2.0.13(2021-12-14) -## [点击加群交流反馈:364463526](https://jq.qq.com/?_chanwv=1027&k=mCxS3TGY) - -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. 修复配置默认单位为rpx可能会导致自定义导航栏高度异常的问题 -## 2.0.12(2021-12-14) -## [点击加群交流反馈:364463526](https://jq.qq.com/?_chanwv=1027&k=mCxS3TGY) - -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. 修复tabs组件在vue环境下划线消失的问题 -2. 修复upload组件在安卓小程序无法选择视频的问题 -3. 添加uni.$u.config.unit配置,用于配置参数默认单位,详见:[默认单位配置](https://www.uviewui.com/components/setting.html#%E9%BB%98%E8%AE%A4%E5%8D%95%E4%BD%8D%E9%85%8D%E7%BD%AE) -4. 修复textarea组件在没绑定v-model时,字符统计不生效问题 -5. 修复nvue下控制是否出现滚动条失效问题 -## 2.0.11(2021-12-13) -## [点击加群交流反馈:364463526](https://jq.qq.com/?_chanwv=1027&k=mCxS3TGY) - -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. text组件align参数无效的问题 -2. subsection组件添加keyName参数 -3. upload组件无法判断[Object file]类型的问题 -4. 处理notify层级过低问题 -5. codeInput组件添加disabledDot参数 -6. 处理actionSheet组件round参数无效的问题 -7. calendar组件添加round参数用于控制圆角值 -8. 处理swipeAction组件在vue环境下默认被打开的问题 -9. button组件的throttleTime节流参数无效的问题 -10. 解决u-notify手动关闭方法close()无效的问题 -11. input组件readonly不生效问题 -12. tag组件type参数为info不生效问题 -## 2.0.10(2021-12-08) -## [点击加群交流反馈:364463526](https://jq.qq.com/?_chanwv=1027&k=mCxS3TGY) - -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. 修复button sendMessagePath属性不生效 -2. 修复DatetimePicker选择器title无效 -3. 修复u-toast设置loading=true不生效 -4. 修复u-text金额模式传0报错 -5. 修复u-toast组件的icon属性配置不生效 -6. button的icon在特殊场景下的颜色优化 -7. IndexList优化,增加# -## 2.0.9(2021-12-01) -## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU) - -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. 优化swiper的height支持100%值(仅vue有效),修复嵌入视频时click事件无法触发的问题 -2. 优化tabs组件对list值为空的判断,或者动态变化list时重新计算相关尺寸的问题 -3. 优化datetime-picker组件逻辑,让其后续打开的默认值为上一次的选中值,需要通过v-model绑定值才有效 -4. 修复upload内嵌在其他组件中,选择图片可能不会换行的问题 -## 2.0.8(2021-12-01) -## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU) - -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. 修复toast的position参数无效问题 -2. 处理input在ios nvue上无法获得焦点的问题 -3. avatar-group组件添加extraValue参数,让剩余展示数量可手动控制 -4. tabs组件添加keyName参数用于配置从对象中读取的键名 -5. 处理text组件名字脱敏默认配置无效的问题 -6. 处理picker组件item文本太长换行问题 -## 2.0.7(2021-11-30) -## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU) - -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. 修复radio和checkbox动态改变v-model无效的问题。 -2. 优化form规则validator在微信小程序用法 -3. 修复backtop组件mode参数在微信小程序无效的问题 -4. 处理Album的previewFullImage属性无效的问题 -5. 处理u-datetime-picker组件mode='time'在选择改变时间时,控制台报错的问题 -## 2.0.6(2021-11-27) -## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU) - -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. 处理tag组件在vue下边框无效的问题。 -2. 处理popup组件圆角参数可能无效的问题。 -3. 处理tabs组件lineColor参数可能无效的问题。 -4. propgress组件在值很小时,显示异常的问题。 -## 2.0.5(2021-11-25) -## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU) - -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. calendar在vue下显示异常问题。 -2. form组件labelPosition和errorType参数无效的问题 -3. input组件inputAlign无效的问题 -4. 其他一些修复 -## 2.0.4(2021-11-23) -## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU) - -# uView2.0重磅发布,利剑出鞘,一统江湖 - -0. input组件缺失@confirm事件,以及subfix和prefix无效问题 -1. component.scss文件样式在vue下干扰全局布局问题 -2. 修复subsection在vue环境下表现异常的问题 -3. tag组件的bgColor等参数无效的问题 -4. upload组件不换行的问题 -5. 其他的一些修复处理 -## 2.0.3(2021-11-16) -## [点击加群交流反馈:1129077272](https://jq.qq.com/?_wv=1027&k=KnbeceDU) - -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. uView2.0已实现全面兼容nvue -2. uView2.0对1.x进行了架构重构,细节和性能都有极大提升 -3. 目前uView2.0为公测阶段,相关细节可能会有变动 -4. 我们写了一份与1.x的对比指南,详见[对比1.x](https://www.uviewui.com/components/diff1.x.html) -5. 处理modal的confirm回调事件拼写错误问题 -6. 处理input组件@input事件参数错误问题 -7. 其他一些修复 -## 2.0.2(2021-11-16) -## [点击加群交流反馈:1129077272](https://jq.qq.com/?_wv=1027&k=KnbeceDU) - -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. uView2.0已实现全面兼容nvue -2. uView2.0对1.x进行了架构重构,细节和性能都有极大提升 -3. 目前uView2.0为公测阶段,相关细节可能会有变动 -4. 我们写了一份与1.x的对比指南,详见[对比1.x](https://www.uviewui.com/components/diff1.x.html) -5. 修复input组件formatter参数缺失问题 -6. 优化loading-icon组件的scss写法问题,防止不兼容新版本scss -## 2.0.0(2020-11-15) -## [点击加群交流反馈:1129077272](https://jq.qq.com/?_wv=1027&k=KnbeceDU) - -# uView2.0重磅发布,利剑出鞘,一统江湖 - -1. uView2.0已实现全面兼容nvue -2. uView2.0对1.x进行了架构重构,细节和性能都有极大提升 -3. 目前uView2.0为公测阶段,相关细节可能会有变动 -4. 我们写了一份与1.x的对比指南,详见[对比1.x](https://www.uviewui.com/components/diff1.x.html) -5. 修复input组件formatter参数缺失问题 - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u--form/u--form.vue b/yudao-ui-app/uni_modules/uview-ui/components/u--form/u--form.vue deleted file mode 100644 index fdfc212ae..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u--form/u--form.vue +++ /dev/null @@ -1,78 +0,0 @@ - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u--image/u--image.vue b/yudao-ui-app/uni_modules/uview-ui/components/u--image/u--image.vue deleted file mode 100644 index 21b7ab196..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u--image/u--image.vue +++ /dev/null @@ -1,47 +0,0 @@ - - - \ No newline at end of file diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u--input/u--input.vue b/yudao-ui-app/uni_modules/uview-ui/components/u--input/u--input.vue deleted file mode 100644 index 1e58b0107..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u--input/u--input.vue +++ /dev/null @@ -1,73 +0,0 @@ - - - \ No newline at end of file diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u--text/u--text.vue b/yudao-ui-app/uni_modules/uview-ui/components/u--text/u--text.vue deleted file mode 100644 index 44ee52a37..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u--text/u--text.vue +++ /dev/null @@ -1,44 +0,0 @@ - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u--textarea/u--textarea.vue b/yudao-ui-app/uni_modules/uview-ui/components/u--textarea/u--textarea.vue deleted file mode 100644 index f4df0b9a4..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u--textarea/u--textarea.vue +++ /dev/null @@ -1,48 +0,0 @@ - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-action-sheet/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-action-sheet/props.js deleted file mode 100644 index e96e04fd4..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-action-sheet/props.js +++ /dev/null @@ -1,54 +0,0 @@ -export default { - props: { - // 操作菜单是否展示 (默认false) - show: { - type: Boolean, - default: uni.$u.props.actionSheet.show - }, - // 标题 - title: { - type: String, - default: uni.$u.props.actionSheet.title - }, - // 选项上方的描述信息 - description: { - type: String, - default: uni.$u.props.actionSheet.description - }, - // 数据 - actions: { - type: Array, - default: uni.$u.props.actionSheet.actions - }, - // 取消按钮的文字,不为空时显示按钮 - cancelText: { - type: String, - default: uni.$u.props.actionSheet.cancelText - }, - // 点击某个菜单项时是否关闭弹窗 - closeOnClickAction: { - type: Boolean, - default: uni.$u.props.actionSheet.closeOnClickAction - }, - // 处理底部安全区(默认true) - safeAreaInsetBottom: { - type: Boolean, - default: uni.$u.props.actionSheet.safeAreaInsetBottom - }, - // 小程序的打开方式 - openType: { - type: String, - default: uni.$u.props.actionSheet.openType - }, - // 点击遮罩是否允许关闭 (默认true) - closeOnClickOverlay: { - type: Boolean, - default: uni.$u.props.actionSheet.closeOnClickOverlay - }, - // 圆角值 - round: { - type: [Boolean, String, Number], - default: uni.$u.props.actionSheet.round - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-action-sheet/u-action-sheet.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-action-sheet/u-action-sheet.vue deleted file mode 100644 index 26d5d8d9f..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-action-sheet/u-action-sheet.vue +++ /dev/null @@ -1,278 +0,0 @@ - - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-album/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-album/props.js deleted file mode 100644 index 75cdb37d5..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-album/props.js +++ /dev/null @@ -1,59 +0,0 @@ -export default { - props: { - // 图片地址,Array|Array形式 - urls: { - type: Array, - default: uni.$u.props.album.urls - }, - // 指定从数组的对象元素中读取哪个属性作为图片地址 - keyName: { - type: String, - default: uni.$u.props.album.keyName - }, - // 单图时,图片长边的长度 - singleSize: { - type: [String, Number], - default: uni.$u.props.album.singleSize - }, - // 多图时,图片边长 - multipleSize: { - type: [String, Number], - default: uni.$u.props.album.multipleSize - }, - // 多图时,图片水平和垂直之间的间隔 - space: { - type: [String, Number], - default: uni.$u.props.album.space - }, - // 单图时,图片缩放裁剪的模式 - singleMode: { - type: String, - default: uni.$u.props.album.singleMode - }, - // 多图时,图片缩放裁剪的模式 - multipleMode: { - type: String, - default: uni.$u.props.album.multipleMode - }, - // 最多展示的图片数量,超出时最后一个位置将会显示剩余图片数量 - maxCount: { - type: [String, Number], - default: uni.$u.props.album.maxCount - }, - // 是否可以预览图片 - previewFullImage: { - type: Boolean, - default: uni.$u.props.album.previewFullImage - }, - // 每行展示图片数量,如设置,singleSize和multipleSize将会无效 - rowCount: { - type: [String, Number], - default: uni.$u.props.album.rowCount - }, - // 超出maxCount时是否显示查看更多的提示 - showMore: { - type: Boolean, - default: uni.$u.props.album.showMore - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-album/u-album.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-album/u-album.vue deleted file mode 100644 index 687e2d52c..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-album/u-album.vue +++ /dev/null @@ -1,259 +0,0 @@ - - - - - \ No newline at end of file diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-alert/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-alert/props.js deleted file mode 100644 index 4297e2c3d..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-alert/props.js +++ /dev/null @@ -1,44 +0,0 @@ -export default { - props: { - // 显示文字 - title: { - type: String, - default: uni.$u.props.alert.title - }, - // 主题,success/warning/info/error - type: { - type: String, - default: uni.$u.props.alert.type - }, - // 辅助性文字 - description: { - type: String, - default: uni.$u.props.alert.description - }, - // 是否可关闭 - closable: { - type: Boolean, - default: uni.$u.props.alert.closable - }, - // 是否显示图标 - showIcon: { - type: Boolean, - default: uni.$u.props.alert.showIcon - }, - // 浅或深色调,light-浅色,dark-深色 - effect: { - type: String, - default: uni.$u.props.alert.effect - }, - // 文字是否居中 - center: { - type: Boolean, - default: uni.$u.props.alert.center - }, - // 字体大小 - fontSize: { - type: [String, Number], - default: uni.$u.props.alert.fontSize - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-alert/u-alert.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-alert/u-alert.vue deleted file mode 100644 index 81f7d43e1..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-alert/u-alert.vue +++ /dev/null @@ -1,243 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-avatar-group/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-avatar-group/props.js deleted file mode 100644 index 58b42ac95..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-avatar-group/props.js +++ /dev/null @@ -1,52 +0,0 @@ -export default { - props: { - // 头像图片组 - urls: { - type: Array, - default: uni.$u.props.avatarGroup.urls - }, - // 最多展示的头像数量 - maxCount: { - type: [String, Number], - default: uni.$u.props.avatarGroup.maxCount - }, - // 头像形状 - shape: { - type: String, - default: uni.$u.props.avatarGroup.shape - }, - // 图片裁剪模式 - mode: { - type: String, - default: uni.$u.props.avatarGroup.mode - }, - // 超出maxCount时是否显示查看更多的提示 - showMore: { - type: Boolean, - default: uni.$u.props.avatarGroup.showMore - }, - // 头像大小 - size: { - type: [String, Number], - default: uni.$u.props.avatarGroup.size - }, - // 指定从数组的对象元素中读取哪个属性作为图片地址 - keyName: { - type: String, - default: uni.$u.props.avatarGroup.keyName - }, - // 头像之间的遮挡比例 - gap: { - type: [String, Number], - validator(value) { - return value >= 0 && value <= 1 - }, - default: uni.$u.props.avatarGroup.gap - }, - // 需额外显示的值 - extraValue: { - type: [Number, String], - default: uni.$u.props.avatarGroup.extraValue - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-avatar-group/u-avatar-group.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-avatar-group/u-avatar-group.vue deleted file mode 100644 index 7e996d770..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-avatar-group/u-avatar-group.vue +++ /dev/null @@ -1,103 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-avatar/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-avatar/props.js deleted file mode 100644 index 34ca0f282..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-avatar/props.js +++ /dev/null @@ -1,78 +0,0 @@ -export default { - props: { - // 头像图片路径(不能为相对路径) - src: { - type: String, - default: uni.$u.props.avatar.src - }, - // 头像形状,circle-圆形,square-方形 - shape: { - type: String, - default: uni.$u.props.avatar.shape - }, - // 头像尺寸 - size: { - type: [String, Number], - default: uni.$u.props.avatar.size - }, - // 裁剪模式 - mode: { - type: String, - default: uni.$u.props.avatar.mode - }, - // 显示的文字 - text: { - type: String, - default: uni.$u.props.avatar.text - }, - // 背景色 - bgColor: { - type: String, - default: uni.$u.props.avatar.bgColor - }, - // 文字颜色 - color: { - type: String, - default: uni.$u.props.avatar.color - }, - // 文字大小 - fontSize: { - type: [String, Number], - default: uni.$u.props.avatar.fontSize - }, - // 显示的图标 - icon: { - type: String, - default: uni.$u.props.avatar.icon - }, - // 显示小程序头像,只对百度,微信,QQ小程序有效 - mpAvatar: { - type: Boolean, - default: uni.$u.props.avatar.mpAvatar - }, - // 是否使用随机背景色 - randomBgColor: { - type: Boolean, - default: uni.$u.props.avatar.randomBgColor - }, - // 加载失败的默认头像(组件有内置默认图片) - defaultUrl: { - type: String, - default: uni.$u.props.avatar.defaultUrl - }, - // 如果配置了randomBgColor为true,且配置了此值,则从默认的背景色数组中取出对应索引的颜色值,取值0-19之间 - colorIndex: { - type: [String, Number], - // 校验参数规则,索引在0-19之间 - validator(n) { - return uni.$u.test.range(n, [0, 19]) || n === '' - }, - default: uni.$u.props.avatar.colorIndex - }, - // 组件标识符 - name: { - type: String, - default: uni.$u.props.avatar.name - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-avatar/u-avatar.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-avatar/u-avatar.vue deleted file mode 100644 index 3319be581..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-avatar/u-avatar.vue +++ /dev/null @@ -1,172 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-back-top/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-back-top/props.js deleted file mode 100644 index 6c702c286..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-back-top/props.js +++ /dev/null @@ -1,54 +0,0 @@ -export default { - props: { - // 返回顶部的形状,circle-圆形,square-方形 - mode: { - type: String, - default: uni.$u.props.backtop.mode - }, - // 自定义图标 - icon: { - type: String, - default: uni.$u.props.backtop.icon - }, - // 提示文字 - text: { - type: String, - default: uni.$u.props.backtop.text - }, - // 返回顶部滚动时间 - duration: { - type: [String, Number], - default: uni.$u.props.backtop.duration - }, - // 滚动距离 - scrollTop: { - type: [String, Number], - default: uni.$u.props.backtop.scrollTop - }, - // 距离顶部多少距离显示,单位px - top: { - type: [String, Number], - default: uni.$u.props.backtop.top - }, - // 返回顶部按钮到底部的距离,单位px - bottom: { - type: [String, Number], - default: uni.$u.props.backtop.bottom - }, - // 返回顶部按钮到右边的距离,单位px - right: { - type: [String, Number], - default: uni.$u.props.backtop.right - }, - // 层级 - zIndex: { - type: [String, Number], - default: uni.$u.props.backtop.zIndex - }, - // 图标的样式,对象形式 - iconStyle: { - type: Object, - default: uni.$u.props.backtop.iconStyle - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-back-top/u-back-top.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-back-top/u-back-top.vue deleted file mode 100644 index 2d075667f..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-back-top/u-back-top.vue +++ /dev/null @@ -1,129 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-badge/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-badge/props.js deleted file mode 100644 index 74c032c39..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-badge/props.js +++ /dev/null @@ -1,72 +0,0 @@ -export default { - props: { - // 是否显示圆点 - isDot: { - type: Boolean, - default: uni.$u.props.badge.isDot - }, - // 显示的内容 - value: { - type: [Number, String], - default: uni.$u.props.badge.value - }, - // 是否显示 - show: { - type: Boolean, - default: uni.$u.props.badge.show - }, - // 最大值,超过最大值会显示 '{max}+' - max: { - type: [Number, String], - default: uni.$u.props.badge.max - }, - // 主题类型,error|warning|success|primary - type: { - type: String, - default: uni.$u.props.badge.type - }, - // 当数值为 0 时,是否展示 Badge - showZero: { - type: Boolean, - default: uni.$u.props.badge.showZero - }, - // 背景颜色,优先级比type高,如设置,type参数会失效 - bgColor: { - type: [String, null], - default: uni.$u.props.badge.bgColor - }, - // 字体颜色 - color: { - type: [String, null], - default: uni.$u.props.badge.color - }, - // 徽标形状,circle-四角均为圆角,horn-左下角为直角 - shape: { - type: String, - default: uni.$u.props.badge.shape - }, - // 设置数字的显示方式,overflow|ellipsis|limit - // overflow会根据max字段判断,超出显示`${max}+` - // ellipsis会根据max判断,超出显示`${max}...` - // limit会依据1000作为判断条件,超出1000,显示`${value/1000}K`,比如2.2k、3.34w,最多保留2位小数 - numberType: { - type: String, - default: uni.$u.props.badge.numberType - }, - // 设置badge的位置偏移,格式为 [x, y],也即设置的为top和right的值,absolute为true时有效 - offset: { - type: Array, - default: uni.$u.props.badge.offset - }, - // 是否反转背景和字体颜色 - inverted: { - type: Boolean, - default: uni.$u.props.badge.inverted - }, - // 是否绝对定位 - absolute: { - type: Boolean, - default: uni.$u.props.badge.absolute - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-badge/u-badge.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-badge/u-badge.vue deleted file mode 100644 index 53cfc8115..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-badge/u-badge.vue +++ /dev/null @@ -1,171 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-button/nvue.scss b/yudao-ui-app/uni_modules/uview-ui/components/u-button/nvue.scss deleted file mode 100644 index 490db7d99..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-button/nvue.scss +++ /dev/null @@ -1,46 +0,0 @@ -$u-button-active-opacity:0.75 !default; -$u-button-loading-text-margin-left:4px !default; -$u-button-text-color: #FFFFFF !default; -$u-button-text-plain-error-color:$u-error !default; -$u-button-text-plain-warning-color:$u-warning !default; -$u-button-text-plain-success-color:$u-success !default; -$u-button-text-plain-info-color:$u-info !default; -$u-button-text-plain-primary-color:$u-primary !default; -.u-button { - &--active { - opacity: $u-button-active-opacity; - } - - &--active--plain { - background-color: rgb(217, 217, 217); - } - - &__loading-text { - margin-left:$u-button-loading-text-margin-left; - } - - &__text, - &__loading-text { - color:$u-button-text-color; - } - - &__text--plain--error { - color:$u-button-text-plain-error-color; - } - - &__text--plain--warning { - color:$u-button-text-plain-warning-color; - } - - &__text--plain--success{ - color:$u-button-text-plain-success-color; - } - - &__text--plain--info { - color:$u-button-text-plain-info-color; - } - - &__text--plain--primary { - color:$u-button-text-plain-primary-color; - } -} \ No newline at end of file diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-button/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-button/props.js deleted file mode 100644 index 07fd84467..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-button/props.js +++ /dev/null @@ -1,161 +0,0 @@ -/* - * @Author : LQ - * @Description : - * @version : 1.0 - * @Date : 2021-08-16 10:04:04 - * @LastAuthor : LQ - * @lastTime : 2021-08-16 10:04:24 - * @FilePath : /u-view2.0/uview-ui/components/u-button/props.js - */ -export default { - props: { - // 是否细边框 - hairline: { - type: Boolean, - default: uni.$u.props.button.hairline - }, - // 按钮的预置样式,info,primary,error,warning,success - type: { - type: String, - default: uni.$u.props.button.type - }, - // 按钮尺寸,large,normal,small,mini - size: { - type: String, - default: uni.$u.props.button.size - }, - // 按钮形状,circle(两边为半圆),square(带圆角) - shape: { - type: String, - default: uni.$u.props.button.shape - }, - // 按钮是否镂空 - plain: { - type: Boolean, - default: uni.$u.props.button.plain - }, - // 是否禁止状态 - disabled: { - type: Boolean, - default: uni.$u.props.button.disabled - }, - // 是否加载中 - loading: { - type: Boolean, - default: uni.$u.props.button.loading - }, - // 加载中提示文字 - loadingText: { - type: [String, Number], - default: uni.$u.props.button.loadingText - }, - // 加载状态图标类型 - loadingMode: { - type: String, - default: uni.$u.props.button.loadingMode - }, - // 加载图标大小 - loadingSize: { - type: [String, Number], - default: uni.$u.props.button.loadingSize - }, - // 开放能力,具体请看uniapp稳定关于button组件部分说明 - // https://uniapp.dcloud.io/component/button - openType: { - type: String, - default: uni.$u.props.button.openType - }, - // 用于
组件,点击分别会触发 组件的 submit/reset 事件 - // 取值为submit(提交表单),reset(重置表单) - formType: { - type: String, - default: uni.$u.props.button.formType - }, - // 打开 APP 时,向 APP 传递的参数,open-type=launchApp时有效 - // 只微信小程序、QQ小程序有效 - appParameter: { - type: String, - default: uni.$u.props.button.appParameter - }, - // 指定是否阻止本节点的祖先节点出现点击态,微信小程序有效 - hoverStopPropagation: { - type: Boolean, - default: uni.$u.props.button.hoverStopPropagation - }, - // 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文。只微信小程序有效 - lang: { - type: String, - default: uni.$u.props.button.lang - }, - // 会话来源,open-type="contact"时有效。只微信小程序有效 - sessionFrom: { - type: String, - default: uni.$u.props.button.sessionFrom - }, - // 会话内消息卡片标题,open-type="contact"时有效 - // 默认当前标题,只微信小程序有效 - sendMessageTitle: { - type: String, - default: uni.$u.props.button.sendMessageTitle - }, - // 会话内消息卡片点击跳转小程序路径,open-type="contact"时有效 - // 默认当前分享路径,只微信小程序有效 - sendMessagePath: { - type: String, - default: uni.$u.props.button.sendMessagePath - }, - // 会话内消息卡片图片,open-type="contact"时有效 - // 默认当前页面截图,只微信小程序有效 - sendMessageImg: { - type: String, - default: uni.$u.props.button.sendMessageImg - }, - // 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示, - // 用户点击后可以快速发送小程序消息,open-type="contact"时有效 - showMessageCard: { - type: Boolean, - default: uni.$u.props.button.showMessageCard - }, - // 额外传参参数,用于小程序的data-xxx属性,通过target.dataset.name获取 - dataName: { - type: String, - default: uni.$u.props.button.dataName - }, - // 节流,一定时间内只能触发一次 - throttleTime: { - type: [String, Number], - default: uni.$u.props.button.throttleTime - }, - // 按住后多久出现点击态,单位毫秒 - hoverStartTime: { - type: [String, Number], - default: uni.$u.props.button.hoverStartTime - }, - // 手指松开后点击态保留时间,单位毫秒 - hoverStayTime: { - type: [String, Number], - default: uni.$u.props.button.hoverStayTime - }, - // 按钮文字,之所以通过props传入,是因为slot传入的话 - // nvue中无法控制文字的样式 - text: { - type: [String, Number], - default: uni.$u.props.button.text - }, - // 按钮图标 - icon: { - type: String, - default: uni.$u.props.button.icon - }, - // 按钮图标 - iconColor: { - type: String, - default: uni.$u.props.button.icon - }, - // 按钮颜色,支持传入linear-gradient渐变色 - color: { - type: String, - default: uni.$u.props.button.color - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-button/u-button.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-button/u-button.vue deleted file mode 100644 index 5494351ea..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-button/u-button.vue +++ /dev/null @@ -1,490 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-button/vue.scss b/yudao-ui-app/uni_modules/uview-ui/components/u-button/vue.scss deleted file mode 100644 index 32019b278..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-button/vue.scss +++ /dev/null @@ -1,80 +0,0 @@ -// nvue下hover-class无效 -$u-button-before-top:50% !default; -$u-button-before-left:50% !default; -$u-button-before-width:100% !default; -$u-button-before-height:100% !default; -$u-button-before-transform:translate(-50%, -50%) !default; -$u-button-before-opacity:0 !default; -$u-button-before-background-color:#000 !default; -$u-button-before-border-color:#000 !default; -$u-button-active-before-opacity:.15 !default; -$u-button-icon-margin-left:4px !default; -$u-button-plain-u-button-info-color:$u-info; -$u-button-plain-u-button-success-color:$u-success; -$u-button-plain-u-button-error-color:$u-error; -$u-button-plain-u-button-warning-color:$u-error; - -.u-button { - width: 100%; - - &__text { - white-space: nowrap; - line-height: 1; - } - - &:before { - position: absolute; - top:$u-button-before-top; - left:$u-button-before-left; - width:$u-button-before-width; - height:$u-button-before-height; - border: inherit; - border-radius: inherit; - transform:$u-button-before-transform; - opacity:$u-button-before-opacity; - content: " "; - background-color:$u-button-before-background-color; - border-color:$u-button-before-border-color; - } - - &--active { - &:before { - opacity: .15 - } - } - - &__icon+&__text:not(:empty), - &__loading-text { - margin-left:$u-button-icon-margin-left; - } - - &--plain { - &.u-button--primary { - color: $u-primary; - } - } - - &--plain { - &.u-button--info { - color:$u-button-plain-u-button-info-color; - } - } - - &--plain { - &.u-button--success { - color:$u-button-plain-u-button-success-color; - } - } - - &--plain { - &.u-button--error { - color:$u-button-plain-u-button-error-color; - } - } - - &--plain { - &.u-button--warning { - color:$u-button-plain-u-button-warning-color; - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-calendar/header.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-calendar/header.vue deleted file mode 100644 index dc4f7d054..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-calendar/header.vue +++ /dev/null @@ -1,99 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-calendar/month.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-calendar/month.vue deleted file mode 100644 index c20937fee..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-calendar/month.vue +++ /dev/null @@ -1,579 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-calendar/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-calendar/props.js deleted file mode 100644 index 2ad7bc769..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-calendar/props.js +++ /dev/null @@ -1,144 +0,0 @@ -export default { - props: { - // 日历顶部标题 - title: { - type: String, - default: uni.$u.props.calendar.title - }, - // 是否显示标题 - showTitle: { - type: Boolean, - default: uni.$u.props.calendar.showTitle - }, - // 是否显示副标题 - showSubtitle: { - type: Boolean, - default: uni.$u.props.calendar.showSubtitle - }, - // 日期类型选择,single-选择单个日期,multiple-可以选择多个日期,range-选择日期范围 - mode: { - type: String, - default: uni.$u.props.calendar.mode - }, - // mode=range时,第一个日期底部的提示文字 - startText: { - type: String, - default: uni.$u.props.calendar.startText - }, - // mode=range时,最后一个日期底部的提示文字 - endText: { - type: String, - default: uni.$u.props.calendar.endText - }, - // 自定义列表 - customList: { - type: Array, - default: uni.$u.props.calendar.customList - }, - // 主题色,对底部按钮和选中日期有效 - color: { - type: String, - default: uni.$u.props.calendar.color - }, - // 最小的可选日期 - minDate: { - type: [String, Number], - default: uni.$u.props.calendar.minDate - }, - // 最大可选日期 - maxDate: { - type: [String, Number], - default: uni.$u.props.calendar.maxDate - }, - // 默认选中的日期,mode为multiple或range是必须为数组格式 - defaultDate: { - type: [Array, String, Date, null], - default: uni.$u.props.calendar.defaultDate - }, - // mode=multiple时,最多可选多少个日期 - maxCount: { - type: [String, Number], - default: uni.$u.props.calendar.maxCount - }, - // 日期行高 - rowHeight: { - type: [String, Number], - default: uni.$u.props.calendar.rowHeight - }, - // 日期格式化函数 - formatter: { - type: [Function, null], - default: uni.$u.props.calendar.formatter - }, - // 是否显示农历 - showLunar: { - type: Boolean, - default: uni.$u.props.calendar.showLunar - }, - // 是否显示月份背景色 - showMark: { - type: Boolean, - default: uni.$u.props.calendar.showMark - }, - // 确定按钮的文字 - confirmText: { - type: String, - default: uni.$u.props.calendar.confirmText - }, - // 确认按钮处于禁用状态时的文字 - confirmDisabledText: { - type: String, - default: uni.$u.props.calendar.confirmDisabledText - }, - // 是否显示日历弹窗 - show: { - type: Boolean, - default: uni.$u.props.calendar.show - }, - // 是否允许点击遮罩关闭日历 - closeOnClickOverlay: { - type: Boolean, - default: uni.$u.props.calendar.closeOnClickOverlay - }, - // 是否为只读状态,只读状态下禁止选择日期 - readonly: { - type: Boolean, - default: uni.$u.props.calendar.readonly - }, - // 是否展示确认按钮 - showConfirm: { - type: Boolean, - default: uni.$u.props.calendar.showConfirm - }, - // 日期区间最多可选天数,默认无限制,mode = range时有效 - maxRange: { - type: [Number, String], - default: uni.$u.props.calendar.maxRange - }, - // 范围选择超过最多可选天数时的提示文案,mode = range时有效 - rangePrompt: { - type: String, - default: uni.$u.props.calendar.rangePrompt - }, - // 范围选择超过最多可选天数时,是否展示提示文案,mode = range时有效 - showRangePrompt: { - type: Boolean, - default: uni.$u.props.calendar.showRangePrompt - }, - // 是否允许日期范围的起止时间为同一天,mode = range时有效 - allowSameDay: { - type: Boolean, - default: uni.$u.props.calendar.allowSameDay - }, - // 圆角值 - round: { - type: [Boolean, String, Number], - default: uni.$u.props.calendar.round - }, - // 最多展示月份数量 - monthNum: { - type: [Number, String], - default: 3 - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-calendar/u-calendar.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-calendar/u-calendar.vue deleted file mode 100644 index 511f99399..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-calendar/u-calendar.vue +++ /dev/null @@ -1,384 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-calendar/util.js b/yudao-ui-app/uni_modules/uview-ui/components/u-calendar/util.js deleted file mode 100644 index ca4736bb2..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-calendar/util.js +++ /dev/null @@ -1,85 +0,0 @@ -export default { - methods: { - // 设置月份数据 - setMonth() { - // 月初是周几 - const day = dayjs(this.date).date(1).day() - const start = day == 0 ? 6 : day - 1 - - // 本月天数 - const days = dayjs(this.date).endOf('month').format('D') - - // 上个月天数 - const prevDays = dayjs(this.date).endOf('month').subtract(1, 'month').format('D') - - // 日期数据 - const arr = [] - // 清空表格 - this.month = [] - - // 添加上月数据 - arr.push( - ...new Array(start).fill(1).map((e, i) => { - const day = prevDays - start + i + 1 - - return { - value: day, - disabled: true, - date: dayjs(this.date).subtract(1, 'month').date(day).format('YYYY-MM-DD') - } - }) - ) - - // 添加本月数据 - arr.push( - ...new Array(days - 0).fill(1).map((e, i) => { - const day = i + 1 - - return { - value: day, - date: dayjs(this.date).date(day).format('YYYY-MM-DD') - } - }) - ) - - // 添加下个月 - arr.push( - ...new Array(42 - days - start).fill(1).map((e, i) => { - const day = i + 1 - - return { - value: day, - disabled: true, - date: dayjs(this.date).add(1, 'month').date(day).format('YYYY-MM-DD') - } - }) - ) - - // 分割数组 - for (let n = 0; n < arr.length; n += 7) { - this.month.push( - arr.slice(n, n + 7).map((e, i) => { - e.index = i + n - - // 自定义信息 - const custom = this.customList.find((c) => c.date == e.date) - - // 农历 - if (this.lunar) { - const { - IDayCn, - IMonthCn - } = this.getLunar(e.date) - e.lunar = IDayCn == '初一' ? IMonthCn : IDayCn - } - - return { - ...e, - ...custom - } - }) - ) - } - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-car-keyboard/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-car-keyboard/props.js deleted file mode 100644 index 3553647a9..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-car-keyboard/props.js +++ /dev/null @@ -1,14 +0,0 @@ -export default { - props: { - // 是否打乱键盘按键的顺序 - random: { - type: Boolean, - default: false - }, - // 输入一个中文后,是否自动切换到英文 - autoChange: { - type: Boolean, - default: false - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-car-keyboard/u-car-keyboard.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-car-keyboard/u-car-keyboard.vue deleted file mode 100644 index 51175b54c..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-car-keyboard/u-car-keyboard.vue +++ /dev/null @@ -1,311 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-cell-group/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-cell-group/props.js deleted file mode 100644 index 350ef403e..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-cell-group/props.js +++ /dev/null @@ -1,14 +0,0 @@ -export default { - props: { - // 分组标题 - title: { - type: String, - default: uni.$u.props.cellGroup.title - }, - // 是否显示外边框 - border: { - type: Boolean, - default: uni.$u.props.cellGroup.border - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-cell-group/u-cell-group.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-cell-group/u-cell-group.vue deleted file mode 100644 index a9508c0c7..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-cell-group/u-cell-group.vue +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-cell/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-cell/props.js deleted file mode 100644 index da0333032..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-cell/props.js +++ /dev/null @@ -1,110 +0,0 @@ -export default { - props: { - // 标题 - title: { - type: [String, Number], - default: uni.$u.props.cell.title - }, - // 标题下方的描述信息 - label: { - type: [String, Number], - default: uni.$u.props.cell.label - }, - // 右侧的内容 - value: { - type: [String, Number], - default: uni.$u.props.cell.value - }, - // 左侧图标名称,或者图片链接(本地文件建议使用绝对地址) - icon: { - type: String, - default: uni.$u.props.cell.icon - }, - // 是否禁用cell - disabled: { - type: Boolean, - default: uni.$u.props.cell.disabled - }, - // 是否显示下边框 - border: { - type: Boolean, - default: uni.$u.props.cell.border - }, - // 内容是否垂直居中(主要是针对右侧的value部分) - center: { - type: Boolean, - default: uni.$u.props.cell.center - }, - // 点击后跳转的URL地址 - url: { - type: String, - default: uni.$u.props.cell.url - }, - // 链接跳转的方式,内部使用的是uView封装的route方法,可能会进行拦截操作 - linkType: { - type: String, - default: uni.$u.props.cell.linkType - }, - // 是否开启点击反馈(表现为点击时加上灰色背景) - clickable: { - type: Boolean, - default: uni.$u.props.cell.clickable - }, - // 是否展示右侧箭头并开启点击反馈 - isLink: { - type: Boolean, - default: uni.$u.props.cell.isLink - }, - // 是否显示表单状态下的必填星号(此组件可能会内嵌入input组件) - required: { - type: Boolean, - default: uni.$u.props.cell.required - }, - // 右侧的图标箭头 - rightIcon: { - type: String, - default: uni.$u.props.cell.rightIcon - }, - // 右侧箭头的方向,可选值为:left,up,down - arrowDirection: { - type: String, - default: uni.$u.props.cell.arrowDirection - }, - // 左侧图标样式 - iconStyle: { - type: [Object, String], - default: () => { - return uni.$u.props.cell.iconStyle - } - }, - // 右侧箭头图标的样式 - rightIconStyle: { - type: [Object, String], - default: () => { - return uni.$u.props.cell.rightIconStyle - } - }, - // 标题的样式 - titleStyle: { - type: [Object, String], - default: () => { - return uni.$u.props.cell.titleStyle - } - }, - // 单位元的大小,可选值为large - size: { - type: String, - default: uni.$u.props.cell.size - }, - // 点击cell是否阻止事件传播 - stop: { - type: Boolean, - default: uni.$u.props.cell.stop - }, - // 标识符,cell被点击时返回 - name: { - type: [Number, String], - default: uni.$u.props.cell.name - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-cell/u-cell.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-cell/u-cell.vue deleted file mode 100644 index b099c9070..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-cell/u-cell.vue +++ /dev/null @@ -1,229 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-checkbox-group/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-checkbox-group/props.js deleted file mode 100644 index 2f818a10c..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-checkbox-group/props.js +++ /dev/null @@ -1,82 +0,0 @@ -export default { - props: { - // 标识符 - name: { - type: String, - default: uni.$u.props.checkboxGroup.name - }, - // 绑定的值 - value: { - type: Array, - default: uni.$u.props.checkboxGroup.value - }, - // 形状,circle-圆形,square-方形 - shape: { - type: String, - default: uni.$u.props.checkboxGroup.shape - }, - // 是否禁用全部checkbox - disabled: { - type: Boolean, - default: uni.$u.props.checkboxGroup.disabled - }, - - // 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值 - activeColor: { - type: String, - default: uni.$u.props.checkboxGroup.activeColor - }, - // 未选中的颜色 - inactiveColor: { - type: String, - default: uni.$u.props.checkboxGroup.inactiveColor - }, - - // 整个组件的尺寸,默认px - size: { - type: [String, Number], - default: uni.$u.props.checkboxGroup.size - }, - // 布局方式,row-横向,column-纵向 - placement: { - type: String, - default: uni.$u.props.checkboxGroup.placement - }, - // label的字体大小,px单位 - labelSize: { - type: [String, Number], - default: uni.$u.props.checkboxGroup.labelSize - }, - // label的字体颜色 - labelColor: { - type: [String], - default: uni.$u.props.checkboxGroup.labelColor - }, - // 是否禁止点击文本操作 - labelDisabled: { - type: Boolean, - default: uni.$u.props.checkboxGroup.labelDisabled - }, - // 图标颜色 - iconColor: { - type: String, - default: uni.$u.props.checkboxGroup.iconColor - }, - // 图标的大小,单位px - iconSize: { - type: [String, Number], - default: uni.$u.props.checkboxGroup.iconSize - }, - // 勾选图标的对齐方式,left-左边,right-右边 - iconPlacement: { - type: String, - default: uni.$u.props.checkboxGroup.iconPlacement - }, - // 竖向配列时,是否显示下划线 - borderBottom: { - type: Boolean, - default: uni.$u.props.checkboxGroup.borderBottom - } - - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-checkbox-group/u-checkbox-group.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-checkbox-group/u-checkbox-group.vue deleted file mode 100644 index 7a6b4fa3c..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-checkbox-group/u-checkbox-group.vue +++ /dev/null @@ -1,103 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-checkbox/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-checkbox/props.js deleted file mode 100644 index 93f4fd9f2..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-checkbox/props.js +++ /dev/null @@ -1,69 +0,0 @@ -export default { - props: { - // checkbox的名称 - name: { - type: [String, Number, Boolean], - default: uni.$u.props.checkbox.name - }, - // 形状,square为方形,circle为圆型 - shape: { - type: String, - default: uni.$u.props.checkbox.shape - }, - // 整体的大小 - size: { - type: [String, Number], - default: uni.$u.props.checkbox.size - }, - // 是否默认选中 - checked: { - type: Boolean, - default: uni.$u.props.checkbox.checked - }, - // 是否禁用 - disabled: { - type: [String, Boolean], - default: uni.$u.props.checkbox.disabled - }, - // 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值 - activeColor: { - type: String, - default: uni.$u.props.checkbox.activeColor - }, - // 未选中的颜色 - inactiveColor: { - type: String, - default: uni.$u.props.checkbox.inactiveColor - }, - // 图标的大小,单位px - iconSize: { - type: [String, Number], - default: uni.$u.props.checkbox.iconSize - }, - // 图标颜色 - iconColor: { - type: String, - default: uni.$u.props.checkbox.iconColor - }, - // label提示文字,因为nvue下,直接slot进来的文字,由于特殊的结构,无法修改样式 - label: { - type: [String, Number], - default: uni.$u.props.checkbox.label - }, - // label的字体大小,px单位 - labelSize: { - type: [String, Number], - default: uni.$u.props.checkbox.labelSize - }, - // label的颜色 - labelColor: { - type: String, - default: uni.$u.props.checkbox.labelColor - }, - // 是否禁止点击提示语选中复选框 - labelDisabled: { - type: [String, Boolean], - default: uni.$u.props.checkbox.labelDisabled - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-checkbox/u-checkbox.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-checkbox/u-checkbox.vue deleted file mode 100644 index 6429cca94..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-checkbox/u-checkbox.vue +++ /dev/null @@ -1,344 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-circle-progress/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-circle-progress/props.js deleted file mode 100644 index d776cfb61..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-circle-progress/props.js +++ /dev/null @@ -1,8 +0,0 @@ -export default { - props: { - percentage: { - type: [String, Number], - default: uni.$u.props.circleProgress.percentage - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-circle-progress/u-circle-progress.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-circle-progress/u-circle-progress.vue deleted file mode 100644 index d1ee2867b..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-circle-progress/u-circle-progress.vue +++ /dev/null @@ -1,198 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-code-input/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-code-input/props.js deleted file mode 100644 index 0f016ee02..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-code-input/props.js +++ /dev/null @@ -1,79 +0,0 @@ -export default { - props: { - // 键盘弹起时,是否自动上推页面 - adjustPosition: { - type: Boolean, - default: uni.$u.props.codeInput.adjustPosition - }, - // 最大输入长度 - maxlength: { - type: [String, Number], - default: uni.$u.props.codeInput.maxlength - }, - // 是否用圆点填充 - dot: { - type: Boolean, - default: uni.$u.props.codeInput.dot - }, - // 显示模式,box-盒子模式,line-底部横线模式 - mode: { - type: String, - default: uni.$u.props.codeInput.mode - }, - // 是否细边框 - hairline: { - type: Boolean, - default: uni.$u.props.codeInput.hairline - }, - // 字符间的距离 - space: { - type: [String, Number], - default: uni.$u.props.codeInput.space - }, - // 预置值 - value: { - type: [String, Number], - default: uni.$u.props.codeInput.value - }, - // 是否自动获取焦点 - focus: { - type: Boolean, - default: uni.$u.props.codeInput.focus - }, - // 字体是否加粗 - bold: { - type: Boolean, - default: uni.$u.props.codeInput.bold - }, - // 字体颜色 - color: { - type: String, - default: uni.$u.props.codeInput.color - }, - // 字体大小 - fontSize: { - type: [String, Number], - default: uni.$u.props.codeInput.fontSize - }, - // 输入框的大小,宽等于高 - size: { - type: [String, Number], - default: uni.$u.props.codeInput.size - }, - // 是否隐藏原生键盘,如果想用自定义键盘的话,需设置此参数为true - disabledKeyboard: { - type: Boolean, - default: uni.$u.props.codeInput.disabledKeyboard - }, - // 边框和线条颜色 - borderColor: { - type: String, - default: uni.$u.props.codeInput.borderColor - }, - // 是否禁止输入"."符号 - disabledDot: { - type: Boolean, - default: uni.$u.props.codeInput.disabledDot - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-code-input/u-code-input.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-code-input/u-code-input.vue deleted file mode 100644 index 96241cfc6..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-code-input/u-code-input.vue +++ /dev/null @@ -1,252 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-code/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-code/props.js deleted file mode 100644 index eaf80d02f..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-code/props.js +++ /dev/null @@ -1,34 +0,0 @@ -export default { - props: { - // 倒计时总秒数 - seconds: { - type: [String, Number], - default: uni.$u.props.code.seconds - }, - // 尚未开始时提示 - startText: { - type: String, - default: uni.$u.props.code.startText - }, - // 正在倒计时中的提示 - changeText: { - type: String, - default: uni.$u.props.code.changeText - }, - // 倒计时结束时的提示 - endText: { - type: String, - default: uni.$u.props.code.endText - }, - // 是否在H5刷新或各端返回再进入时继续倒计时 - keepRunning: { - type: Boolean, - default: uni.$u.props.code.keepRunning - }, - // 为了区分多个页面,或者一个页面多个倒计时组件本地存储的继续倒计时变了 - uniqueKey: { - type: String, - default: uni.$u.props.code.uniqueKey - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-code/u-code.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-code/u-code.vue deleted file mode 100644 index f79a09ac9..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-code/u-code.vue +++ /dev/null @@ -1,129 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-col/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-col/props.js deleted file mode 100644 index 06222517e..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-col/props.js +++ /dev/null @@ -1,29 +0,0 @@ -export default { - props: { - // 占父容器宽度的多少等分,总分为12份 - span: { - type: [String, Number], - default: uni.$u.props.col.span - }, - // 指定栅格左侧的间隔数(总12栏) - offset: { - type: [String, Number], - default: uni.$u.props.col.offset - }, - // 水平排列方式,可选值为`start`(或`flex-start`)、`end`(或`flex-end`)、`center`、`around`(或`space-around`)、`between`(或`space-between`) - justify: { - type: String, - default: uni.$u.props.col.justify - }, - // 垂直对齐方式,可选值为top、center、bottom、stretch - align: { - type: String, - default: uni.$u.props.col.align - }, - // 文字对齐方式 - textAlign: { - type: String, - default: uni.$u.props.col.textAlign - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-col/u-col.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-col/u-col.vue deleted file mode 100644 index 8be151742..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-col/u-col.vue +++ /dev/null @@ -1,162 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-collapse-item/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-collapse-item/props.js deleted file mode 100644 index bd5749b62..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-collapse-item/props.js +++ /dev/null @@ -1,59 +0,0 @@ -export default { - props: { - // 标题 - title: { - type: String, - default: uni.$u.props.collapseItem.title - }, - // 标题右侧内容 - value: { - type: String, - default: uni.$u.props.collapseItem.value - }, - // 标题下方的描述信息 - label: { - type: String, - default: uni.$u.props.collapseItem.label - }, - // 是否禁用折叠面板 - disabled: { - type: Boolean, - default: uni.$u.props.collapseItem.disabled - }, - // 是否展示右侧箭头并开启点击反馈 - isLink: { - type: Boolean, - default: uni.$u.props.collapseItem.isLink - }, - // 是否开启点击反馈 - clickable: { - type: Boolean, - default: uni.$u.props.collapseItem.clickable - }, - // 是否显示内边框 - border: { - type: Boolean, - default: uni.$u.props.collapseItem.border - }, - // 标题的对齐方式 - align: { - type: String, - default: uni.$u.props.collapseItem.align - }, - // 唯一标识符 - name: { - type: [String, Number], - default: uni.$u.props.collapseItem.name - }, - // 标题左侧图片,可为绝对路径的图片或内置图标 - icon: { - type: String, - default: uni.$u.props.collapseItem.icon - }, - // 面板展开收起的过渡时间,单位ms - duration: { - type: Number, - default: uni.$u.props.collapseItem.duration - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-collapse-item/u-collapse-item.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-collapse-item/u-collapse-item.vue deleted file mode 100644 index 0e1b7039e..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-collapse-item/u-collapse-item.vue +++ /dev/null @@ -1,225 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-collapse/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-collapse/props.js deleted file mode 100644 index 7ee6d3198..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-collapse/props.js +++ /dev/null @@ -1,19 +0,0 @@ -export default { - props: { - // 当前展开面板的name,非手风琴模式:[],手风琴模式:string | number - value: { - type: [String, Number, Array, null], - default: uni.$u.props.collapse.value - }, - // 是否手风琴模式 - accordion: { - type: Boolean, - default: uni.$u.props.collapse.accordion - }, - // 是否显示外边框 - border: { - type: Boolean, - default: uni.$u.props.collapse.border - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-collapse/u-collapse.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-collapse/u-collapse.vue deleted file mode 100644 index fc188a2ea..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-collapse/u-collapse.vue +++ /dev/null @@ -1,90 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-column-notice/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-column-notice/props.js deleted file mode 100644 index 48091549f..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-column-notice/props.js +++ /dev/null @@ -1,55 +0,0 @@ -export default { - props: { - // 显示的内容,字符串 - text: { - type: [Array], - default: uni.$u.props.columnNotice.text - }, - // 是否显示左侧的音量图标 - icon: { - type: String, - default: uni.$u.props.columnNotice.icon - }, - // 通告模式,link-显示右箭头,closable-显示右侧关闭图标 - mode: { - type: String, - default: uni.$u.props.columnNotice.mode - }, - // 文字颜色,各图标也会使用文字颜色 - color: { - type: String, - default: uni.$u.props.columnNotice.color - }, - // 背景颜色 - bgColor: { - type: String, - default: uni.$u.props.columnNotice.bgColor - }, - // 字体大小,单位px - fontSize: { - type: [String, Number], - default: uni.$u.props.columnNotice.fontSize - }, - // 水平滚动时的滚动速度,即每秒滚动多少px(px),这有利于控制文字无论多少时,都能有一个恒定的速度 - speed: { - type: [String, Number], - default: uni.$u.props.columnNotice.speed - }, - // direction = row时,是否使用步进形式滚动 - step: { - type: Boolean, - default: uni.$u.props.columnNotice.step - }, - // 滚动一个周期的时间长,单位ms - duration: { - type: [String, Number], - default: uni.$u.props.columnNotice.duration - }, - // 是否禁止用手滑动切换 - // 目前HX2.6.11,只支持App 2.5.5+、H5 2.5.5+、支付宝小程序、字节跳动小程序 - disableTouch: { - type: Boolean, - default: uni.$u.props.columnNotice.disableTouch - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-column-notice/u-column-notice.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-column-notice/u-column-notice.vue deleted file mode 100644 index fc395321e..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-column-notice/u-column-notice.vue +++ /dev/null @@ -1,160 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-count-down/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-count-down/props.js deleted file mode 100644 index d62f02551..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-count-down/props.js +++ /dev/null @@ -1,24 +0,0 @@ -export default { - props: { - // 倒计时时长,单位ms - time: { - type: [String, Number], - default: uni.$u.props.countDown.time - }, - // 时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒 - format: { - type: String, - default: uni.$u.props.countDown.format - }, - // 是否自动开始倒计时 - autoStart: { - type: Boolean, - default: uni.$u.props.countDown.autoStart - }, - // 是否展示毫秒倒计时 - millisecond: { - type: Boolean, - default: uni.$u.props.countDown.millisecond - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-count-down/u-count-down.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-count-down/u-count-down.vue deleted file mode 100644 index b5e85a635..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-count-down/u-count-down.vue +++ /dev/null @@ -1,163 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-count-down/utils.js b/yudao-ui-app/uni_modules/uview-ui/components/u-count-down/utils.js deleted file mode 100644 index 8c7500501..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-count-down/utils.js +++ /dev/null @@ -1,62 +0,0 @@ -// 补0,如1 -> 01 -function padZero(num, targetLength = 2) { - let str = `${num}` - while (str.length < targetLength) { - str = `0${str}` - } - return str -} -const SECOND = 1000 -const MINUTE = 60 * SECOND -const HOUR = 60 * MINUTE -const DAY = 24 * HOUR -export function parseTimeData(time) { - const days = Math.floor(time / DAY) - const hours = Math.floor((time % DAY) / HOUR) - const minutes = Math.floor((time % HOUR) / MINUTE) - const seconds = Math.floor((time % MINUTE) / SECOND) - const milliseconds = Math.floor(time % SECOND) - return { - days, - hours, - minutes, - seconds, - milliseconds - } -} -export function parseFormat(format, timeData) { - let { - days, - hours, - minutes, - seconds, - milliseconds - } = timeData - // 如果格式化字符串中不存在DD(天),则将天的时间转为小时中去 - if (format.indexOf('DD') === -1) { - hours += days * 24 - } else { - // 对天补0 - format = format.replace('DD', padZero(days)) - } - // 其他同理于DD的格式化处理方式 - if (format.indexOf('HH') === -1) { - minutes += hours * 60 - } else { - format = format.replace('HH', padZero(hours)) - } - if (format.indexOf('mm') === -1) { - seconds += minutes * 60 - } else { - format = format.replace('mm', padZero(minutes)) - } - if (format.indexOf('ss') === -1) { - milliseconds += seconds * 1000 - } else { - format = format.replace('ss', padZero(seconds)) - } - return format.replace('SSS', padZero(milliseconds, 3)) -} -export function isSameSecond(time1, time2) { - return Math.floor(time1 / 1000) === Math.floor(time2 / 1000) -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-count-to/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-count-to/props.js deleted file mode 100644 index 86873c184..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-count-to/props.js +++ /dev/null @@ -1,59 +0,0 @@ -export default { - props: { - // 开始的数值,默认从0增长到某一个数 - startVal: { - type: [String, Number], - default: uni.$u.props.countTo.startVal - }, - // 要滚动的目标数值,必须 - endVal: { - type: [String, Number], - default: uni.$u.props.countTo.endVal - }, - // 滚动到目标数值的动画持续时间,单位为毫秒(ms) - duration: { - type: [String, Number], - default: uni.$u.props.countTo.duration - }, - // 设置数值后是否自动开始滚动 - autoplay: { - type: Boolean, - default: uni.$u.props.countTo.autoplay - }, - // 要显示的小数位数 - decimals: { - type: [String, Number], - default: uni.$u.props.countTo.decimals - }, - // 是否在即将到达目标数值的时候,使用缓慢滚动的效果 - useEasing: { - type: Boolean, - default: uni.$u.props.countTo.useEasing - }, - // 十进制分割 - decimal: { - type: [String, Number], - default: uni.$u.props.countTo.decimal - }, - // 字体颜色 - color: { - type: String, - default: uni.$u.props.countTo.color - }, - // 字体大小 - fontSize: { - type: [String, Number], - default: uni.$u.props.countTo.fontSize - }, - // 是否加粗字体 - bold: { - type: Boolean, - default: uni.$u.props.countTo.bold - }, - // 千位分隔符,类似金额的分割(¥23,321.05中的",") - separator: { - type: String, - default: uni.$u.props.countTo.separator - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-count-to/u-count-to.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-count-to/u-count-to.vue deleted file mode 100644 index 417b7327b..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-count-to/u-count-to.vue +++ /dev/null @@ -1,184 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-datetime-picker/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-datetime-picker/props.js deleted file mode 100644 index f44c0f99a..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-datetime-picker/props.js +++ /dev/null @@ -1,116 +0,0 @@ -export default { - props: { - // 是否打开组件 - show: { - type: Boolean, - default: uni.$u.props.datetimePicker.show - }, - // 是否展示顶部的操作栏 - showToolbar: { - type: Boolean, - default: uni.$u.props.datetimePicker.showToolbar - }, - // 绑定值 - value: { - type: [String, Number], - default: uni.$u.props.datetimePicker.value - }, - // 顶部标题 - title: { - type: String, - default: uni.$u.props.datetimePicker.title - }, - // 展示格式,mode=date为日期选择,mode=time为时间选择,mode=year-month为年月选择,mode=datetime为日期时间选择 - mode: { - type: String, - default: uni.$u.props.datetimePicker.mode - }, - // 可选的最大时间 - maxDate: { - type: Number, - // 最大默认值为后10年 - default: uni.$u.props.datetimePicker.maxDate - }, - // 可选的最小时间 - minDate: { - type: Number, - // 最小默认值为前10年 - default: uni.$u.props.datetimePicker.minDate - }, - // 可选的最小小时,仅mode=time有效 - minHour: { - type: Number, - default: uni.$u.props.datetimePicker.minHour - }, - // 可选的最大小时,仅mode=time有效 - maxHour: { - type: Number, - default: uni.$u.props.datetimePicker.maxHour - }, - // 可选的最小分钟,仅mode=time有效 - minMinute: { - type: Number, - default: uni.$u.props.datetimePicker.minMinute - }, - // 可选的最大分钟,仅mode=time有效 - maxMinute: { - type: Number, - default: uni.$u.props.datetimePicker.maxMinute - }, - // 选项过滤函数 - filter: { - type: [Function, null], - default: uni.$u.props.datetimePicker.filter - }, - // 选项格式化函数 - formatter: { - type: [Function, null], - default: uni.$u.props.datetimePicker.formatter - }, - // 是否显示加载中状态 - loading: { - type: Boolean, - default: uni.$u.props.datetimePicker.loading - }, - // 各列中,单个选项的高度 - itemHeight: { - type: [String, Number], - default: uni.$u.props.datetimePicker.itemHeight - }, - // 取消按钮的文字 - cancelText: { - type: String, - default: uni.$u.props.datetimePicker.cancelText - }, - // 确认按钮的文字 - confirmText: { - type: String, - default: uni.$u.props.datetimePicker.confirmText - }, - // 取消按钮的颜色 - cancelColor: { - type: String, - default: uni.$u.props.datetimePicker.cancelColor - }, - // 确认按钮的颜色 - confirmColor: { - type: String, - default: uni.$u.props.datetimePicker.confirmColor - }, - // 每列中可见选项的数量 - visibleItemCount: { - type: [String, Number], - default: uni.$u.props.datetimePicker.visibleItemCount - }, - // 是否允许点击遮罩关闭选择器 - closeOnClickOverlay: { - type: Boolean, - default: uni.$u.props.datetimePicker.closeOnClickOverlay - }, - // 各列的默认索引 - defaultIndex: { - type: Array, - default: uni.$u.props.datetimePicker.defaultIndex - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-datetime-picker/u-datetime-picker.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-datetime-picker/u-datetime-picker.vue deleted file mode 100644 index 18d8dcc67..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-datetime-picker/u-datetime-picker.vue +++ /dev/null @@ -1,360 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-divider/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-divider/props.js deleted file mode 100644 index 1fa8359fc..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-divider/props.js +++ /dev/null @@ -1,44 +0,0 @@ -export default { - props: { - // 是否虚线 - dashed: { - type: Boolean, - default: uni.$u.props.divider.dashed - }, - // 是否细线 - hairline: { - type: Boolean, - default: uni.$u.props.divider.hairline - }, - // 是否以点替代文字,优先于text字段起作用 - dot: { - type: Boolean, - default: uni.$u.props.divider.dot - }, - // 内容文本的位置,left-左边,center-中间,right-右边 - textPosition: { - type: String, - default: uni.$u.props.divider.textPosition - }, - // 文本内容 - text: { - type: [String, Number], - default: uni.$u.props.divider.text - }, - // 文本大小 - textSize: { - type: [String, Number], - default: uni.$u.props.divider.textSize - }, - // 文本颜色 - textColor: { - type: String, - default: uni.$u.props.divider.textColor - }, - // 线条颜色 - lineColor: { - type: String, - default: uni.$u.props.divider.lineColor - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-divider/u-divider.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-divider/u-divider.vue deleted file mode 100644 index b629da64a..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-divider/u-divider.vue +++ /dev/null @@ -1,116 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-dropdown-item/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-dropdown-item/props.js deleted file mode 100644 index 501a1f058..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-dropdown-item/props.js +++ /dev/null @@ -1,36 +0,0 @@ -export default { - props: { - // 当前选中项的value值 - value: { - type: [Number, String, Array], - default: '' - }, - // 菜单项标题 - title: { - type: [String, Number], - default: '' - }, - // 选项数据,如果传入了默认slot,此参数无效 - options: { - type: Array, - default() { - return [] - } - }, - // 是否禁用此菜单项 - disabled: { - type: Boolean, - default: false - }, - // 下拉弹窗的高度 - height: { - type: [Number, String], - default: 'auto' - }, - // 点击遮罩是否可以收起弹窗 - closeOnClickOverlay: { - type: Boolean, - default: true - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-dropdown-item/u-dropdown-item.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-dropdown-item/u-dropdown-item.vue deleted file mode 100644 index f830291a2..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-dropdown-item/u-dropdown-item.vue +++ /dev/null @@ -1,127 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-dropdown/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-dropdown/props.js deleted file mode 100644 index 5f8465efe..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-dropdown/props.js +++ /dev/null @@ -1,65 +0,0 @@ -export default { - props: { - // 标题选中时的样式 - activeStyle: { - type: [String, Object], - default: () => ({ - color: '#2979ff', - fontSize: '14px' - }) - }, - // 标题未选中时的样式 - inactiveStyle: { - type: [String, Object], - default: () => ({ - color: '#606266', - fontSize: '14px' - }) - }, - // 点击遮罩是否关闭菜单 - closeOnClickMask: { - type: Boolean, - default: true - }, - // 点击当前激活项标题是否关闭菜单 - closeOnClickSelf: { - type: Boolean, - default: true - }, - // 过渡时间 - duration: { - type: [Number, String], - default: 300 - }, - // 标题菜单的高度 - height: { - type: [Number, String], - default: 40 - }, - // 是否显示下边框 - borderBottom: { - type: Boolean, - default: false - }, - // 标题的字体大小 - titleSize: { - type: [Number, String], - default: 14 - }, - // 下拉出来的内容部分的圆角值 - borderRadius: { - type: [Number, String], - default: 0 - }, - // 菜单右侧的icon图标 - menuIcon: { - type: String, - default: 'arrow-down' - }, - // 菜单右侧图标的大小 - menuIconSize: { - type: [Number, String], - default: 14 - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-dropdown/u-dropdown.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-dropdown/u-dropdown.vue deleted file mode 100644 index f830291a2..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-dropdown/u-dropdown.vue +++ /dev/null @@ -1,127 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-empty/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-empty/props.js deleted file mode 100644 index 78662f8fd..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-empty/props.js +++ /dev/null @@ -1,59 +0,0 @@ -export default { - props: { - // 内置图标名称,或图片路径,建议绝对路径 - icon: { - type: String, - default: uni.$u.props.empty.icon - }, - // 提示文字 - text: { - type: String, - default: uni.$u.props.empty.text - }, - // 文字颜色 - textColor: { - type: String, - default: uni.$u.props.empty.textColor - }, - // 文字大小 - textSize: { - type: [String, Number], - default: uni.$u.props.empty.textSize - }, - // 图标的颜色 - iconColor: { - type: String, - default: uni.$u.props.empty.iconColor - }, - // 图标的大小 - iconSize: { - type: [String, Number], - default: uni.$u.props.empty.iconSize - }, - // 选择预置的图标类型 - mode: { - type: String, - default: uni.$u.props.empty.mode - }, - // 图标宽度,单位px - width: { - type: [String, Number], - default: uni.$u.props.empty.width - }, - // 图标高度,单位px - height: { - type: [String, Number], - default: uni.$u.props.empty.height - }, - // 是否显示组件 - show: { - type: Boolean, - default: uni.$u.props.empty.show - }, - // 组件距离上一个元素之间的距离,默认px单位 - marginTop: { - type: [String, Number], - default: uni.$u.props.empty.marginTop - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-empty/u-empty.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-empty/u-empty.vue deleted file mode 100644 index 03d6a2736..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-empty/u-empty.vue +++ /dev/null @@ -1,128 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-form-item/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-form-item/props.js deleted file mode 100644 index 7b1665561..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-form-item/props.js +++ /dev/null @@ -1,48 +0,0 @@ -export default { - props: { - // input的label提示语 - label: { - type: String, - default: uni.$u.props.formItem.label - }, - // 绑定的值 - prop: { - type: String, - default: uni.$u.props.formItem.prop - }, - // 是否显示表单域的下划线边框 - borderBottom: { - type: [String, Boolean], - default: uni.$u.props.formItem.borderBottom - }, - // label的位置,left-左边,top-上边 - labelPosition: { - type: String, - default: uni.$u.props.formItem.labelPosition - }, - // label的宽度,单位px - labelWidth: { - type: [String, Number], - default: uni.$u.props.formItem.labelWidth - }, - // 右侧图标 - rightIcon: { - type: String, - default: uni.$u.props.formItem.rightIcon - }, - // 左侧图标 - leftIcon: { - type: String, - default: uni.$u.props.formItem.leftIcon - }, - // 是否显示左边的必填星号,只作显示用,具体校验必填的逻辑,请在rules中配置 - required: { - type: Boolean, - default: uni.$u.props.formItem.required - }, - leftIconStyle: { - type: [String, Object], - default: uni.$u.props.formItem.leftIconStyle, - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-form-item/u-form-item.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-form-item/u-form-item.vue deleted file mode 100644 index 6aa8d6909..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-form-item/u-form-item.vue +++ /dev/null @@ -1,235 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-form/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-form/props.js deleted file mode 100644 index f2a629c0e..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-form/props.js +++ /dev/null @@ -1,45 +0,0 @@ -export default { - props: { - // 当前form的需要验证字段的集合 - model: { - type: Object, - default: uni.$u.props.form.model - }, - // 验证规则 - rules: { - type: [Object, Function, Array], - default: uni.$u.props.form.rules - }, - // 有错误时的提示方式,message-提示信息,toast-进行toast提示 - // border-bottom-下边框呈现红色,none-无提示 - errorType: { - type: String, - default: uni.$u.props.form.errorType - }, - // 是否显示表单域的下划线边框 - borderBottom: { - type: Boolean, - default: uni.$u.props.form.borderBottom - }, - // label的位置,left-左边,top-上边 - labelPosition: { - type: String, - default: uni.$u.props.form.labelPosition - }, - // label的宽度,单位px - labelWidth: { - type: [String, Number], - default: uni.$u.props.form.labelWidth - }, - // lable字体的对齐方式 - labelAlign: { - type: String, - default: uni.$u.props.form.labelAlign - }, - // lable的样式,对象形式 - labelStyle: { - type: Object, - default: uni.$u.props.form.labelStyle - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-form/u-form.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-form/u-form.vue deleted file mode 100644 index fe2dde2d3..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-form/u-form.vue +++ /dev/null @@ -1,214 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-gap/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-gap/props.js deleted file mode 100644 index 89953e32a..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-gap/props.js +++ /dev/null @@ -1,24 +0,0 @@ -export default { - props: { - // 背景颜色(默认transparent) - bgColor: { - type: String, - default: uni.$u.props.gap.bgColor - }, - // 分割槽高度,单位px(默认30) - height: { - type: [String, Number], - default: uni.$u.props.gap.height - }, - // 与上一个组件的距离 - marginTop: { - type: [String, Number], - default: uni.$u.props.gap.marginTop - }, - // 与下一个组件的距离 - marginBottom: { - type: [String, Number], - default: uni.$u.props.gap.marginBottom - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-gap/u-gap.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-gap/u-gap.vue deleted file mode 100644 index e4429f0e4..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-gap/u-gap.vue +++ /dev/null @@ -1,38 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-grid-item/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-grid-item/props.js deleted file mode 100644 index 06c3c6637..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-grid-item/props.js +++ /dev/null @@ -1,14 +0,0 @@ -export default { - props: { - // 宫格的name - name: { - type: [String, Number, null], - default: uni.$u.props.gridItem.name - }, - // 背景颜色 - bgColor: { - type: String, - default: uni.$u.props.gridItem.bgColor - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-grid-item/u-grid-item.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-grid-item/u-grid-item.vue deleted file mode 100644 index fc0c7cf1d..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-grid-item/u-grid-item.vue +++ /dev/null @@ -1,209 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-grid/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-grid/props.js deleted file mode 100644 index 87b0f6a74..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-grid/props.js +++ /dev/null @@ -1,19 +0,0 @@ -export default { - props: { - // 分成几列 - col: { - type: [String, Number], - default: uni.$u.props.grid.col - }, - // 是否显示边框 - border: { - type: Boolean, - default: uni.$u.props.grid.border - }, - // 宫格对齐方式,表现为数量少的时候,靠左,居中,还是靠右 - align: { - type: String, - default: uni.$u.props.grid.align - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-grid/u-grid.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-grid/u-grid.vue deleted file mode 100644 index b43cc270a..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-grid/u-grid.vue +++ /dev/null @@ -1,97 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-icon/icons.js b/yudao-ui-app/uni_modules/uview-ui/components/u-icon/icons.js deleted file mode 100644 index f4d0fe293..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-icon/icons.js +++ /dev/null @@ -1,214 +0,0 @@ -export default { - 'uicon-level': '\ue693', - 'uicon-column-line': '\ue68e', - 'uicon-checkbox-mark': '\ue807', - 'uicon-folder': '\ue7f5', - 'uicon-movie': '\ue7f6', - 'uicon-star-fill': '\ue669', - 'uicon-star': '\ue65f', - 'uicon-phone-fill': '\ue64f', - 'uicon-phone': '\ue622', - 'uicon-apple-fill': '\ue881', - 'uicon-chrome-circle-fill': '\ue885', - 'uicon-backspace': '\ue67b', - 'uicon-attach': '\ue632', - 'uicon-cut': '\ue948', - 'uicon-empty-car': '\ue602', - 'uicon-empty-coupon': '\ue682', - 'uicon-empty-address': '\ue646', - 'uicon-empty-favor': '\ue67c', - 'uicon-empty-permission': '\ue686', - 'uicon-empty-news': '\ue687', - 'uicon-empty-search': '\ue664', - 'uicon-github-circle-fill': '\ue887', - 'uicon-rmb': '\ue608', - 'uicon-person-delete-fill': '\ue66a', - 'uicon-reload': '\ue788', - 'uicon-order': '\ue68f', - 'uicon-server-man': '\ue6bc', - 'uicon-search': '\ue62a', - 'uicon-fingerprint': '\ue955', - 'uicon-more-dot-fill': '\ue630', - 'uicon-scan': '\ue662', - 'uicon-share-square': '\ue60b', - 'uicon-map': '\ue61d', - 'uicon-map-fill': '\ue64e', - 'uicon-tags': '\ue629', - 'uicon-tags-fill': '\ue651', - 'uicon-bookmark-fill': '\ue63b', - 'uicon-bookmark': '\ue60a', - 'uicon-eye': '\ue613', - 'uicon-eye-fill': '\ue641', - 'uicon-mic': '\ue64a', - 'uicon-mic-off': '\ue649', - 'uicon-calendar': '\ue66e', - 'uicon-calendar-fill': '\ue634', - 'uicon-trash': '\ue623', - 'uicon-trash-fill': '\ue658', - 'uicon-play-left': '\ue66d', - 'uicon-play-right': '\ue610', - 'uicon-minus': '\ue618', - 'uicon-plus': '\ue62d', - 'uicon-info': '\ue653', - 'uicon-info-circle': '\ue7d2', - 'uicon-info-circle-fill': '\ue64b', - 'uicon-question': '\ue715', - 'uicon-error': '\ue6d3', - 'uicon-close': '\ue685', - 'uicon-checkmark': '\ue6a8', - 'uicon-android-circle-fill': '\ue67e', - 'uicon-android-fill': '\ue67d', - 'uicon-ie': '\ue87b', - 'uicon-IE-circle-fill': '\ue889', - 'uicon-google': '\ue87a', - 'uicon-google-circle-fill': '\ue88a', - 'uicon-setting-fill': '\ue872', - 'uicon-setting': '\ue61f', - 'uicon-minus-square-fill': '\ue855', - 'uicon-plus-square-fill': '\ue856', - 'uicon-heart': '\ue7df', - 'uicon-heart-fill': '\ue851', - 'uicon-camera': '\ue7d7', - 'uicon-camera-fill': '\ue870', - 'uicon-more-circle': '\ue63e', - 'uicon-more-circle-fill': '\ue645', - 'uicon-chat': '\ue620', - 'uicon-chat-fill': '\ue61e', - 'uicon-bag-fill': '\ue617', - 'uicon-bag': '\ue619', - 'uicon-error-circle-fill': '\ue62c', - 'uicon-error-circle': '\ue624', - 'uicon-close-circle': '\ue63f', - 'uicon-close-circle-fill': '\ue637', - 'uicon-checkmark-circle': '\ue63d', - 'uicon-checkmark-circle-fill': '\ue635', - 'uicon-question-circle-fill': '\ue666', - 'uicon-question-circle': '\ue625', - 'uicon-share': '\ue631', - 'uicon-share-fill': '\ue65e', - 'uicon-shopping-cart': '\ue621', - 'uicon-shopping-cart-fill': '\ue65d', - 'uicon-bell': '\ue609', - 'uicon-bell-fill': '\ue640', - 'uicon-list': '\ue650', - 'uicon-list-dot': '\ue616', - 'uicon-zhihu': '\ue6ba', - 'uicon-zhihu-circle-fill': '\ue709', - 'uicon-zhifubao': '\ue6b9', - 'uicon-zhifubao-circle-fill': '\ue6b8', - 'uicon-weixin-circle-fill': '\ue6b1', - 'uicon-weixin-fill': '\ue6b2', - 'uicon-twitter-circle-fill': '\ue6ab', - 'uicon-twitter': '\ue6aa', - 'uicon-taobao-circle-fill': '\ue6a7', - 'uicon-taobao': '\ue6a6', - 'uicon-weibo-circle-fill': '\ue6a5', - 'uicon-weibo': '\ue6a4', - 'uicon-qq-fill': '\ue6a1', - 'uicon-qq-circle-fill': '\ue6a0', - 'uicon-moments-circel-fill': '\ue69a', - 'uicon-moments': '\ue69b', - 'uicon-qzone': '\ue695', - 'uicon-qzone-circle-fill': '\ue696', - 'uicon-baidu-circle-fill': '\ue680', - 'uicon-baidu': '\ue681', - 'uicon-facebook-circle-fill': '\ue68a', - 'uicon-facebook': '\ue689', - 'uicon-car': '\ue60c', - 'uicon-car-fill': '\ue636', - 'uicon-warning-fill': '\ue64d', - 'uicon-warning': '\ue694', - 'uicon-clock-fill': '\ue638', - 'uicon-clock': '\ue60f', - 'uicon-edit-pen': '\ue612', - 'uicon-edit-pen-fill': '\ue66b', - 'uicon-email': '\ue611', - 'uicon-email-fill': '\ue642', - 'uicon-minus-circle': '\ue61b', - 'uicon-minus-circle-fill': '\ue652', - 'uicon-plus-circle': '\ue62e', - 'uicon-plus-circle-fill': '\ue661', - 'uicon-file-text': '\ue663', - 'uicon-file-text-fill': '\ue665', - 'uicon-pushpin': '\ue7e3', - 'uicon-pushpin-fill': '\ue86e', - 'uicon-grid': '\ue673', - 'uicon-grid-fill': '\ue678', - 'uicon-play-circle': '\ue647', - 'uicon-play-circle-fill': '\ue655', - 'uicon-pause-circle-fill': '\ue654', - 'uicon-pause': '\ue8fa', - 'uicon-pause-circle': '\ue643', - 'uicon-eye-off': '\ue648', - 'uicon-eye-off-outline': '\ue62b', - 'uicon-gift-fill': '\ue65c', - 'uicon-gift': '\ue65b', - 'uicon-rmb-circle-fill': '\ue657', - 'uicon-rmb-circle': '\ue677', - 'uicon-kefu-ermai': '\ue656', - 'uicon-server-fill': '\ue751', - 'uicon-coupon-fill': '\ue8c4', - 'uicon-coupon': '\ue8ae', - 'uicon-integral': '\ue704', - 'uicon-integral-fill': '\ue703', - 'uicon-home-fill': '\ue964', - 'uicon-home': '\ue965', - 'uicon-hourglass-half-fill': '\ue966', - 'uicon-hourglass': '\ue967', - 'uicon-account': '\ue628', - 'uicon-plus-people-fill': '\ue626', - 'uicon-minus-people-fill': '\ue615', - 'uicon-account-fill': '\ue614', - 'uicon-thumb-down-fill': '\ue726', - 'uicon-thumb-down': '\ue727', - 'uicon-thumb-up': '\ue733', - 'uicon-thumb-up-fill': '\ue72f', - 'uicon-lock-fill': '\ue979', - 'uicon-lock-open': '\ue973', - 'uicon-lock-opened-fill': '\ue974', - 'uicon-lock': '\ue97a', - 'uicon-red-packet-fill': '\ue690', - 'uicon-photo-fill': '\ue98b', - 'uicon-photo': '\ue98d', - 'uicon-volume-off-fill': '\ue659', - 'uicon-volume-off': '\ue644', - 'uicon-volume-fill': '\ue670', - 'uicon-volume': '\ue633', - 'uicon-red-packet': '\ue691', - 'uicon-download': '\ue63c', - 'uicon-arrow-up-fill': '\ue6b0', - 'uicon-arrow-down-fill': '\ue600', - 'uicon-play-left-fill': '\ue675', - 'uicon-play-right-fill': '\ue676', - 'uicon-rewind-left-fill': '\ue679', - 'uicon-rewind-right-fill': '\ue67a', - 'uicon-arrow-downward': '\ue604', - 'uicon-arrow-leftward': '\ue601', - 'uicon-arrow-rightward': '\ue603', - 'uicon-arrow-upward': '\ue607', - 'uicon-arrow-down': '\ue60d', - 'uicon-arrow-right': '\ue605', - 'uicon-arrow-left': '\ue60e', - 'uicon-arrow-up': '\ue606', - 'uicon-skip-back-left': '\ue674', - 'uicon-skip-forward-right': '\ue672', - 'uicon-rewind-right': '\ue66f', - 'uicon-rewind-left': '\ue671', - 'uicon-arrow-right-double': '\ue68d', - 'uicon-arrow-left-double': '\ue68c', - 'uicon-wifi-off': '\ue668', - 'uicon-wifi': '\ue667', - 'uicon-empty-data': '\ue62f', - 'uicon-empty-history': '\ue684', - 'uicon-empty-list': '\ue68b', - 'uicon-empty-page': '\ue627', - 'uicon-empty-order': '\ue639', - 'uicon-man': '\ue697', - 'uicon-woman': '\ue69c', - 'uicon-man-add': '\ue61c', - 'uicon-man-add-fill': '\ue64c', - 'uicon-man-delete': '\ue61a', - 'uicon-man-delete-fill': '\ue66a', - 'uicon-zh': '\ue70a', - 'uicon-en': '\ue692' -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-icon/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-icon/props.js deleted file mode 100644 index 71845b7ca..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-icon/props.js +++ /dev/null @@ -1,89 +0,0 @@ -export default { - props: { - // 图标类名 - name: { - type: String, - default: uni.$u.props.icon.name - }, - // 图标颜色,可接受主题色 - color: { - type: String, - default: uni.$u.props.icon.color - }, - // 字体大小,单位px - size: { - type: [String, Number], - default: uni.$u.props.icon.size - }, - // 是否显示粗体 - bold: { - type: Boolean, - default: uni.$u.props.icon.bold - }, - // 点击图标的时候传递事件出去的index(用于区分点击了哪一个) - index: { - type: [String, Number], - default: uni.$u.props.icon.index - }, - // 触摸图标时的类名 - hoverClass: { - type: String, - default: uni.$u.props.icon.hoverClass - }, - // 自定义扩展前缀,方便用户扩展自己的图标库 - customPrefix: { - type: String, - default: uni.$u.props.icon.customPrefix - }, - // 图标右边或者下面的文字 - label: { - type: [String, Number], - default: uni.$u.props.icon.label - }, - // label的位置,只能右边或者下边 - labelPos: { - type: String, - default: uni.$u.props.icon.labelPos - }, - // label的大小 - labelSize: { - type: [String, Number], - default: uni.$u.props.icon.labelSize - }, - // label的颜色 - labelColor: { - type: String, - default: uni.$u.props.icon.labelColor - }, - // label与图标的距离 - space: { - type: [String, Number], - default: uni.$u.props.icon.space - }, - // 图片的mode - imgMode: { - type: String, - default: uni.$u.props.icon.imgMode - }, - // 用于显示图片小图标时,图片的宽度 - width: { - type: [String, Number], - default: uni.$u.props.icon.width - }, - // 用于显示图片小图标时,图片的高度 - height: { - type: [String, Number], - default: uni.$u.props.icon.height - }, - // 用于解决某些情况下,让图标垂直居中的用途 - top: { - type: [String, Number], - default: uni.$u.props.icon.top - }, - // 是否阻止事件传播 - stop: { - type: Boolean, - default: uni.$u.props.icon.stop - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-icon/u-icon.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-icon/u-icon.vue deleted file mode 100644 index 9340328ee..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-icon/u-icon.vue +++ /dev/null @@ -1,234 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-image/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-image/props.js deleted file mode 100644 index 2eabb746b..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-image/props.js +++ /dev/null @@ -1,84 +0,0 @@ -export default { - props: { - // 图片地址 - src: { - type: String, - default: uni.$u.props.image.src - }, - // 裁剪模式 - mode: { - type: String, - default: uni.$u.props.image.mode - }, - // 宽度,单位任意 - width: { - type: [String, Number], - default: uni.$u.props.image.width - }, - // 高度,单位任意 - height: { - type: [String, Number], - default: uni.$u.props.image.height - }, - // 图片形状,circle-圆形,square-方形 - shape: { - type: String, - default: uni.$u.props.image.shape - }, - // 圆角,单位任意 - radius: { - type: [String, Number], - default: uni.$u.props.image.radius - }, - // 是否懒加载,微信小程序、App、百度小程序、字节跳动小程序 - lazyLoad: { - type: Boolean, - default: uni.$u.props.image.lazyLoad - }, - // 开启长按图片显示识别微信小程序码菜单 - showMenuByLongpress: { - type: Boolean, - default: uni.$u.props.image.showMenuByLongpress - }, - // 加载中的图标,或者小图片 - loadingIcon: { - type: String, - default: uni.$u.props.image.loadingIcon - }, - // 加载失败的图标,或者小图片 - errorIcon: { - type: String, - default: uni.$u.props.image.errorIcon - }, - // 是否显示加载中的图标或者自定义的slot - showLoading: { - type: Boolean, - default: uni.$u.props.image.showLoading - }, - // 是否显示加载错误的图标或者自定义的slot - showError: { - type: Boolean, - default: uni.$u.props.image.showError - }, - // 是否需要淡入效果 - fade: { - type: Boolean, - default: uni.$u.props.image.fade - }, - // 只支持网络资源,只对微信小程序有效 - webp: { - type: Boolean, - default: uni.$u.props.image.webp - }, - // 过渡时间,单位ms - duration: { - type: [String, Number], - default: uni.$u.props.image.duration - }, - // 背景颜色,用于深色页面加载图片时,为了和背景色融合 - bgColor: { - type: String, - default: uni.$u.props.image.bgColor - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-image/u-image.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-image/u-image.vue deleted file mode 100644 index 473e35b44..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-image/u-image.vue +++ /dev/null @@ -1,232 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-index-anchor/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-index-anchor/props.js deleted file mode 100644 index 6d8b59a72..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-index-anchor/props.js +++ /dev/null @@ -1,29 +0,0 @@ -export default { - props: { - // 列表锚点文本内容 - text: { - type: [String, Number], - default: uni.$u.props.indexAnchor.text - }, - // 列表锚点文字颜色 - color: { - type: String, - default: uni.$u.props.indexAnchor.color - }, - // 列表锚点文字大小,单位默认px - size: { - type: [String, Number], - default: uni.$u.props.indexAnchor.size - }, - // 列表锚点背景颜色 - bgColor: { - type: String, - default: uni.$u.props.indexAnchor.bgColor - }, - // 列表锚点高度,单位默认px - height: { - type: [String, Number], - default: uni.$u.props.indexAnchor.height - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-index-anchor/u-index-anchor.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-index-anchor/u-index-anchor.vue deleted file mode 100644 index b95ddef9e..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-index-anchor/u-index-anchor.vue +++ /dev/null @@ -1,91 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-index-item/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-index-item/props.js deleted file mode 100644 index 7c1133117..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-index-item/props.js +++ /dev/null @@ -1,5 +0,0 @@ -export default { - props: { - - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-index-item/u-index-item.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-index-item/u-index-item.vue deleted file mode 100644 index 0bc7fb3cd..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-index-item/u-index-item.vue +++ /dev/null @@ -1,87 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-index-list/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-index-list/props.js deleted file mode 100644 index 354d45914..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-index-list/props.js +++ /dev/null @@ -1,29 +0,0 @@ -export default { - props: { - // 右边锚点非激活的颜色 - inactiveColor: { - type: String, - default: uni.$u.props.indexList.inactiveColor - }, - // 右边锚点激活的颜色 - activeColor: { - type: String, - default: uni.$u.props.indexList.activeColor - }, - // 索引字符列表,数组形式 - indexList: { - type: Array, - default: uni.$u.props.indexList.indexList - }, - // 是否开启锚点自动吸顶 - sticky: { - type: Boolean, - default: uni.$u.props.indexList.sticky - }, - // 自定义导航栏的高度 - customNavHeight: { - type: [String, Number], - default: uni.$u.props.indexList.customNavHeight - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-index-list/u-index-list.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-index-list/u-index-list.vue deleted file mode 100644 index d71261853..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-index-list/u-index-list.vue +++ /dev/null @@ -1,440 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-input/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-input/props.js deleted file mode 100644 index 2c5087010..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-input/props.js +++ /dev/null @@ -1,187 +0,0 @@ -export default { - props: { - // 输入的值 - value: { - type: [String, Number], - default: uni.$u.props.input.value - }, - // 输入框类型 - // number-数字输入键盘,app-vue下可以输入浮点数,app-nvue和小程序平台下只能输入整数 - // idcard-身份证输入键盘,微信、支付宝、百度、QQ小程序 - // digit-带小数点的数字键盘,App的nvue页面、微信、支付宝、百度、头条、QQ小程序 - // text-文本输入键盘 - type: { - type: String, - default: uni.$u.props.input.type - }, - // 如果 textarea 是在一个 position:fixed 的区域,需要显示指定属性 fixed 为 true, - // 兼容性:微信小程序、百度小程序、字节跳动小程序、QQ小程序 - fixed: { - type: Boolean, - default: uni.$u.props.input.fixed - }, - // 是否禁用输入框 - disabled: { - type: Boolean, - default: uni.$u.props.input.disabled - }, - // 禁用状态时的背景色 - disabledColor: { - type: String, - default: uni.$u.props.input.disabledColor - }, - // 是否显示清除控件 - clearable: { - type: Boolean, - default: uni.$u.props.input.clearable - }, - // 是否密码类型 - password: { - type: Boolean, - default: uni.$u.props.input.password - }, - // 最大输入长度,设置为 -1 的时候不限制最大长度 - maxlength: { - type: [String, Number], - default: uni.$u.props.input.maxlength - }, - // 输入框为空时的占位符 - placeholder: { - type: String, - default: uni.$u.props.input.placeholder - }, - // 指定placeholder的样式类,注意页面或组件的style中写了scoped时,需要在类名前写/deep/ - placeholderClass: { - type: String, - default: uni.$u.props.input.placeholderClass - }, - // 指定placeholder的样式 - placeholderStyle: { - type: [String, Object], - default: uni.$u.props.input.placeholderStyle - }, - // 是否显示输入字数统计,只在 type ="text"或type ="textarea"时有效 - showWordLimit: { - type: Boolean, - default: uni.$u.props.input.showWordLimit - }, - // 设置右下角按钮的文字,有效值:send|search|next|go|done,兼容性详见uni-app文档 - // https://uniapp.dcloud.io/component/input - // https://uniapp.dcloud.io/component/textarea - confirmType: { - type: String, - default: uni.$u.props.input.confirmType - }, - // 点击键盘右下角按钮时是否保持键盘不收起,H5无效 - confirmHold: { - type: Boolean, - default: uni.$u.props.input.confirmHold - }, - // focus时,点击页面的时候不收起键盘,微信小程序有效 - holdKeyboard: { - type: Boolean, - default: uni.$u.props.input.holdKeyboard - }, - // 自动获取焦点 - // 在 H5 平台能否聚焦以及软键盘是否跟随弹出,取决于当前浏览器本身的实现。nvue 页面不支持,需使用组件的 focus()、blur() 方法控制焦点 - focus: { - type: Boolean, - default: uni.$u.props.input.focus - }, - // 键盘收起时,是否自动失去焦点,目前仅App3.0.0+有效 - autoBlur: { - type: Boolean, - default: uni.$u.props.input.autoBlur - }, - // 是否去掉 iOS 下的默认内边距,仅微信小程序,且type=textarea时有效 - disableDefaultPadding: { - type: Boolean, - default: uni.$u.props.input.disableDefaultPadding - }, - // 指定focus时光标的位置 - cursor: { - type: [String, Number], - default: uni.$u.props.input.cursor - }, - // 输入框聚焦时底部与键盘的距离 - cursorSpacing: { - type: [String, Number], - default: uni.$u.props.input.cursorSpacing - }, - // 光标起始位置,自动聚集时有效,需与selection-end搭配使用 - selectionStart: { - type: [String, Number], - default: uni.$u.props.input.selectionStart - }, - // 光标结束位置,自动聚集时有效,需与selection-start搭配使用 - selectionEnd: { - type: [String, Number], - default: uni.$u.props.input.selectionEnd - }, - // 键盘弹起时,是否自动上推页面 - adjustPosition: { - type: Boolean, - default: uni.$u.props.input.adjustPosition - }, - // 输入框内容对齐方式,可选值为:left|center|right - inputAlign: { - type: String, - default: uni.$u.props.input.inputAlign - }, - // 输入框字体的大小 - fontSize: { - type: [String, Number], - default: uni.$u.props.input.fontSize - }, - // 输入框字体颜色 - color: { - type: String, - default: uni.$u.props.input.color - }, - // 输入框前置图标 - prefixIcon: { - type: String, - default: uni.$u.props.input.prefixIcon - }, - // 前置图标样式,对象或字符串 - prefixIconStyle: { - type: [String, Object], - default: uni.$u.props.input.prefixIconStyle - }, - // 输入框后置图标 - suffixIcon: { - type: String, - default: uni.$u.props.input.suffixIcon - }, - // 后置图标样式,对象或字符串 - suffixIconStyle: { - type: [String, Object], - default: uni.$u.props.input.suffixIconStyle - }, - // 边框类型,surround-四周边框,bottom-底部边框,none-无边框 - border: { - type: String, - default: uni.$u.props.input.border - }, - // 是否只读,与disabled不同之处在于disabled会置灰组件,而readonly则不会 - readonly: { - type: Boolean, - default: uni.$u.props.input.readonly - }, - // 输入框形状,circle-圆形,square-方形 - shape: { - type: String, - default: uni.$u.props.input.shape - }, - // 用于处理或者过滤输入框内容的方法 - formatter: { - type: [Function, null], - default: uni.$u.props.input.formatter - }, - // 是否忽略组件内对文本合成系统事件的处理 - ignoreCompositionEvent: { - type: Boolean, - default: true - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-input/u-input.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-input/u-input.vue deleted file mode 100644 index 30073eb25..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-input/u-input.vue +++ /dev/null @@ -1,354 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-keyboard/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-keyboard/props.js deleted file mode 100644 index cfdb00aca..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-keyboard/props.js +++ /dev/null @@ -1,84 +0,0 @@ -export default { - props: { - // 键盘的类型,number-数字键盘,card-身份证键盘,car-车牌号键盘 - mode: { - type: String, - default: uni.$u.props.keyboard.mode - }, - // 是否显示键盘的"."符号 - dotDisabled: { - type: Boolean, - default: uni.$u.props.keyboard.dotDisabled - }, - // 是否显示顶部工具条 - tooltip: { - type: Boolean, - default: uni.$u.props.keyboard.tooltip - }, - // 是否显示工具条中间的提示 - showTips: { - type: Boolean, - default: uni.$u.props.keyboard.showTips - }, - // 工具条中间的提示文字 - tips: { - type: String, - default: uni.$u.props.keyboard.tips - }, - // 是否显示工具条左边的"取消"按钮 - showCancel: { - type: Boolean, - default: uni.$u.props.keyboard.showCancel - }, - // 是否显示工具条右边的"完成"按钮 - showConfirm: { - type: Boolean, - default: uni.$u.props.keyboard.showConfirm - }, - // 是否打乱键盘按键的顺序 - random: { - type: Boolean, - default: uni.$u.props.keyboard.random - }, - // 是否开启底部安全区适配,开启的话,会在iPhoneX机型底部添加一定的内边距 - safeAreaInsetBottom: { - type: Boolean, - default: uni.$u.props.keyboard.safeAreaInsetBottom - }, - // 是否允许通过点击遮罩关闭键盘 - closeOnClickOverlay: { - type: Boolean, - default: uni.$u.props.keyboard.closeOnClickOverlay - }, - // 控制键盘的弹出与收起 - show: { - type: Boolean, - default: uni.$u.props.keyboard.show - }, - // 是否显示遮罩,某些时候数字键盘时,用户希望看到自己的数值,所以可能不想要遮罩 - overlay: { - type: Boolean, - default: uni.$u.props.keyboard.overlay - }, - // z-index值 - zIndex: { - type: [String, Number], - default: uni.$u.props.keyboard.zIndex - }, - // 取消按钮的文字 - cancelText: { - type: String, - default: uni.$u.props.keyboard.cancelText - }, - // 确认按钮的文字 - confirmText: { - type: String, - default: uni.$u.props.keyboard.confirmText - }, - // 输入一个中文后,是否自动切换到英文 - autoChange: { - type: Boolean, - default: uni.$u.props.keyboard.autoChange - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-keyboard/u-keyboard.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-keyboard/u-keyboard.vue deleted file mode 100644 index 14228cbf5..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-keyboard/u-keyboard.vue +++ /dev/null @@ -1,164 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-line-progress/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-line-progress/props.js deleted file mode 100644 index a4210bdfa..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-line-progress/props.js +++ /dev/null @@ -1,28 +0,0 @@ -export default { - props: { - // 激活部分的颜色 - activeColor: { - type: String, - default: uni.$u.props.lineProgress.activeColor - }, - inactiveColor: { - type: String, - default: uni.$u.props.lineProgress.color - }, - // 进度百分比,数值 - percentage: { - type: [String, Number], - default: uni.$u.props.lineProgress.inactiveColor - }, - // 是否在进度条内部显示百分比的值 - showText: { - type: Boolean, - default: uni.$u.props.lineProgress.showText - }, - // 进度条的高度,单位px - height: { - type: [String, Number], - default: uni.$u.props.lineProgress.height - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-line-progress/u-line-progress.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-line-progress/u-line-progress.vue deleted file mode 100644 index 4e2793101..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-line-progress/u-line-progress.vue +++ /dev/null @@ -1,144 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-line/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-line/props.js deleted file mode 100644 index 2308cc364..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-line/props.js +++ /dev/null @@ -1,33 +0,0 @@ -export default { - props: { - color: { - type: String, - default: uni.$u.props.line.color - }, - // 长度,竖向时表现为高度,横向时表现为长度,可以为百分比,带px单位的值等 - length: { - type: [String, Number], - default: uni.$u.props.line.length - }, - // 线条方向,col-竖向,row-横向 - direction: { - type: String, - default: uni.$u.props.line.direction - }, - // 是否显示细边框 - hairline: { - type: Boolean, - default: uni.$u.props.line.hairline - }, - // 线条与上下左右元素的间距,字符串形式,如"30px"、"20px 30px" - margin: { - type: [String, Number], - default: uni.$u.props.line.margin - }, - // 是否虚线,true-虚线,false-实线 - dashed: { - type: Boolean, - default: uni.$u.props.line.dashed - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-line/u-line.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-line/u-line.vue deleted file mode 100644 index e0a6d9255..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-line/u-line.vue +++ /dev/null @@ -1,62 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-link/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-link/props.js deleted file mode 100644 index d39353f18..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-link/props.js +++ /dev/null @@ -1,39 +0,0 @@ -export default { - props: { - // 文字颜色 - color: { - type: String, - default: uni.$u.props.link.color - }, - // 字体大小,单位px - fontSize: { - type: [String, Number], - default: uni.$u.props.link.fontSize - }, - // 是否显示下划线 - underLine: { - type: Boolean, - default: uni.$u.props.link.underLine - }, - // 要跳转的链接 - href: { - type: String, - default: uni.$u.props.link.href - }, - // 小程序中复制到粘贴板的提示语 - mpTips: { - type: String, - default: uni.$u.props.link.mpTips - }, - // 下划线颜色 - lineColor: { - type: String, - default: uni.$u.props.link.lineColor - }, - // 超链接的问题,不使用slot形式传入,是因为nvue下无法修改颜色 - text: { - type: String, - default: uni.$u.props.link.text - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-link/u-link.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-link/u-link.vue deleted file mode 100644 index c6802a560..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-link/u-link.vue +++ /dev/null @@ -1,83 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-list-item/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-list-item/props.js deleted file mode 100644 index 58ddc493c..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-list-item/props.js +++ /dev/null @@ -1,9 +0,0 @@ -export default { - props: { - // 用于滚动到指定item - anchor: { - type: [String, Number], - default: uni.$u.props.listItem.anchor - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-list-item/u-list-item.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-list-item/u-list-item.vue deleted file mode 100644 index 1a25db65e..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-list-item/u-list-item.vue +++ /dev/null @@ -1,116 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-list/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-list/props.js deleted file mode 100644 index 25406f4e0..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-list/props.js +++ /dev/null @@ -1,76 +0,0 @@ -export default { - props: { - // 控制是否出现滚动条,仅nvue有效 - showScrollbar: { - type: Boolean, - default: uni.$u.props.list.showScrollbar - }, - // 距底部多少时触发scrolltolower事件 - lowerThreshold: { - type: [String, Number], - default: uni.$u.props.list.lowerThreshold - }, - // 距顶部多少时触发scrolltoupper事件,非nvue有效 - upperThreshold: { - type: [String, Number], - default: uni.$u.props.list.upperThreshold - }, - // 设置竖向滚动条位置 - scrollTop: { - type: [String, Number], - default: uni.$u.props.list.scrollTop - }, - // 控制 onscroll 事件触发的频率,仅nvue有效 - offsetAccuracy: { - type: [String, Number], - default: uni.$u.props.list.offsetAccuracy - }, - // 启用 flexbox 布局。开启后,当前节点声明了display: flex就会成为flex container,并作用于其孩子节点,仅微信小程序有效 - enableFlex: { - type: Boolean, - default: uni.$u.props.list.enableFlex - }, - // 是否按分页模式显示List,默认值false - pagingEnabled: { - type: Boolean, - default: uni.$u.props.list.pagingEnabled - }, - // 是否允许List滚动 - scrollable: { - type: Boolean, - default: uni.$u.props.list.scrollable - }, - // 值应为某子元素id(id不能以数字开头) - scrollIntoView: { - type: String, - default: uni.$u.props.list.scrollIntoView - }, - // 在设置滚动条位置时使用动画过渡 - scrollWithAnimation: { - type: Boolean, - default: uni.$u.props.list.scrollWithAnimation - }, - // iOS点击顶部状态栏、安卓双击标题栏时,滚动条返回顶部,只对微信小程序有效 - enableBackToTop: { - type: Boolean, - default: uni.$u.props.list.enableBackToTop - }, - // 列表的高度 - height: { - type: [String, Number], - default: uni.$u.props.list.height - }, - // 列表宽度 - width: { - type: [String, Number], - default: uni.$u.props.list.width - }, - // 列表前后预渲染的屏数,1代表一个屏幕的高度,1.5代表1个半屏幕高度 - preLoadScreen: { - type: [String, Number], - default: uni.$u.props.list.preLoadScreen - } - // vue下,是否开启虚拟列表 - - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-list/u-list.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-list/u-list.vue deleted file mode 100644 index 4447cab65..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-list/u-list.vue +++ /dev/null @@ -1,157 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-loading-icon/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-loading-icon/props.js deleted file mode 100644 index c35524e2a..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-loading-icon/props.js +++ /dev/null @@ -1,59 +0,0 @@ -export default { - props: { - // 是否显示组件 - show: { - type: Boolean, - default: uni.$u.props.loadingIcon.show - }, - // 颜色 - color: { - type: String, - default: uni.$u.props.loadingIcon.color - }, - // 提示文字颜色 - textColor: { - type: String, - default: uni.$u.props.loadingIcon.textColor - }, - // 文字和图标是否垂直排列 - vertical: { - type: Boolean, - default: uni.$u.props.loadingIcon.vertical - }, - // 模式选择,circle-圆形,spinner-花朵形,semicircle-半圆形 - mode: { - type: String, - default: uni.$u.props.loadingIcon.mode - }, - // 图标大小,单位默认px - size: { - type: [String, Number], - default: uni.$u.props.loadingIcon.size - }, - // 文字大小 - textSize: { - type: [String, Number], - default: uni.$u.props.loadingIcon.textSize - }, - // 文字内容 - text: { - type: [String, Number], - default: uni.$u.props.loadingIcon.text - }, - // 动画模式 - timingFunction: { - type: String, - default: uni.$u.props.loadingIcon.timingFunction - }, - // 动画执行周期时间 - duration: { - type: [String, Number], - default: uni.$u.props.loadingIcon.duration - }, - // mode=circle时的暗边颜色 - inactiveColor: { - type: String, - default: uni.$u.props.loadingIcon.inactiveColor - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-loading-icon/u-loading-icon.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-loading-icon/u-loading-icon.vue deleted file mode 100644 index 2ede5c3a3..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-loading-icon/u-loading-icon.vue +++ /dev/null @@ -1,343 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-loading-page/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-loading-page/props.js deleted file mode 100644 index e239b6124..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-loading-page/props.js +++ /dev/null @@ -1,49 +0,0 @@ -export default { - props: { - // 提示内容 - loadingText: { - type: [String, Number], - default: uni.$u.props.loadingPage.loadingText - }, - // 文字上方用于替换loading动画的图片 - image: { - type: String, - default: uni.$u.props.loadingPage.image - }, - // 加载动画的模式,circle-圆形,spinner-花朵形,semicircle-半圆形 - loadingMode: { - type: String, - default: uni.$u.props.loadingPage.loadingMode - }, - // 是否加载中 - loading: { - type: Boolean, - default: uni.$u.props.loadingPage.loading - }, - // 背景色 - bgColor: { - type: String, - default: uni.$u.props.loadingPage.bgColor - }, - // 文字颜色 - color: { - type: String, - default: uni.$u.props.loadingPage.color - }, - // 文字大小 - fontSize: { - type: [String, Number], - default: uni.$u.props.loadingPage.fontSize - }, - // 图标大小 - iconSize: { - type: [String, Number], - default: uni.$u.props.loadingPage.fontSize - }, - // 加载中图标的颜色,只能rgb或者十六进制颜色值 - loadingColor: { - type: String, - default: uni.$u.props.loadingPage.loadingColor - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-loading-page/u-loading-page.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-loading-page/u-loading-page.vue deleted file mode 100644 index 03a78ad8b..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-loading-page/u-loading-page.vue +++ /dev/null @@ -1,115 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-loadmore/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-loadmore/props.js deleted file mode 100644 index 1e67d8919..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-loadmore/props.js +++ /dev/null @@ -1,94 +0,0 @@ -export default { - props: { - // 组件状态,loadmore-加载前的状态,loading-加载中的状态,nomore-没有更多的状态 - status: { - type: String, - default: uni.$u.props.loadmore.status - }, - // 组件背景色 - bgColor: { - type: String, - default: uni.$u.props.loadmore.bgColor - }, - // 是否显示加载中的图标 - icon: { - type: Boolean, - default: uni.$u.props.loadmore.icon - }, - // 字体大小 - fontSize: { - type: [String, Number], - default: uni.$u.props.loadmore.fontSize - }, - // 图标大小 - iconSize: { - type: [String, Number], - default: uni.$u.props.loadmore.iconSize - }, - // 字体颜色 - color: { - type: String, - default: uni.$u.props.loadmore.color - }, - // 加载中状态的图标,spinner-花朵状图标,circle-圆圈状,semicircle-半圆 - loadingIcon: { - type: String, - default: uni.$u.props.loadmore.loadingIcon - }, - // 加载前的提示语 - loadmoreText: { - type: String, - default: uni.$u.props.loadmore.loadmoreText - }, - // 加载中提示语 - loadingText: { - type: String, - default: uni.$u.props.loadmore.loadingText - }, - // 没有更多的提示语 - nomoreText: { - type: String, - default: uni.$u.props.loadmore.nomoreText - }, - // 在“没有更多”状态下,是否显示粗点 - isDot: { - type: Boolean, - default: uni.$u.props.loadmore.isDot - }, - // 加载中图标的颜色 - iconColor: { - type: String, - default: uni.$u.props.loadmore.iconColor - }, - // 上边距 - marginTop: { - type: [String, Number], - default: uni.$u.props.loadmore.marginTop - }, - // 下边距 - marginBottom: { - type: [String, Number], - default: uni.$u.props.loadmore.marginBottom - }, - // 高度,单位px - height: { - type: [String, Number], - default: uni.$u.props.loadmore.height - }, - // 是否显示左边分割线 - line: { - type: Boolean, - default: uni.$u.props.loadmore.line - }, - // 线条颜色 - lineColor: { - type: String, - default: uni.$u.props.loadmore.lineColor - }, - // 是否虚线,true-虚线,false-实线 - dashed: { - type: Boolean, - default: uni.$u.props.loadmore.dashed - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-loadmore/u-loadmore.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-loadmore/u-loadmore.vue deleted file mode 100644 index 73c79feff..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-loadmore/u-loadmore.vue +++ /dev/null @@ -1,150 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-modal/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-modal/props.js deleted file mode 100644 index f76672c81..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-modal/props.js +++ /dev/null @@ -1,84 +0,0 @@ -export default { - props: { - // 是否展示modal - show: { - type: Boolean, - default: uni.$u.props.modal.show - }, - // 标题 - title: { - type: [String], - default: uni.$u.props.modal.title - }, - // 弹窗内容 - content: { - type: String, - default: uni.$u.props.modal.content - }, - // 确认文案 - confirmText: { - type: String, - default: uni.$u.props.modal.confirmText - }, - // 取消文案 - cancelText: { - type: String, - default: uni.$u.props.modal.cancelText - }, - // 是否显示确认按钮 - showConfirmButton: { - type: Boolean, - default: uni.$u.props.modal.showConfirmButton - }, - // 是否显示取消按钮 - showCancelButton: { - type: Boolean, - default: uni.$u.props.modal.showCancelButton - }, - // 确认按钮颜色 - confirmColor: { - type: String, - default: uni.$u.props.modal.confirmColor - }, - // 取消文字颜色 - cancelColor: { - type: String, - default: uni.$u.props.modal.cancelColor - }, - // 对调确认和取消的位置 - buttonReverse: { - type: Boolean, - default: uni.$u.props.modal.buttonReverse - }, - // 是否开启缩放效果 - zoom: { - type: Boolean, - default: uni.$u.props.modal.zoom - }, - // 是否异步关闭,只对确定按钮有效 - asyncClose: { - type: Boolean, - default: uni.$u.props.modal.asyncClose - }, - // 是否允许点击遮罩关闭modal - closeOnClickOverlay: { - type: Boolean, - default: uni.$u.props.modal.closeOnClickOverlay - }, - // 给一个负的margin-top,往上偏移,避免和键盘重合的情况 - negativeTop: { - type: [String, Number], - default: uni.$u.props.modal.negativeTop - }, - // modal宽度,不支持百分比,可以数值,px,rpx单位 - width: { - type: [String, Number], - default: uni.$u.props.modal.width - }, - // 确认按钮的样式,circle-圆形,square-方形,如设置,将不会显示取消按钮 - confirmButtonShape: { - type: String, - default: uni.$u.props.modal.confirmButtonShape - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-modal/u-modal.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-modal/u-modal.vue deleted file mode 100644 index 4c37ae2ed..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-modal/u-modal.vue +++ /dev/null @@ -1,227 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-navbar/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-navbar/props.js deleted file mode 100644 index 5398de287..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-navbar/props.js +++ /dev/null @@ -1,84 +0,0 @@ -export default { - props: { - // 是否开启顶部安全区适配 - safeAreaInsetTop: { - type: Boolean, - default: uni.$u.props.navbar.safeAreaInsetTop - }, - // 固定在顶部时,是否生成一个等高元素,以防止塌陷 - placeholder: { - type: Boolean, - default: uni.$u.props.navbar.placeholder - }, - // 是否固定在顶部 - fixed: { - type: Boolean, - default: uni.$u.props.navbar.fixed - }, - // 是否显示下边框 - border: { - type: Boolean, - default: uni.$u.props.navbar.border - }, - // 左边的图标 - leftIcon: { - type: String, - default: uni.$u.props.navbar.leftIcon - }, - // 左边的提示文字 - leftText: { - type: String, - default: uni.$u.props.navbar.leftText - }, - // 左右的提示文字 - rightText: { - type: String, - default: uni.$u.props.navbar.rightText - }, - // 右边的图标 - rightIcon: { - type: String, - default: uni.$u.props.navbar.rightIcon - }, - // 标题 - title: { - type: [String, Number], - default: uni.$u.props.navbar.title - }, - // 背景颜色 - bgColor: { - type: String, - default: uni.$u.props.navbar.bgColor - }, - // 标题的宽度 - titleWidth: { - type: [String, Number], - default: uni.$u.props.navbar.titleWidth - }, - // 导航栏高度 - height: { - type: [String, Number], - default: uni.$u.props.navbar.height - }, - // 左侧返回图标的大小 - leftIconSize: { - type: [String, Number], - default: uni.$u.props.navbar.leftIconSize - }, - // 左侧返回图标的颜色 - leftIconColor: { - type: String, - default: uni.$u.props.navbar.leftIconColor - }, - // 点击左侧区域(返回图标),是否自动返回上一页 - autoBack: { - type: Boolean, - default: uni.$u.props.navbar.autoBack - }, - // 标题的样式,对象或字符串 - titleStyle: { - type: [String, Object], - default: uni.$u.props.navbar.titleStyle - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-navbar/u-navbar.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-navbar/u-navbar.vue deleted file mode 100644 index 2b206b7db..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-navbar/u-navbar.vue +++ /dev/null @@ -1,186 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-no-network/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-no-network/props.js deleted file mode 100644 index 9f3af62ca..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-no-network/props.js +++ /dev/null @@ -1,19 +0,0 @@ -export default { - props: { - // 页面文字提示 - tips: { - type: String, - default: uni.$u.props.noNetwork.tips - }, - // 一个z-index值,用于设置没有网络这个组件的层次,因为页面可能会有其他定位的元素层级过高,导致此组件被覆盖 - zIndex: { - type: [String, Number], - default: uni.$u.props.noNetwork.zIndex - }, - // image 没有网络的图片提示 - image: { - type: String, - default: uni.$u.props.noNetwork.image - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-no-network/u-no-network.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-no-network/u-no-network.vue deleted file mode 100644 index 9710729eb..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-no-network/u-no-network.vue +++ /dev/null @@ -1,220 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-notice-bar/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-notice-bar/props.js deleted file mode 100644 index 7040c29a5..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-notice-bar/props.js +++ /dev/null @@ -1,70 +0,0 @@ -export default { - props: { - // 显示的内容,数组 - text: { - type: [Array, String], - default: uni.$u.props.noticeBar.text - }, - // 通告滚动模式,row-横向滚动,column-竖向滚动 - direction: { - type: String, - default: uni.$u.props.noticeBar.direction - }, - // direction = row时,是否使用步进形式滚动 - step: { - type: Boolean, - default: uni.$u.props.noticeBar.step - }, - // 是否显示左侧的音量图标 - icon: { - type: String, - default: uni.$u.props.noticeBar.icon - }, - // 通告模式,link-显示右箭头,closable-显示右侧关闭图标 - mode: { - type: String, - default: uni.$u.props.noticeBar.mode - }, - // 文字颜色,各图标也会使用文字颜色 - color: { - type: String, - default: uni.$u.props.noticeBar.color - }, - // 背景颜色 - bgColor: { - type: String, - default: uni.$u.props.noticeBar.bgColor - }, - // 水平滚动时的滚动速度,即每秒滚动多少px(px),这有利于控制文字无论多少时,都能有一个恒定的速度 - speed: { - type: [String, Number], - default: uni.$u.props.noticeBar.speed - }, - // 字体大小 - fontSize: { - type: [String, Number], - default: uni.$u.props.noticeBar.fontSize - }, - // 滚动一个周期的时间长,单位ms - duration: { - type: [String, Number], - default: uni.$u.props.noticeBar.duration - }, - // 是否禁止用手滑动切换 - // 目前HX2.6.11,只支持App 2.5.5+、H5 2.5.5+、支付宝小程序、字节跳动小程序 - disableTouch: { - type: Boolean, - default: uni.$u.props.noticeBar.disableTouch - }, - // 跳转的页面路径 - url: { - type: String, - default: uni.$u.props.noticeBar.url - }, - // 页面跳转的类型 - linkType: { - type: String, - default: uni.$u.props.noticeBar.linkType - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-notice-bar/u-notice-bar.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-notice-bar/u-notice-bar.vue deleted file mode 100644 index a06eb39ad..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-notice-bar/u-notice-bar.vue +++ /dev/null @@ -1,101 +0,0 @@ - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-notify/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-notify/props.js deleted file mode 100644 index 57a9d71e9..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-notify/props.js +++ /dev/null @@ -1,49 +0,0 @@ -export default { - props: { - // 到顶部的距离 - top: { - type: [String, Number], - default: uni.$u.props.notify.top - }, - // 是否展示组件 - // show: { - // type: Boolean, - // default: uni.$u.props.notify.show - // }, - // type主题,primary,success,warning,error - type: { - type: String, - default: uni.$u.props.notify.type - }, - // 字体颜色 - color: { - type: String, - default: uni.$u.props.notify.color - }, - // 背景颜色 - bgColor: { - type: String, - default: uni.$u.props.notify.bgColor - }, - // 展示的文字内容 - message: { - type: String, - default: uni.$u.props.notify.message - }, - // 展示时长,为0时不消失,单位ms - duration: { - type: [String, Number], - default: uni.$u.props.notify.duration - }, - // 字体大小 - fontSize: { - type: [String, Number], - default: uni.$u.props.notify.fontSize - }, - // 是否留出顶部安全距离(状态栏高度) - safeAreaInsetTop: { - type: Boolean, - default: uni.$u.props.notify.safeAreaInsetTop - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-notify/u-notify.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-notify/u-notify.vue deleted file mode 100644 index 30adb72fa..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-notify/u-notify.vue +++ /dev/null @@ -1,211 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-number-box/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-number-box/props.js deleted file mode 100644 index fb0fa947f..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-number-box/props.js +++ /dev/null @@ -1,109 +0,0 @@ -export default { - props: { - // 步进器标识符,在change回调返回 - name: { - type: [String, Number], - default: uni.$u.props.numberBox.name - }, - // 用于双向绑定的值,初始化时设置设为默认min值(最小值) - value: { - type: [String, Number], - default: uni.$u.props.numberBox.value - }, - // 最小值 - min: { - type: [String, Number], - default: uni.$u.props.numberBox.min - }, - // 最大值 - max: { - type: [String, Number], - default: uni.$u.props.numberBox.max - }, - // 加减的步长,可为小数 - step: { - type: [String, Number], - default: uni.$u.props.numberBox.step - }, - // 是否只允许输入整数 - integer: { - type: Boolean, - default: uni.$u.props.numberBox.integer - }, - // 是否禁用,包括输入框,加减按钮 - disabled: { - type: Boolean, - default: uni.$u.props.numberBox.disabled - }, - // 是否禁用输入框 - disabledInput: { - type: Boolean, - default: uni.$u.props.numberBox.disabledInput - }, - // 是否开启异步变更,开启后需要手动控制输入值 - asyncChange: { - type: Boolean, - default: uni.$u.props.numberBox.asyncChange - }, - // 输入框宽度,单位为px - inputWidth: { - type: [String, Number], - default: uni.$u.props.numberBox.inputWidth - }, - // 是否显示减少按钮 - showMinus: { - type: Boolean, - default: uni.$u.props.numberBox.showMinus - }, - // 是否显示增加按钮 - showPlus: { - type: Boolean, - default: uni.$u.props.numberBox.showPlus - }, - // 显示的小数位数 - decimalLength: { - type: [String, Number, null], - default: uni.$u.props.numberBox.decimalLength - }, - // 是否开启长按加减手势 - longPress: { - type: Boolean, - default: uni.$u.props.numberBox.longPress - }, - // 输入框文字和加减按钮图标的颜色 - color: { - type: String, - default: uni.$u.props.numberBox.color - }, - // 按钮大小,宽高等于此值,单位px,输入框高度和此值保持一致 - buttonSize: { - type: [String, Number], - default: uni.$u.props.numberBox.buttonSize - }, - // 输入框和按钮的背景颜色 - bgColor: { - type: String, - default: uni.$u.props.numberBox.bgColor - }, - // 指定光标于键盘的距离,避免键盘遮挡输入框,单位px - cursorSpacing: { - type: [String, Number], - default: uni.$u.props.numberBox.cursorSpacing - }, - // 是否禁用增加按钮 - disablePlus: { - type: Boolean, - default: uni.$u.props.numberBox.disablePlus - }, - // 是否禁用减少按钮 - disableMinus: { - type: Boolean, - default: uni.$u.props.numberBox.disableMinus - }, - // 加减按钮图标的样式 - iconStyle: { - type: [Object, String], - default: uni.$u.props.numberBox.iconStyle - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-number-box/u-number-box.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-number-box/u-number-box.vue deleted file mode 100644 index 69211c540..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-number-box/u-number-box.vue +++ /dev/null @@ -1,416 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-number-keyboard/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-number-keyboard/props.js deleted file mode 100644 index 5e3bf556b..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-number-keyboard/props.js +++ /dev/null @@ -1,19 +0,0 @@ -export default { - props: { - // 键盘的类型,number-数字键盘,card-身份证键盘 - mode: { - type: String, - default: uni.$u.props.numberKeyboard.value - }, - // 是否显示键盘的"."符号 - dotDisabled: { - type: Boolean, - default: uni.$u.props.numberKeyboard.dotDisabled - }, - // 是否打乱键盘按键的顺序 - random: { - type: Boolean, - default: uni.$u.props.numberKeyboard.random - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-number-keyboard/u-number-keyboard.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-number-keyboard/u-number-keyboard.vue deleted file mode 100644 index 4f505c6e4..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-number-keyboard/u-number-keyboard.vue +++ /dev/null @@ -1,196 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-overlay/props.js b/yudao-ui-app/uni_modules/uview-ui/components/u-overlay/props.js deleted file mode 100644 index e6974df9b..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-overlay/props.js +++ /dev/null @@ -1,24 +0,0 @@ -export default { - props: { - // 是否显示遮罩 - show: { - type: Boolean, - default: uni.$u.props.overlay.show - }, - // 层级z-index - zIndex: { - type: [String, Number], - default: uni.$u.props.overlay.zIndex - }, - // 遮罩的过渡时间,单位为ms - duration: { - type: [String, Number], - default: uni.$u.props.overlay.duration - }, - // 不透明度值,当做rgba的第四个参数 - opacity: { - type: [String, Number], - default: uni.$u.props.overlay.opacity - } - } -} diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-overlay/u-overlay.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-overlay/u-overlay.vue deleted file mode 100644 index 92de4e9fd..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-overlay/u-overlay.vue +++ /dev/null @@ -1,68 +0,0 @@ - - - - - diff --git a/yudao-ui-app/uni_modules/uview-ui/components/u-parse/node/node.vue b/yudao-ui-app/uni_modules/uview-ui/components/u-parse/node/node.vue deleted file mode 100644 index 73e30fd61..000000000 --- a/yudao-ui-app/uni_modules/uview-ui/components/u-parse/node/node.vue +++ /dev/null @@ -1,499 +0,0 @@ -