lb用户同步的代码结构

This commit is contained in:
2026-05-19 07:29:43 +08:00
parent 8ddab219b7
commit 7c9ee9101e
10 changed files with 673 additions and 16 deletions

View File

@@ -60,6 +60,7 @@ public class MybatisPlusConfig {
ignoreTables.add("industry_tags"); // 行业标签(示例:如认为是公共字典)
ignoreTables.add("menu"); // 菜单表(不需要租户隔离)
ignoreTables.add("ai_prompts"); // AI 提示词全局配置,表无 tenant_id 字段
ignoreTables.add("lb_user"); // LB 用户表,表无 tenant_id 字段
return new TenantLineHandler() {

View File

@@ -0,0 +1,120 @@
package com.rj.controller;
import com.rj.entity.LbUser;
import com.rj.service.ILbUserService;
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/lbUser")
@Tag(name = "LB 用户", description = "lb_user 增删改查与分页")
public class LbUserController {
@Autowired
private ILbUserService lbUserService;
@PostMapping("/add")
@Operation(summary = "新增")
public ResponseEntity<Map<String, Object>> add(
@Parameter(description = "实体id 为外部用户 id需调用方指定", required = true)
@RequestBody LbUser entity) {
Map<String, Object> result = lbUserService.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<Map<String, Object>> update(
@Parameter(description = "实体", required = true) @RequestBody LbUser entity) {
Map<String, Object> result = lbUserService.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<Map<String, Object>> delete(
@Parameter(description = "主键(用户 id", required = true) @PathVariable Long id) {
Map<String, Object> result = lbUserService.deleteById(id);
Boolean success = (Boolean) result.get("success");
if (success != null && success) {
return ResponseEntity.ok(result);
}
return ResponseEntity.badRequest().body(result);
}
@GetMapping("/get/{id}")
@Operation(summary = "根据ID查询")
public ResponseEntity<Map<String, Object>> getById(
@Parameter(description = "用户 id", required = true) @PathVariable Long id) {
LbUser data = lbUserService.getById(id);
if (data == null) {
return ResponseEntity.badRequest().body(Map.of("success", false, "message", "记录不存在"));
}
return ResponseEntity.ok(Map.of("success", true, "message", "查询成功", "data", data));
}
@GetMapping("/list")
@Operation(summary = "分页查询")
public ResponseEntity<Map<String, Object>> list(
@RequestParam(defaultValue = "1") Integer current,
@RequestParam(defaultValue = "10") Integer size,
@RequestParam(required = false) Long pid,
@RequestParam(required = false) String username,
@RequestParam(required = false) String nickname,
@RequestParam(required = false) String mobile,
@RequestParam(required = false) String invite,
@RequestParam(required = false) Integer status,
@RequestParam(required = false) Integer isVip,
@RequestParam(required = false) Integer isResell,
@RequestParam(required = false) Integer level,
@RequestParam(required = false) String pname,
@Parameter(description = "注册开始时间格式yyyy-MM-dd HH:mm:ss")
@RequestParam(required = false) String joinTimeStart,
@Parameter(description = "注册结束时间格式yyyy-MM-dd HH:mm:ss")
@RequestParam(required = false) String joinTimeEnd,
@Parameter(description = "更新开始时间格式yyyy-MM-dd HH:mm:ss")
@RequestParam(required = false) String updatedAtStart,
@Parameter(description = "更新结束时间格式yyyy-MM-dd HH:mm:ss")
@RequestParam(required = false) String updatedAtEnd) {
Map<String, Object> result =
lbUserService.pageQuery(
current,
size,
pid,
username,
nickname,
mobile,
invite,
status,
isVip,
isResell,
level,
pname,
joinTimeStart,
joinTimeEnd,
updatedAtStart,
updatedAtEnd);
Boolean success = (Boolean) result.get("success");
if (success != null && success) {
return ResponseEntity.ok(result);
}
if (result.get("message") != null && result.get("message").toString().contains("格式错误")) {
return ResponseEntity.badRequest().body(result);
}
return ResponseEntity.internalServerError().body(result);
}
}

View File

@@ -0,0 +1,167 @@
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.LocalDate;
import java.time.LocalDateTime;
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("lb_user")
@Schema(description = "LB 用户表")
public class LbUser implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.INPUT)
@Schema(description = "用户ID外部系统主键")
private Long id;
@TableField("pid")
@Schema(description = "上级用户ID")
private Long pid;
@TableField("username")
@Schema(description = "用户名")
private String username;
@TableField("nickname")
@Schema(description = "昵称")
private String nickname;
@TableField("mobile")
@Schema(description = "手机号")
private String mobile;
@TableField("password")
@Schema(description = "密码(加密后)")
private String password;
@TableField("salt")
@Schema(description = "密码盐")
private String salt;
@TableField("sex")
@Schema(description = "性别")
private String sex;
@TableField("avatar")
@Schema(description = "头像路径")
private String avatar;
@TableField("invite")
@Schema(description = "邀请码")
private String invite;
@TableField("level")
@Schema(description = "等级")
private Integer level;
@TableField("birthday")
@Schema(description = "生日")
private LocalDate birthday;
@TableField("money")
@Schema(description = "余额")
private BigDecimal money;
@TableField("coupon")
@Schema(description = "优惠券金额")
private BigDecimal coupon;
@TableField("self_bonus")
@Schema(description = "自购奖金")
private BigDecimal selfBonus;
@TableField("share_bonus")
@Schema(description = "分享奖金")
private BigDecimal shareBonus;
@TableField("score")
@Schema(description = "积分")
private Integer score;
@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;
@TableField("token")
@Schema(description = "登录令牌")
private String token;
@TableField("created_at")
@Schema(description = "创建时间")
private LocalDateTime createdAt;
@TableField("updated_at")
@Schema(description = "更新时间")
private LocalDateTime updatedAt;
@TableField("status")
@Schema(description = "状态")
private Integer status;
@TableField("viptime")
@Schema(description = "VIP到期时间")
private LocalDateTime viptime;
@TableField("is_vip")
@Schema(description = "是否VIP0否 1是")
private Integer isVip;
@TableField("contract")
@Schema(description = "签约合同文件路径")
private String contract;
@TableField("max_order")
@Schema(description = "最大订单数")
private Integer maxOrder;
@TableField("is_resell")
@Schema(description = "是否可转卖0否 1是")
private Integer isResell;
@TableField("yesterday_sell_count")
@Schema(description = "昨日卖出笔数")
private Integer yesterdaySellCount;
@TableField("today_buy_count")
@Schema(description = "今日买入笔数")
private Integer todayBuyCount;
@TableField("today_buy_total")
@Schema(description = "今日买入总额")
private BigDecimal todayBuyTotal;
@TableField("today_sell_total")
@Schema(description = "今日卖出总额")
private BigDecimal todaySellTotal;
@TableField("poor")
@Schema(description = "贫困标识")
private Integer poor;
@TableField("pname")
@Schema(description = "上级用户昵称")
private String pname;
}

View File

@@ -0,0 +1,9 @@
package com.rj.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.rj.entity.LbUser;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface LbUserMapper extends BaseMapper<LbUser> {
}

View File

@@ -79,9 +79,9 @@ public class LBAdminPullScheduler {
/**
* 未支付/已支付订单同步:工作日每天 11:0015:00应用时区仅在窗口内真正执行。
*/
@Scheduled(
fixedRate = UnPay_MINUTES_MS,
initialDelayString = "${hxr.admin.pull-initial-delay-ms:0}")
// @Scheduled(
// fixedRate = UnPay_MINUTES_MS,
// initialDelayString = "${hxr.admin.pull-initial-delay-ms:0}")
public void pullOrdersForUnPay() {
try {
if (!appConfig.getScheduler().isStart()) {

View File

@@ -169,9 +169,9 @@ public class HxrAdminOrderSelectService {
}
HxrOrderSelectResponse body = opt.get();
log.info("{} order/select ok count={} allMoney={}", label, body.count(), body.allMoney());
for (HxrOrderRow row : body.data()) {
log.info("hxr order row {}", JSON.writeValueAsString(row));
}
// for (HxrOrderRow row : body.data()) {
// log.info("hxr order row {}", JSON.writeValueAsString(row));
// }
}
private static String abbreviate(String s, int maxLen) {

View File

@@ -0,0 +1,33 @@
package com.rj.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.rj.entity.LbUser;
import java.util.Map;
public interface ILbUserService extends IService<LbUser> {
Map<String, Object> add(LbUser entity);
Map<String, Object> update(LbUser entity);
Map<String, Object> deleteById(Long id);
Map<String, Object> pageQuery(
Integer current,
Integer size,
Long pid,
String username,
String nickname,
String mobile,
String invite,
Integer status,
Integer isVip,
Integer isResell,
Integer level,
String pname,
String joinTimeStart,
String joinTimeEnd,
String updatedAtStart,
String updatedAtEnd);
}

View File

@@ -48,7 +48,7 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
private static final int DINGTALK_SELLER_CONFIRM_BATCH_SIZE = 15;
private static final String DINGTALK_SELLER_CONFIRM_PREFIX =
"买家已支付,不要影响 对方寄卖, 请如下卖家确认:";
"提醒,请如下卖家确认,不要耽误 买方寄卖";
private static final long SUM_PLACEHOLDER_USER_ID = 10000L;
@@ -458,16 +458,18 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
return result;
}
List<String> sellerNames =
details.stream()
.map(this::resolveSellerDisplayName)
.distinct()
.limit(DINGTALK_SELLER_CONFIRM_BATCH_SIZE)
.collect(Collectors.toList());
int messageCount = 0;
for (int i = 0; i < details.size(); i += DINGTALK_SELLER_CONFIRM_BATCH_SIZE) {
int end = Math.min(i + DINGTALK_SELLER_CONFIRM_BATCH_SIZE, details.size());
List<LbOrderRow> batch = details.subList(i, end);
String sellerNames =
batch.stream()
.map(this::resolveSellerDisplayName)
.collect(Collectors.joining(","));
dingTalkRobotService.sendText(DINGTALK_SELLER_CONFIRM_PREFIX + sellerNames);
messageCount++;
if (!sellerNames.isEmpty()) {
dingTalkRobotService.sendText(
DINGTALK_SELLER_CONFIRM_PREFIX + String.join(",", sellerNames));
messageCount = 1;
}
result.put("success", true);

View File

@@ -0,0 +1,279 @@
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.LbUser;
import com.rj.mapper.LbUserMapper;
import com.rj.service.ILbUserService;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.HashMap;
import java.util.Map;
@Service
public class LbUserServiceImpl extends ServiceImpl<LbUserMapper, LbUser> implements ILbUserService {
private static final DateTimeFormatter DATETIME_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Override
public Map<String, Object> add(LbUser entity) {
Map<String, Object> result = new HashMap<>();
try {
if (entity.getId() == null) {
result.put("success", false);
result.put("message", "id不能为空");
return result;
}
if (this.getById(entity.getId()) != null) {
result.put("success", false);
result.put("message", "该用户 id 已存在");
return result;
}
applyDefaults(entity);
LocalDateTime now = LocalDateTime.now();
if (entity.getCreatedAt() == null) {
entity.setCreatedAt(now);
}
if (entity.getUpdatedAt() == null) {
entity.setUpdatedAt(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<String, Object> update(LbUser entity) {
Map<String, Object> result = new HashMap<>();
try {
if (entity.getId() == null) {
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;
}
entity.setUpdatedAt(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<String, Object> deleteById(Long id) {
Map<String, Object> result = new HashMap<>();
try {
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<String, Object> pageQuery(
Integer current,
Integer size,
Long pid,
String username,
String nickname,
String mobile,
String invite,
Integer status,
Integer isVip,
Integer isResell,
Integer level,
String pname,
String joinTimeStart,
String joinTimeEnd,
String updatedAtStart,
String updatedAtEnd) {
Map<String, Object> result = new HashMap<>();
try {
if (current == null || current < 1) {
current = 1;
}
if (size == null || size < 1) {
size = 10;
}
LambdaQueryWrapper<LbUser> w = new LambdaQueryWrapper<>();
if (pid != null) {
w.eq(LbUser::getPid, pid);
}
if (username != null && !username.trim().isEmpty()) {
w.like(LbUser::getUsername, username.trim());
}
if (nickname != null && !nickname.trim().isEmpty()) {
w.like(LbUser::getNickname, nickname.trim());
}
if (mobile != null && !mobile.trim().isEmpty()) {
w.like(LbUser::getMobile, mobile.trim());
}
if (invite != null && !invite.trim().isEmpty()) {
w.eq(LbUser::getInvite, invite.trim());
}
if (status != null) {
w.eq(LbUser::getStatus, status);
}
if (isVip != null) {
w.eq(LbUser::getIsVip, isVip);
}
if (isResell != null) {
w.eq(LbUser::getIsResell, isResell);
}
if (level != null) {
w.eq(LbUser::getLevel, level);
}
if (pname != null && !pname.trim().isEmpty()) {
w.like(LbUser::getPname, pname.trim());
}
LocalDateTime joinStart = parseDateTime(joinTimeStart);
if (joinTimeStart != null && !joinTimeStart.trim().isEmpty() && joinStart == null) {
result.put("success", false);
result.put("message", "joinTimeStart 格式错误,请使用 yyyy-MM-dd HH:mm:ss");
return result;
}
LocalDateTime joinEnd = parseDateTime(joinTimeEnd);
if (joinTimeEnd != null && !joinTimeEnd.trim().isEmpty() && joinEnd == null) {
result.put("success", false);
result.put("message", "joinTimeEnd 格式错误,请使用 yyyy-MM-dd HH:mm:ss");
return result;
}
if (joinStart != null) {
w.ge(LbUser::getJoinTime, joinStart);
}
if (joinEnd != null) {
w.le(LbUser::getJoinTime, joinEnd);
}
LocalDateTime updatedStart = parseDateTime(updatedAtStart);
if (updatedAtStart != null && !updatedAtStart.trim().isEmpty() && updatedStart == null) {
result.put("success", false);
result.put("message", "updatedAtStart 格式错误,请使用 yyyy-MM-dd HH:mm:ss");
return result;
}
LocalDateTime updatedEnd = parseDateTime(updatedAtEnd);
if (updatedAtEnd != null && !updatedAtEnd.trim().isEmpty() && updatedEnd == null) {
result.put("success", false);
result.put("message", "updatedAtEnd 格式错误,请使用 yyyy-MM-dd HH:mm:ss");
return result;
}
if (updatedStart != null) {
w.ge(LbUser::getUpdatedAt, updatedStart);
}
if (updatedEnd != null) {
w.le(LbUser::getUpdatedAt, updatedEnd);
}
w.orderByDesc(LbUser::getUpdatedAt).orderByDesc(LbUser::getId);
Page<LbUser> 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;
}
}
private static void applyDefaults(LbUser entity) {
if (entity.getLevel() == null) {
entity.setLevel(0);
}
if (entity.getMoney() == null) {
entity.setMoney(BigDecimal.ZERO);
}
if (entity.getCoupon() == null) {
entity.setCoupon(BigDecimal.ZERO);
}
if (entity.getSelfBonus() == null) {
entity.setSelfBonus(BigDecimal.ZERO);
}
if (entity.getShareBonus() == null) {
entity.setShareBonus(BigDecimal.ZERO);
}
if (entity.getScore() == null) {
entity.setScore(0);
}
if (entity.getStatus() == null) {
entity.setStatus(1);
}
if (entity.getIsVip() == null) {
entity.setIsVip(0);
}
if (entity.getMaxOrder() == null) {
entity.setMaxOrder(0);
}
if (entity.getIsResell() == null) {
entity.setIsResell(0);
}
if (entity.getYesterdaySellCount() == null) {
entity.setYesterdaySellCount(0);
}
if (entity.getTodayBuyCount() == null) {
entity.setTodayBuyCount(0);
}
if (entity.getTodayBuyTotal() == null) {
entity.setTodayBuyTotal(BigDecimal.ZERO);
}
if (entity.getTodaySellTotal() == null) {
entity.setTodaySellTotal(BigDecimal.ZERO);
}
if (entity.getPoor() == null) {
entity.setPoor(0);
}
}
private static LocalDateTime parseDateTime(String text) {
if (text == null || text.trim().isEmpty()) {
return null;
}
try {
return LocalDateTime.parse(text.trim(), DATETIME_FMT);
} catch (DateTimeParseException e) {
return null;
}
}
}