From 1b8294ae65126f94ecdf0090ca6d241bcc8de6c1 Mon Sep 17 00:00:00 2001 From: cst61 Date: Tue, 8 Sep 2026 01:15:22 +0800 Subject: [PATCH] =?UTF-8?q?=E6=89=B9=E9=87=8F=E6=8C=89=E9=83=A8=E9=97=A8?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BB=A3=E7=90=86=E5=95=86=E7=9A=84=E5=AF=84?= =?UTF-8?q?=E5=8D=96=E7=8A=B6=E6=80=81=EF=BC=8C=E7=94=A8=E6=88=B7=E7=8A=B6?= =?UTF-8?q?=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/rj/config/MybatisPlusConfig.java | 1 + .../controller/LbPurchaseApplyController.java | 93 +++++++ .../rj/controller/MemberInfoController.java | 99 +++++++ src/main/java/com/rj/entity/MemberInfo.java | 182 +++++++++++++ .../java/com/rj/mapper/MemberInfoMapper.java | 9 + .../com/rj/service/HxrAdminUserService.java | 51 +++- .../rj/service/ILbPurchaseApplyService.java | 19 ++ .../impl/LbPurchaseApplyServiceImpl.java | 207 +++++++++++++++ .../service/impl/MemberInfoServiceImpl.java | 246 ++++++++++++++++++ 9 files changed, 905 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/rj/controller/MemberInfoController.java create mode 100644 src/main/java/com/rj/entity/MemberInfo.java create mode 100644 src/main/java/com/rj/mapper/MemberInfoMapper.java create mode 100644 src/main/java/com/rj/service/impl/MemberInfoServiceImpl.java diff --git a/src/main/java/com/rj/config/MybatisPlusConfig.java b/src/main/java/com/rj/config/MybatisPlusConfig.java index c13594a..b5a9c02 100644 --- a/src/main/java/com/rj/config/MybatisPlusConfig.java +++ b/src/main/java/com/rj/config/MybatisPlusConfig.java @@ -64,6 +64,7 @@ public class MybatisPlusConfig { ignoreTables.add("lb_buy_account"); // 抢单账号跨租户管理;分页/批量抢单按记录 tenant_id 业务处理 ignoreTables.add("lb_buy_account_history"); // 抢单历史跨租户查询;按记录 tenant_id 业务过滤 ignoreTables.add("lb_goods"); // 货品跨租户管理;分页/抢单按页面或业务传入的 tenant_id 显式过滤 + ignoreTables.add("member_info"); // 第三方库镜像会员表(business_shop.member_info),表无 tenant_id 字段 return new TenantLineHandler() { diff --git a/src/main/java/com/rj/controller/LbPurchaseApplyController.java b/src/main/java/com/rj/controller/LbPurchaseApplyController.java index 4a64983..078caf0 100644 --- a/src/main/java/com/rj/controller/LbPurchaseApplyController.java +++ b/src/main/java/com/rj/controller/LbPurchaseApplyController.java @@ -53,6 +53,58 @@ public class LbPurchaseApplyController { private Integer maxOrder; } + @Data + @Schema(description = "按用户ID批量修改「是否可以寄卖 / 用户状态」请求体") + public static class UpdateHxrAdminUserResellStatusRequest { + @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "租户id不能为空") + private String tenantId; + + @Schema(description = "hxrd 后台用户 ID 列表", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "用户id列表不能为空") + private List userIds; + + @Schema(description = "isResell 是否生效:true 修改「是否可以寄卖」,false 不修改该字段", + requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "isResellEnabled不能为空") + private Boolean isResellEnabled; + + @Schema(description = "是否可以寄卖 is_resell 的值:1 可以寄卖,0 不可以寄卖;isResellEnabled 为 true 时必填") + private Integer isResell; + + @Schema(description = "status 是否生效:true 修改「用户状态」,false 不修改该字段", + requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "statusEnabled不能为空") + private Boolean statusEnabled; + + @Schema(description = "用户状态 status 的值:1 正常,0 停用;statusEnabled 为 true 时必填") + private Integer status; + } + + @Data + @Schema(description = "按 member_info 全部用户批量修改「是否可以寄卖 / 用户状态」请求体") + public static class UpdateHxrAdminUserResellStatusForAllMembersRequest { + @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "租户id不能为空") + private String tenantId; + + @Schema(description = "isResell 是否生效:true 修改「是否可以寄卖」,false 不修改该字段", + requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "isResellEnabled不能为空") + private Boolean isResellEnabled; + + @Schema(description = "是否可以寄卖 is_resell 的值:1 可以寄卖,0 不可以寄卖;isResellEnabled 为 true 时必填") + private Integer isResell; + + @Schema(description = "status 是否生效:true 修改「用户状态」,false 不修改该字段", + requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "statusEnabled不能为空") + private Boolean statusEnabled; + + @Schema(description = "用户状态 status 的值:1 正常,0 停用;statusEnabled 为 true 时必填") + private Integer status; + } + @Data @Schema(description = "大模型解析订货信息请求体") public static class ParseOrderInfoRequest { @@ -176,6 +228,47 @@ public class LbPurchaseApplyController { return ResponseEntity.badRequest().body(result); } + @PostMapping("/updateHxrAdminUserResellStatusByUserIds") + @Operation(summary = "按用户ID列表批量修改是否可寄卖与用户状态", + description = "根据入参 userIds 逐条调用 POST /app/admin/user/update," + + "仅修改生效标记为 true 的字段(isResellEnabled→is_resell,statusEnabled→status)," + + "未生效的字段不向第三方提交、保持原值;" + + "cookie、URL、Referer 等从 lb_third_integration_config 按 tenantId 读取") + public ResponseEntity> updateHxrAdminUserResellStatusByUserIds( + @Parameter(description = "租户、用户列表及寄卖/状态参数", required = true) + @Valid @RequestBody UpdateHxrAdminUserResellStatusRequest body) { + Map result = lbPurchaseApplyService.updateHxrAdminUserResellStatusByUserIds( + body.getTenantId(), body.getUserIds(), + body.getIsResellEnabled(), body.getIsResell(), + body.getStatusEnabled(), body.getStatus()); + Boolean success = (Boolean) result.get("success"); + if (success != null && success) { + return ResponseEntity.ok(result); + } + return ResponseEntity.badRequest().body(result); + } + + @PostMapping("/updateHxrAdminUserResellStatusForAllMembers") + @Operation(summary = "按 member_info 全部用户批量修改是否可寄卖与用户状态", + description = "用户 id 列表从 member_info 表读取全部用户(不接收 id 列表)," + + "逐条调用 POST /app/admin/user/update(v1 后台接口)," + + "仅修改生效标记为 true 的字段(isResellEnabled→is_resell,statusEnabled→status)," + + "未生效的字段不向第三方提交、保持原值;" + + "cookie、URL、Referer 等从 lb_third_integration_config 按 tenantId 读取") + public ResponseEntity> updateHxrAdminUserResellStatusForAllMembers( + @Parameter(description = "租户及寄卖/状态参数", required = true) + @Valid @RequestBody UpdateHxrAdminUserResellStatusForAllMembersRequest body) { + Map result = lbPurchaseApplyService.updateHxrAdminUserResellStatusForAllMembers( + body.getTenantId(), + body.getIsResellEnabled(), body.getIsResell(), + body.getStatusEnabled(), body.getStatus()); + Boolean success = (Boolean) result.get("success"); + if (success != null && success) { + return ResponseEntity.ok(result); + } + return ResponseEntity.badRequest().body(result); + } + @GetMapping("/syncHxrAdminColleagueVip") @Operation(summary = "按申请日期与租户同步同事 hxrd 用户 VIP", description = "根据 lb_purchase_apply 的申请日期区间与 tenant_id 逐条处理," diff --git a/src/main/java/com/rj/controller/MemberInfoController.java b/src/main/java/com/rj/controller/MemberInfoController.java new file mode 100644 index 0000000..a8211e2 --- /dev/null +++ b/src/main/java/com/rj/controller/MemberInfoController.java @@ -0,0 +1,99 @@ +package com.rj.controller; + +import com.rj.entity.MemberInfo; +import com.rj.service.IMemberInfoService; +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.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +@RestController +@RequestMapping("/api/memberInfo") +@Tag(name = "会员信息", description = "member_info 增删改查与分页") +public class MemberInfoController { + + @Autowired + private IMemberInfoService memberInfoService; + + @PostMapping("/add") + @Operation(summary = "新增") + public ResponseEntity> add( + @Parameter(description = "会员实体", required = true) @RequestBody MemberInfo entity) { + Map result = memberInfoService.add(entity); + Boolean success = (Boolean) result.get("success"); + if (success != null && success) { + return ResponseEntity.ok(result); + } + return ResponseEntity.badRequest().body(result); + } + + @PutMapping("/update") + @Operation(summary = "编辑") + public ResponseEntity> update( + @Parameter(description = "会员实体(须含 id)", required = true) @RequestBody MemberInfo entity) { + Map result = memberInfoService.update(entity); + Boolean success = (Boolean) result.get("success"); + if (success != null && success) { + return ResponseEntity.ok(result); + } + return ResponseEntity.badRequest().body(result); + } + + @DeleteMapping("/delete/{id}") + @Operation(summary = "删除") + public ResponseEntity> delete( + @Parameter(description = "主键ID", required = true) @PathVariable String id) { + Map result = memberInfoService.deleteById(id); + Boolean success = (Boolean) result.get("success"); + if (success != null && success) { + return ResponseEntity.ok(result); + } + return ResponseEntity.badRequest().body(result); + } + + @GetMapping("/list") + @Operation(summary = "分页查询") + public ResponseEntity> list( + @RequestParam(defaultValue = "1") Integer current, + @RequestParam(defaultValue = "10") Integer size, + @Parameter(description = "手机号") @RequestParam(required = false) String phone, + @Parameter(description = "昵称") @RequestParam(required = false) String nickname, + @Parameter(description = "邀请码") @RequestParam(required = false) String inviteCode, + @Parameter(description = "上级ID") @RequestParam(required = false) String parentId, + @Parameter(description = "用户等级") @RequestParam(required = false) String userLevel, + @Parameter(description = "状态") @RequestParam(required = false) Integer status, + @Parameter(description = "审核状态") @RequestParam(required = false) Integer auditStatus, + @Parameter(description = "是否可以寄卖(0-禁用,1-启用)") @RequestParam(required = false) Integer canConsign) { + Map result = memberInfoService.pageQuery( + current, size, phone, nickname, inviteCode, parentId, userLevel, status, auditStatus, canConsign); + Boolean success = (Boolean) result.get("success"); + if (success != null && success) { + return ResponseEntity.ok(result); + } + return ResponseEntity.internalServerError().body(result); + } + + @GetMapping("/listAll") + @Operation(summary = "查询全部数据") + public ResponseEntity> listAll( + @Parameter(description = "手机号") @RequestParam(required = false) String phone, + @Parameter(description = "昵称") @RequestParam(required = false) String nickname, + @Parameter(description = "邀请码") @RequestParam(required = false) String inviteCode, + @Parameter(description = "上级ID") @RequestParam(required = false) String parentId, + @Parameter(description = "用户等级") @RequestParam(required = false) String userLevel, + @Parameter(description = "状态") @RequestParam(required = false) Integer status, + @Parameter(description = "审核状态") @RequestParam(required = false) Integer auditStatus, + @Parameter(description = "是否可以寄卖(0-禁用,1-启用)") @RequestParam(required = false) Integer canConsign) { + Map result = memberInfoService.listAll( + phone, nickname, inviteCode, parentId, userLevel, status, auditStatus, canConsign); + Boolean success = (Boolean) result.get("success"); + if (success != null && success) { + return ResponseEntity.ok(result); + } + return ResponseEntity.internalServerError().body(result); + } +} diff --git a/src/main/java/com/rj/entity/MemberInfo.java b/src/main/java/com/rj/entity/MemberInfo.java new file mode 100644 index 0000000..a1698ba --- /dev/null +++ b/src/main/java/com/rj/entity/MemberInfo.java @@ -0,0 +1,182 @@ +package com.rj.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("member_info") +@Schema(description = "会员表") +public class MemberInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.ASSIGN_UUID) + @Schema(description = "主键ID") + private String id; + + @TableField("phone") + @Schema(description = "手机号/账号") + private String phone; + + @TableField("nickname") + @Schema(description = "昵称") + private String nickname; + + @TableField("avatar") + @Schema(description = "头像") + private String avatar; + + @TableField("password") + @Schema(description = "密码") + private String password; + + @TableField("invite_code") + @Schema(description = "邀请码") + private String inviteCode; + + @TableField("parent_id") + @Schema(description = "上级ID") + private String parentId; + + @TableField("user_level") + @Schema(description = "用户等级(normal-普通用户,referral-推荐人,shopkeeper-店长,second_shopkeeper-二代店长)") + private String userLevel; + + @TableField("available_order_count") + @Schema(description = "当天可抢订单数量") + private Integer availableOrderCount; + + @TableField("vip_end_time") + @Schema(description = "新人体验VIP截止时间") + private LocalDateTime vipEndTime; + + @TableField("is_priority_buy") + @Schema(description = "是否优先抢购(0-禁用,1-启用)") + private Integer isPriorityBuy; + + @TableField("can_consign") + @Schema(description = "是否可以寄卖(0-禁用,1-启用)") + private Integer canConsign; + + @TableField("status") + @Schema(description = "状态(0-禁用,1-正常)") + private Integer status; + + @TableField("balance") + @Schema(description = "余额") + private BigDecimal balance; + + @TableField("coupon_balance") + @Schema(description = "优惠券") + private BigDecimal couponBalance; + + @TableField("personal_bonus") + @Schema(description = "个人奖金") + private BigDecimal personalBonus; + + @TableField("promotion_bonus") + @Schema(description = "推广奖金") + private BigDecimal promotionBonus; + + @TableField("contract_status") + @Schema(description = "合同状态") + private String contractStatus; + + @TableField("today_buy_amount") + @Schema(description = "今日购买总金额") + private BigDecimal todayBuyAmount; + + @TableField("today_sell_amount") + @Schema(description = "今日卖出总金额") + private BigDecimal todaySellAmount; + + @TableField("yesterday_new_count") + @Schema(description = "昨日卖出数量") + private Integer yesterdayNewCount; + + @TableField("today_buy_count") + @Schema(description = "今日购买数量") + private Integer todayBuyCount; + + @TableField("available_goods_count") + @Schema(description = "商品可抢单数") + private Integer availableGoodsCount; + + @TableField("bank_card_number") + @Schema(description = "银行卡号") + private String bankCardNumber; + + @TableField("bank_name") + @Schema(description = "开户行") + private String bankName; + + @TableField("bank_card_name") + @Schema(description = "银行卡姓名") + private String bankCardName; + + @TableField("bank_phone") + @Schema(description = "银行卡手机号") + private String bankPhone; + + @TableField("alipay_account") + @Schema(description = "支付宝账号") + private String alipayAccount; + + @TableField("alipay_name") + @Schema(description = "支付宝姓名") + private String alipayName; + + @TableField("alipay_qr_code") + @Schema(description = "支付宝二维码") + private String alipayQrCode; + + @TableField("alipay_phone") + @Schema(description = "支付宝手机号") + private String alipayPhone; + + @TableField("create_by") + @Schema(description = "创建人") + private String createBy; + + @TableField("update_by") + @Schema(description = "更新人") + private String updateBy; + + @TableField("create_time") + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @TableField("update_time") + @Schema(description = "更新时间") + private LocalDateTime updateTime; + + @TableField("audit_status") + @Schema(description = "审核状态(0-未审核,1-已审核)") + private Integer auditStatus; + + @TableField("last_time") + @Schema(description = "最后登录时间") + private LocalDateTime lastTime; + + @TableField("last_ip") + @Schema(description = "最后登录IP") + private String lastIp; + + @TableField("join_time") + @Schema(description = "注册时间") + private LocalDateTime joinTime; + + @TableField("join_ip") + @Schema(description = "注册IP") + private String joinIp; +} diff --git a/src/main/java/com/rj/mapper/MemberInfoMapper.java b/src/main/java/com/rj/mapper/MemberInfoMapper.java new file mode 100644 index 0000000..053c4d2 --- /dev/null +++ b/src/main/java/com/rj/mapper/MemberInfoMapper.java @@ -0,0 +1,9 @@ +package com.rj.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.rj.entity.MemberInfo; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface MemberInfoMapper extends BaseMapper { +} diff --git a/src/main/java/com/rj/service/HxrAdminUserService.java b/src/main/java/com/rj/service/HxrAdminUserService.java index 2dcea4a..0ff1c7c 100644 --- a/src/main/java/com/rj/service/HxrAdminUserService.java +++ b/src/main/java/com/rj/service/HxrAdminUserService.java @@ -1056,6 +1056,42 @@ public class HxrAdminUserService { public boolean updateUserVipFields( long userId, Integer maxOrder, String viptimeFormatted, int isVip, HxrAdminUserApiContext ctx) throws Exception { + String form = buildUpdateFormBody(userId, maxOrder, viptimeFormatted, isVip); + return postUserUpdateForm(form, ctx, String.valueOf(userId)); + } + + /** + * 更新用户「是否可以寄卖 is_resell / 用户状态 status」字段({@code application/x-www-form-urlencoded})。 + * 仅当对应参数非 {@code null} 时才向第三方提交该字段,为 {@code null} 时不传、第三方保持原值。 + * + * @param isResell 是否可以寄卖:1 可以,0 不可以;null 不修改该字段 + * @param status 用户状态:1 正常,0 停用;null 不修改该字段 + * @return 接口 {@code code==0} 时为 true + */ + public boolean updateUserResellStatusFields(long userId, Integer isResell, Integer status, HxrAdminUserApiContext ctx) + throws Exception { + return updateUserResellStatusFields(String.valueOf(userId), isResell, status, ctx); + } + + /** + * 更新用户「是否可以寄卖 is_resell / 用户状态 status」字段(重载:用户 id 为字符串,如 member_info.id,原样透传给第三方)。 + * 仅当对应参数非 {@code null} 时才向第三方提交该字段,为 {@code null} 时不传、第三方保持原值。 + * + * @param isResell 是否可以寄卖:1 可以,0 不可以;null 不修改该字段 + * @param status 用户状态:1 正常,0 停用;null 不修改该字段 + * @return 接口 {@code code==0} 时为 true + */ + public boolean updateUserResellStatusFields(String userId, Integer isResell, Integer status, HxrAdminUserApiContext ctx) + throws Exception { + String form = buildResellStatusFormBody(userId, isResell, status); + return postUserUpdateForm(form, ctx, userId); + } + + /** + * 校验上下文并以 {@code application/x-www-form-urlencoded} 表单 POST 到 user/update, + * 接口 {@code code==0} 时返回 true。 + */ + private boolean postUserUpdateForm(String form, HxrAdminUserApiContext ctx, String userId) throws Exception { if (ctx == null) { log.warn("用户 API 配置为空,跳过 user/update"); return false; @@ -1076,8 +1112,6 @@ public class HxrAdminUserService { return false; } - String form = buildUpdateFormBody(userId, maxOrder, viptimeFormatted, isVip); - HttpClient client = HttpClient.newBuilder() .connectTimeout(java.time.Duration.ofSeconds(35)) .followRedirects(HttpClient.Redirect.NORMAL) @@ -1135,6 +1169,19 @@ public class HxrAdminUserService { return form.toString(); } + /** 仅提交「是否可以寄卖 is_resell / 用户状态 status」中非 null 的字段(id 必传;id 为字符串原样透传)。 */ + private static String buildResellStatusFormBody(String userId, Integer isResell, Integer status) { + StringBuilder form = new StringBuilder(); + form.append("id=").append(userId); + if (isResell != null) { + form.append("&is_resell=").append(isResell == 1 ? 1 : 0); + } + if (status != null) { + form.append("&status=").append(status == 1 ? 1 : 0); + } + return form.toString(); + } + /** * v2 模拟登录:POST JSON {phone,password} → /trade-app/api/app/login。 * 成功返回格式:{ success:true, token:"Bearer eyJ..." };去掉 "Bearer " 前缀后返回。 diff --git a/src/main/java/com/rj/service/ILbPurchaseApplyService.java b/src/main/java/com/rj/service/ILbPurchaseApplyService.java index 4766eb3..69886fe 100644 --- a/src/main/java/com/rj/service/ILbPurchaseApplyService.java +++ b/src/main/java/com/rj/service/ILbPurchaseApplyService.java @@ -41,6 +41,25 @@ public interface ILbPurchaseApplyService extends IService { Map updateHxrAdminUserVipByUserIds( String tenantId, List userIds, Integer isVip, String vipTime, Integer maxOrder); + /** + * 按用户 ID 列表批量调用 hxrd 用户更新接口,修改「是否可以寄卖 is_resell」与「用户状态 status」; + * 仅修改生效标记为 {@code true} 的字段,未生效的字段不向第三方提交、保持原值。 + */ + Map updateHxrAdminUserResellStatusByUserIds( + String tenantId, List userIds, + Boolean isResellEnabled, Integer isResell, + Boolean statusEnabled, Integer status); + + /** + * 从 {@code member_info} 表读取全部用户 id(不接收 id 列表),批量调用 hxrd 用户更新接口(v1 后台接口) + * 修改「是否可以寄卖 is_resell」与「用户状态 status」; + * 仅修改生效标记为 {@code true} 的字段,未生效的字段不向第三方提交、保持原值。 + */ + Map updateHxrAdminUserResellStatusForAllMembers( + String tenantId, + Boolean isResellEnabled, Integer isResell, + Boolean statusEnabled, Integer status); + /** * 按申请日期区间与租户筛选进货申请,对每条记录的 {@code colleague_phone} 调用 hxrd 用户查询与更新, * 仅当 {@code colleague_name} 能在 {@code lb_daily_user_trade}(同租户、按 nickname)中查到时才开通; diff --git a/src/main/java/com/rj/service/impl/LbPurchaseApplyServiceImpl.java b/src/main/java/com/rj/service/impl/LbPurchaseApplyServiceImpl.java index fbe7c64..dc64e3d 100644 --- a/src/main/java/com/rj/service/impl/LbPurchaseApplyServiceImpl.java +++ b/src/main/java/com/rj/service/impl/LbPurchaseApplyServiceImpl.java @@ -17,11 +17,13 @@ import com.rj.entity.LbDailyUserTradeReport; import com.rj.entity.LbOrderRow; import com.rj.entity.LbPurchaseApply; import com.rj.entity.LbUser; +import com.rj.entity.MemberInfo; import com.rj.util.IsoWorkdayUtils; import com.rj.mapper.LbDailyUserTradeReportMapper; import com.rj.mapper.LbOrderRowMapper; import com.rj.mapper.LbPurchaseApplyMapper; import com.rj.mapper.LbUserMapper; +import com.rj.mapper.MemberInfoMapper; import com.rj.service.HxrAdminUserService; import com.rj.service.ILbPurchaseApplyService; import com.rj.service.ILbThirdIntegrationConfigService; @@ -74,6 +76,9 @@ public class LbPurchaseApplyServiceImpl @Autowired private LbUserMapper lbUserMapper; + @Autowired + private MemberInfoMapper memberInfoMapper; + @Autowired private LbOrderRowMapper lbOrderRowMapper; @@ -978,6 +983,208 @@ public class LbPurchaseApplyServiceImpl } } + @Override + public Map updateHxrAdminUserResellStatusByUserIds( + String tenantId, List userIds, + Boolean isResellEnabled, Integer isResell, + Boolean statusEnabled, Integer status) { + Map result = new HashMap<>(); + try { + if (tenantId == null || tenantId.trim().isEmpty()) { + result.put("success", false); + result.put("message", "租户id不能为空"); + return result; + } + if (userIds == null || userIds.isEmpty()) { + result.put("success", false); + result.put("message", "用户id列表不能为空"); + return result; + } + String validationError = validateResellStatusParams(isResellEnabled, isResell, statusEnabled, status); + if (validationError != null) { + result.put("success", false); + result.put("message", validationError); + return result; + } + + String tid = tenantId.trim(); + Optional apiContextOpt = + lbThirdIntegrationConfigService.resolveAdminUserApiContext(tid); + if (apiContextOpt.isEmpty()) { + return buildApiContextMissingResult(tid, userIds.size()); + } + + List ids = new ArrayList<>(userIds.size()); + for (Long userId : userIds) { + ids.add(userId == null ? null : String.valueOf(userId)); + } + return doUpdateHxrAdminUserResellStatus(tid, ids, apiContextOpt.get(), + Boolean.TRUE.equals(isResellEnabled), isResell, + Boolean.TRUE.equals(statusEnabled), status); + } catch (Exception e) { + result.put("success", false); + result.put("message", "处理异常:" + e.getMessage()); + return result; + } + } + + @Override + public Map updateHxrAdminUserResellStatusForAllMembers( + String tenantId, + Boolean isResellEnabled, Integer isResell, + Boolean statusEnabled, Integer status) { + Map result = new HashMap<>(); + try { + if (tenantId == null || tenantId.trim().isEmpty()) { + result.put("success", false); + result.put("message", "租户id不能为空"); + return result; + } + String validationError = validateResellStatusParams(isResellEnabled, isResell, statusEnabled, status); + if (validationError != null) { + result.put("success", false); + result.put("message", validationError); + return result; + } + + // 读取 member_info 全部用户(该表为第三方库镜像,无 tenant_id,已在租户拦截器忽略名单中) + // 过滤掉昵称中包含 "**" 的记录(脱敏/无效数据) + LambdaQueryWrapper memberQuery = new LambdaQueryWrapper<>(); + memberQuery.and(w -> w.isNull(MemberInfo::getNickname) + .or().notLike(MemberInfo::getNickname, "**")); + List members = memberInfoMapper.selectList(memberQuery); + if (members == null || members.isEmpty()) { + result.put("success", false); + result.put("message", "member_info 表无用户数据"); + return result; + } + List userIds = new ArrayList<>(members.size()); + for (MemberInfo member : members) { + userIds.add(member == null ? null : member.getId()); + } + + String tid = tenantId.trim(); + Optional apiContextOpt = + lbThirdIntegrationConfigService.resolveAdminUserApiContext(tid); + if (apiContextOpt.isEmpty()) { + return buildApiContextMissingResult(tid, userIds.size()); + } + + return doUpdateHxrAdminUserResellStatus(tid, userIds, apiContextOpt.get(), + Boolean.TRUE.equals(isResellEnabled), isResell, + Boolean.TRUE.equals(statusEnabled), status); + } catch (Exception e) { + result.put("success", false); + result.put("message", "处理异常:" + e.getMessage()); + return result; + } + } + + /** 校验寄卖/状态参数:至少一项生效,生效字段的值必须为 0 或 1;返回 null 表示校验通过。 */ + private static String validateResellStatusParams( + Boolean isResellEnabled, Integer isResell, + Boolean statusEnabled, Integer status) { + boolean resellEffect = Boolean.TRUE.equals(isResellEnabled); + boolean statusEffect = Boolean.TRUE.equals(statusEnabled); + if (!resellEffect && !statusEffect) { + return "isResellEnabled 与 statusEnabled 至少一项需为 true"; + } + if (resellEffect && (isResell == null || (isResell != 0 && isResell != 1))) { + return "isResell 生效时其值必须为 0 或 1"; + } + if (statusEffect && (status == null || (status != 0 && status != 1))) { + return "status 生效时其值必须为 0 或 1"; + } + return null; + } + + /** 组装「未找到租户第三方集成配置」的失败结果。 */ + private static Map buildApiContextMissingResult(String tid, int total) { + Map result = new HashMap<>(); + result.put("success", false); + result.put("message", + "未找到该租户的第三方集成配置,或配置未启用、URL/凭证不完整(请检查 lb_third_integration_config)"); + result.put("totalRecords", total); + result.put("successCount", 0); + result.put("failCount", total); + result.put("details", List.of()); + result.put("tenantId", tid); + return result; + } + + /** + * 逐个用户调用 hxrd user/update(v1 后台接口)修改 is_resell/status; + * 未生效字段传 null,第三方提交时不携带、保持原值。 + */ + private Map doUpdateHxrAdminUserResellStatus( + String tid, + List userIds, + HxrAdminUserApiContext apiContext, + boolean resellEffect, Integer isResell, + boolean statusEffect, Integer status) { + Map result = new HashMap<>(); + + Integer isResellForApi = resellEffect ? isResell : null; + Integer statusForApi = statusEffect ? status : null; + + List> details = new ArrayList<>(); + int ok = 0; + int fail = 0; + for (String userId : userIds) { + Map one = new HashMap<>(); + one.put("userId", userId); + if (resellEffect) { + one.put("isResell", isResellForApi); + } + if (statusEffect) { + one.put("status", statusForApi); + } + if (userId == null || userId.trim().isEmpty()) { + one.put("success", false); + one.put("message", "用户id为空,跳过"); + fail++; + details.add(one); + continue; + } + try { + boolean updated = + hxrAdminUserService.updateUserResellStatusFields( + userId, isResellForApi, statusForApi, apiContext); + if (updated) { + one.put("success", true); + one.put("message", "user/update 成功"); + ok++; + } else { + one.put("success", false); + one.put("message", "user/update 失败"); + fail++; + } + } catch (Exception ex) { + one.put("success", false); + one.put("message", "调用异常:" + ex.getMessage()); + fail++; + } + details.add(one); + } + + result.put("success", fail == 0); + result.put("message", fail == 0 ? "全部处理成功" : "部分或全部失败,见 details"); + result.put("totalRecords", userIds.size()); + result.put("successCount", ok); + result.put("failCount", fail); + result.put("isResellEnabled", resellEffect); + if (resellEffect) { + result.put("isResell", isResellForApi); + } + result.put("statusEnabled", statusEffect); + if (statusEffect) { + result.put("status", statusForApi); + } + result.put("details", details); + result.put("tenantId", tid); + return result; + } + @Override public Map syncHxrAdminColleagueVipByApplyDateRange( LocalDate applyDateStart, LocalDate applyDateEnd, String tenantId) { diff --git a/src/main/java/com/rj/service/impl/MemberInfoServiceImpl.java b/src/main/java/com/rj/service/impl/MemberInfoServiceImpl.java new file mode 100644 index 0000000..0baa795 --- /dev/null +++ b/src/main/java/com/rj/service/impl/MemberInfoServiceImpl.java @@ -0,0 +1,246 @@ +package com.rj.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.rj.entity.MemberInfo; +import com.rj.mapper.MemberInfoMapper; +import com.rj.service.IMemberInfoService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Slf4j +@Service +public class MemberInfoServiceImpl extends ServiceImpl implements IMemberInfoService { + + @Override + public Map add(MemberInfo entity) { + Map result = new HashMap<>(); + try { + if (entity.getPhone() == null || entity.getPhone().trim().isEmpty()) { + result.put("success", false); + result.put("message", "phone(手机号)不能为空"); + return result; + } + entity.setPhone(entity.getPhone().trim()); + // 同一手机号唯一 + MemberInfo existing = this.getOne( + new LambdaQueryWrapper().eq(MemberInfo::getPhone, entity.getPhone()), + false); + if (existing != null) { + result.put("success", false); + result.put("message", "该手机号已存在"); + return result; + } + // 设置默认值 + if (entity.getStatus() == null) { + entity.setStatus(1); + } + if (entity.getUserLevel() == null || entity.getUserLevel().trim().isEmpty()) { + entity.setUserLevel("normal"); + } + if (entity.getAvailableOrderCount() == null) { + entity.setAvailableOrderCount(0); + } + if (entity.getIsPriorityBuy() == null) { + entity.setIsPriorityBuy(0); + } + if (entity.getCanConsign() == null) { + entity.setCanConsign(1); + } + if (entity.getAuditStatus() == null) { + entity.setAuditStatus(0); + } + LocalDateTime now = LocalDateTime.now(); + if (entity.getCreateTime() == null) { + entity.setCreateTime(now); + } + entity.setUpdateTime(now); + if (entity.getJoinTime() == null) { + entity.setJoinTime(now); + } + + boolean ok = this.save(entity); + result.put("success", ok); + result.put("message", ok ? "新增成功" : "新增失败"); + if (ok) { + result.put("data", this.getById(entity.getId())); + } + return result; + } catch (Exception e) { + result.put("success", false); + result.put("message", "新增异常:" + e.getMessage()); + return result; + } + } + + @Override + public Map update(MemberInfo entity) { + Map result = new HashMap<>(); + try { + if (entity.getId() == null || entity.getId().trim().isEmpty()) { + result.put("success", false); + result.put("message", "id不能为空"); + return result; + } + if (this.getById(entity.getId()) == null) { + result.put("success", false); + result.put("message", "记录不存在"); + return result; + } + if (entity.getPhone() != null) { + entity.setPhone(entity.getPhone().trim()); + } + entity.setUpdateTime(LocalDateTime.now()); + + boolean ok = this.updateById(entity); + result.put("success", ok); + result.put("message", ok ? "编辑成功" : "编辑失败"); + if (ok) { + result.put("data", this.getById(entity.getId())); + } + return result; + } catch (Exception e) { + result.put("success", false); + result.put("message", "编辑异常:" + e.getMessage()); + return result; + } + } + + @Override + public Map deleteById(String id) { + Map result = new HashMap<>(); + try { + if (id == null || id.trim().isEmpty()) { + result.put("success", false); + result.put("message", "id不能为空"); + return result; + } + if (this.getById(id) == null) { + result.put("success", false); + result.put("message", "记录不存在"); + return result; + } + boolean ok = this.removeById(id); + result.put("success", ok); + result.put("message", ok ? "删除成功" : "删除失败"); + return result; + } catch (Exception e) { + result.put("success", false); + result.put("message", "删除异常:" + e.getMessage()); + return result; + } + } + + @Override + public Map pageQuery( + Integer current, + Integer size, + String phone, + String nickname, + String inviteCode, + String parentId, + String userLevel, + Integer status, + Integer auditStatus, + Integer canConsign) { + Map result = new HashMap<>(); + try { + if (current == null || current < 1) { + current = 1; + } + if (size == null || size < 1) { + size = 10; + } + + LambdaQueryWrapper w = buildWrapper( + phone, nickname, inviteCode, parentId, userLevel, status, auditStatus, canConsign); + w.orderByDesc(MemberInfo::getCreateTime); + + Page page = this.page(new Page<>(current, size), w); + result.put("success", true); + result.put("message", "查询成功"); + result.put("data", page.getRecords()); + result.put("total", page.getTotal()); + result.put("current", page.getCurrent()); + result.put("size", page.getSize()); + result.put("pages", page.getPages()); + return result; + } catch (Exception e) { + result.put("success", false); + result.put("message", "查询异常:" + e.getMessage()); + return result; + } + } + + @Override + public Map listAll( + String phone, + String nickname, + String inviteCode, + String parentId, + String userLevel, + Integer status, + Integer auditStatus, + Integer canConsign) { + Map result = new HashMap<>(); + try { + LambdaQueryWrapper w = buildWrapper( + phone, nickname, inviteCode, parentId, userLevel, status, auditStatus, canConsign); + w.orderByDesc(MemberInfo::getCreateTime); + + List list = this.list(w); + result.put("success", true); + result.put("message", "查询成功"); + result.put("data", list); + result.put("total", list.size()); + return result; + } catch (Exception e) { + result.put("success", false); + result.put("message", "查询异常:" + e.getMessage()); + return result; + } + } + + private LambdaQueryWrapper buildWrapper( + String phone, + String nickname, + String inviteCode, + String parentId, + String userLevel, + Integer status, + Integer auditStatus, + Integer canConsign) { + LambdaQueryWrapper w = new LambdaQueryWrapper<>(); + if (phone != null && !phone.trim().isEmpty()) { + w.like(MemberInfo::getPhone, phone.trim()); + } + if (nickname != null && !nickname.trim().isEmpty()) { + w.like(MemberInfo::getNickname, nickname.trim()); + } + if (inviteCode != null && !inviteCode.trim().isEmpty()) { + w.eq(MemberInfo::getInviteCode, inviteCode.trim()); + } + if (parentId != null && !parentId.trim().isEmpty()) { + w.eq(MemberInfo::getParentId, parentId.trim()); + } + if (userLevel != null && !userLevel.trim().isEmpty()) { + w.eq(MemberInfo::getUserLevel, userLevel.trim()); + } + if (status != null) { + w.eq(MemberInfo::getStatus, status); + } + if (auditStatus != null) { + w.eq(MemberInfo::getAuditStatus, auditStatus); + } + if (canConsign != null) { + w.eq(MemberInfo::getCanConsign, canConsign); + } + return w; + } +}