因为数据库连接问题导致的插入数据库异常

This commit is contained in:
2026-05-15 23:30:40 +08:00
parent 42b1555c80
commit d66daf375c
25 changed files with 1371 additions and 4 deletions

View File

@@ -1,6 +1,7 @@
package com.rj;
import com.rj.config.AmapProperties;
import com.rj.config.HxrAdminProperties;
import com.rj.config.LbAssessmentDingTalkProperties;
import com.rj.config.YihangyiVllmAsrProperties;
import org.mybatis.spring.annotation.MapperScan;
@@ -41,7 +42,12 @@ import org.springframework.scheduling.annotation.EnableScheduling;
@MapperScan("com.rj.mapper")
@SpringBootApplication
@EnableScheduling
@EnableConfigurationProperties({YihangyiVllmAsrProperties.class, AmapProperties.class, LbAssessmentDingTalkProperties.class})
@EnableConfigurationProperties({
YihangyiVllmAsrProperties.class,
AmapProperties.class,
LbAssessmentDingTalkProperties.class,
HxrAdminProperties.class
})
public class AISmartCard20251230Application {
public static void main(String[] args) {

View File

@@ -1,10 +1,13 @@
package com.rj.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import java.time.Clock;
/**
* 显式扩大 {@code @Scheduled} 线程池,避免单个耗时任务(如长时间 HTTP占满默认单线程后拖死全部定时任务。
* <p>与 {@code spring.task.scheduling.pool.size} 配置互补;此处代码保证至少 8 个调度线程。
@@ -14,6 +17,11 @@ public class AppSchedulingConfiguration implements SchedulingConfigurer {
private static final int SCHEDULER_POOL_SIZE = 8;
@Bean
public Clock applicationClock() {
return Clock.systemDefaultZone();
}
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();

View File

@@ -0,0 +1,34 @@
package com.rj.config;
import com.rj.scheduler.LBAdminPullScheduler;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* hxrd 后台订单列表拉取(供 {@link LBAdminPullScheduler} 使用)。
*/
@Data
@ConfigurationProperties(prefix = "hxr.admin")
public class HxrAdminProperties {
/**
* 是否启用拉取任务;未启用时不发 HTTP 请求。
*/
private boolean enabled = true;
/**
* 完整请求 URL含查询串与浏览器地址栏一致即可。
*/
private String orderSelectUrl =
"https://hxrdhoutai.hxrdsm.cn/app/admin/order/select?page=1&limit=90";
/**
* 请求头 Cookie 完整取值,例如 {@code PHPSID=xxxx}。非空时优先于 {@link #phpsid}。
*/
private String cookie = "";
/**
* 仅 PHPSID 会话值(不含 {@code PHPSID=} 前缀);在 {@link #cookie} 为空时使用。
*/
private String phpsid = "";
}

View File

@@ -0,0 +1,98 @@
package com.rj.controller;
import com.rj.dto.LbOrderRowSyncFromHxrRequest;
import com.rj.entity.LbOrderRow;
import com.rj.service.ILbOrderRowService;
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/lbOrderRow")
@Tag(name = "LB 订单行", description = "lb_order_row 增删改查与分页")
public class LbOrderRowController {
@Autowired
private ILbOrderRowService lbOrderRowService;
@PostMapping("/add")
@Operation(summary = "新增")
public ResponseEntity<Map<String, Object>> add(
@Parameter(description = "实体id 为订单 id需调用方指定", required = true) @RequestBody LbOrderRow entity) {
Map<String, Object> result = lbOrderRowService.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 LbOrderRow entity) {
Map<String, Object> result = lbOrderRowService.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 = lbOrderRowService.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<Map<String, Object>> list(
@RequestParam(defaultValue = "1") Integer current,
@RequestParam(defaultValue = "10") Integer size,
@RequestParam(required = false) String isResell,
@RequestParam(required = false) String orderSn,
@RequestParam(required = false) Long buyerId,
@RequestParam(required = false) Long sellerId,
@RequestParam(required = false) Integer status,
@RequestParam(required = false) Long merchandiseId) {
Map<String, Object> result =
lbOrderRowService.pageQuery(
current, size, isResell, orderSn, buyerId, sellerId, status, merchandiseId);
Boolean success = (Boolean) result.get("success");
if (success != null && success) {
return ResponseEntity.ok(result);
}
return ResponseEntity.internalServerError().body(result);
}
@PostMapping("/sync-order-from-third")
@Operation(
summary = "从 外部系统 同步订单",
description = "按购买时间区间、租户 id、转卖状态调用后台 order/select将结果写入 lb_order_row按订单 id upsert")
public ResponseEntity<Map<String, Object>> syncFromHxr(
@Parameter(description = "同步条件", required = true) @RequestBody LbOrderRowSyncFromHxrRequest request) {
Map<String, Object> result =
lbOrderRowService.syncFromHxrAdmin(
request.getBuyTimeStart(),
request.getBuyTimeEnd(),
request.getTenantId(),
request.getIsResell());
Boolean success = (Boolean) result.get("success");
if (success != null && success) {
return ResponseEntity.ok(result);
}
return ResponseEntity.badRequest().body(result);
}
}

View File

@@ -0,0 +1,24 @@
package com.rj.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 从 hxrd 后台同步订单到 {@code lb_order_row} 的请求体。
*/
@Data
@Schema(description = "LB 订单从 hxrd 后台同步请求")
public class LbOrderRowSyncFromHxrRequest {
@Schema(description = "购买时间起(对应后台 buy_time[0]),可空表示不限制")
private String buyTimeStart;
@Schema(description = "购买时间止(对应后台 buy_time[1]),可空表示不限制")
private String buyTimeEnd;
@Schema(description = "写入本系统的租户 id", requiredMode = Schema.RequiredMode.REQUIRED)
private String tenantId;
@Schema(description = "转卖状态筛选(对应后台 is_resell", requiredMode = Schema.RequiredMode.REQUIRED)
private Integer isResell;
}

View File

@@ -0,0 +1,28 @@
package com.rj.dto.hxr;
/**
* hxrd 后台 {@code /app/admin/order/select} 返回的 {@code data} 中单条订单。
*/
public record HxrOrderRow(
long id,
Long oldId,
long sellerId,
long buyerId,
String orderSn,
String totalMoney,
String payTime,
String payImg,
int status,
int isResell,
int isShow,
String consignee,
String phone,
String province,
String city,
String area,
String address,
long merchandiseId,
String confirmTime,
String buyTime,
String createdAt,
String updatedAt) {}

View File

@@ -0,0 +1,9 @@
package com.rj.dto.hxr;
import java.util.List;
/**
* hxrd 后台 {@code /app/admin/order/select} 顶层 JSON。
*/
public record HxrOrderSelectResponse(
int code, String msg, int count, List<HxrOrderRow> data, String allMoney) {}

View File

@@ -0,0 +1,41 @@
package com.rj.entity;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
/**
* Parses {@link LocalDateTime} from ISO-8601 or common SQL-style {@code yyyy-MM-dd HH:mm:ss}.
*/
public class FlexibleLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
private static final DateTimeFormatter SQL_SPACE = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Override
public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String text = p.getValueAsString();
if (text == null) {
return null;
}
text = text.trim();
if (text.isEmpty()) {
return null;
}
try {
return LocalDateTime.parse(text, SQL_SPACE);
} catch (DateTimeParseException ignored) {
// continue
}
try {
return LocalDateTime.parse(text, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
} catch (DateTimeParseException e) {
throw ctxt.weirdStringException(text, LocalDateTime.class,
"Expected ISO-8601 local date-time or yyyy-MM-dd HH:mm:ss");
}
}
}

View File

@@ -0,0 +1,19 @@
package com.rj.entity;
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Accepts ISO-8601 local date-time and common SQL-style {@code yyyy-MM-dd HH:mm:ss} for JSON binding.
*/
@JacksonAnnotationsInside
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@JsonDeserialize(using = FlexibleLocalDateTimeDeserializer.class)
public @interface JsonFlexibleLocalDateTime {
}

View File

@@ -76,13 +76,16 @@ public class LbAssessmentApply implements Serializable {
@TableField("application_datetime")
@Schema(description = "申请日期时间")
@JsonFlexibleLocalDateTime
private LocalDateTime applicationDatetime;
@TableField("created_at")
@Schema(description = "创建时间")
@JsonFlexibleLocalDateTime
private LocalDateTime createdAt;
@TableField("updated_at")
@Schema(description = "修改时间")
@JsonFlexibleLocalDateTime
private LocalDateTime updatedAt;
}

View File

@@ -0,0 +1,113 @@
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;
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("lb_order_row")
@Schema(description = "LB 订单行表")
public class LbOrderRow implements Serializable {
private static final long serialVersionUID = 1L;
/** 业务主键为订单 id由调用方传入非数据库自增 */
@TableId(value = "id", type = IdType.INPUT)
@Schema(description = "订单 id")
private Long id;
@TableField("old_id")
@Schema(description = "旧订单 id")
private Long oldId;
@TableField("tenant_id")
@Schema(description = "租户ID")
private String tenantId;
@TableField("seller_id")
@Schema(description = "卖家 id")
private Long sellerId;
@TableField("buyer_id")
@Schema(description = "买家 id")
private Long buyerId;
@TableField("order_sn")
@Schema(description = "订单号")
private String orderSn;
@TableField("total_money")
@Schema(description = "总金额(接口为字符串)")
private String totalMoney;
@TableField("pay_time")
@Schema(description = "支付时间(原样字符串)")
private String payTime;
@TableField("pay_img")
@Schema(description = "支付凭证图")
private String payImg;
@TableField("status")
@Schema(description = "状态")
private Integer status;
@TableField("is_resell")
@Schema(description = "是否转卖")
private Integer isResell;
@TableField("is_show")
@Schema(description = "是否展示")
private Integer isShow;
@TableField("consignee")
@Schema(description = "收货人")
private String consignee;
@TableField("phone")
@Schema(description = "电话")
private String phone;
@TableField("province")
@Schema(description = "")
private String province;
@TableField("city")
@Schema(description = "")
private String city;
@TableField("area")
@Schema(description = "")
private String area;
@TableField("address")
@Schema(description = "详细地址")
private String address;
@TableField("merchandise_id")
@Schema(description = "商品 id")
private Long merchandiseId;
@TableField("confirm_time")
@Schema(description = "确认时间")
private String confirmTime;
@TableField("buy_time")
@Schema(description = "下单时间")
private String buyTime;
@TableField("created_at")
@Schema(description = "创建时间")
private String createdAt;
@TableField("updated_at")
@Schema(description = "更新时间")
private String updatedAt;
}

View File

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

View File

@@ -0,0 +1,66 @@
package com.rj.scheduler;
import com.rj.config.AppConfig;
import com.rj.config.HxrAdminProperties;
import com.rj.service.HxrAdminOrderSelectService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.Clock;
import java.time.DayOfWeek;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
/**
* hxrd 后台订单列表定时拉取:每 50 分钟触发一次,仅工作日(周一至周五)且在每天 18:1023:59:59应用时区内真正执行。
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class LBAdminPullScheduler {
private static final long FIFTY_MINUTES_MS = 50L * 60L * 1000L;
private final AppConfig appConfig;
private final HxrAdminProperties hxrAdminProperties;
private final HxrAdminOrderSelectService hxrAdminOrderSelectService;
private final Clock clock;
@Scheduled(
fixedRate = FIFTY_MINUTES_MS,
initialDelayString = "${hxr.admin.pull-initial-delay-ms:0}")
public void pullAdminOrders() {
try {
if (!appConfig.getScheduler().isStart()) {
log.debug("全局调度未启用,跳过 未寄卖 订单拉取");
return;
}
if (!hxrAdminProperties.isEnabled()) {
log.debug("hxr.admin.enabled=false跳过订单拉取");
return;
}
ZoneId zone = ZoneId.of(appConfig.getTimezone());
ZonedDateTime nowZdt = ZonedDateTime.now(clock.withZone(zone));
DayOfWeek dow = nowZdt.getDayOfWeek();
if (dow == DayOfWeek.SATURDAY || dow == DayOfWeek.SUNDAY) {
log.debug("当前为周末 {},跳过 未寄卖 订单拉取", dow);
return;
}
LocalTime now = nowZdt.toLocalTime();
LocalTime windowStart = LocalTime.of(18, 10);
LocalTime windowEnd = LocalTime.of(23, 59, 59);
if (now.isBefore(windowStart) || now.isAfter(windowEnd)) {
log.debug("当前时刻 {} 不在窗口 {}{},跳过 未寄卖 订单拉取", now, windowStart, windowEnd);
return;
}
log.info("开始执行 未寄卖 订单拉取(工作日 18:1023:59:59 窗口内)");
hxrAdminOrderSelectService.fetchAndLogEachOrder();
} catch (Exception e) {
log.error("未寄卖 admin 订单拉取失败", e);
}
}
}

View File

@@ -0,0 +1,148 @@
package com.rj.service;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.rj.config.HxrAdminProperties;
import com.rj.dto.hxr.HxrOrderRow;
import com.rj.dto.hxr.HxrOrderSelectResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.util.UriComponentsBuilder;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.Optional;
/**
* 调用 hxrd 后台订单列表接口并解析 JSON。
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class HxrAdminOrderSelectService {
private static final ObjectMapper JSON = new ObjectMapper()
.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
private final HxrAdminProperties properties;
/**
* 拉取订单列表;配置未就绪或 HTTP 非 2xx 时返回 empty。
* <p>使用 {@link HxrAdminProperties#getOrderSelectUrl()} 原样请求(与定时任务一致)。
*/
public Optional<HxrOrderSelectResponse> fetchOrderSelect() throws Exception {
return fetchOrderSelectInternal(properties.getOrderSelectUrl());
}
/**
* 按购买时间区间、转卖状态等条件拉取订单列表(在配置的 {@code orderSelectUrl} 上覆盖查询参数)。
*
* @param buyTimeStart 购买时间起,对应 {@code buy_time[0]},可为 null 或空串表示不限制
* @param buyTimeEnd 购买时间止,对应 {@code buy_time[1]}
* @param isResell 转卖筛选,对应 {@code is_resell};为 null 时不改写该参数
*/
public Optional<HxrOrderSelectResponse> fetchOrderSelect(
String buyTimeStart, String buyTimeEnd, Integer isResell) throws Exception {
return fetchOrderSelectInternal(buildOrderSelectUrl(buyTimeStart, buyTimeEnd, isResell));
}
private Optional<HxrOrderSelectResponse> fetchOrderSelectInternal(String requestUri) throws Exception {
String cookieHeader = resolveCookieHeader();
if (cookieHeader == null || cookieHeader.isBlank()) {
log.warn("hxr.admin 未配置 cookie 或 phpsid跳过拉取");
return Optional.empty();
}
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(35))
.followRedirects(HttpClient.Redirect.NORMAL)
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(requestUri))
.timeout(Duration.ofSeconds(160))
.header("Accept", "application/json, text/javascript, */*; q=0.01")
.header("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6")
.header("Cookie", cookieHeader)
.header("Priority", "u=1, i")
.header("Referer", "https://hxrdhoutai.hxrdsm.cn/app/admin/order/index")
.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36 Edg/148.0.0.0")
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
int status = response.statusCode();
if (status < 200 || status >= 300) {
log.warn("hxr admin order/select HTTP {} bodyPrefix={}", status, abbreviate(response.body(), 500));
return Optional.empty();
}
HxrOrderSelectResponse body = JSON.readValue(response.body(), HxrOrderSelectResponse.class);
if (body.code() != 0) {
log.warn("hxr admin order/select api code={} msg={}", body.code(), body.msg());
return Optional.empty();
}
return Optional.of(body);
}
/**
* 在 {@link HxrAdminProperties#getOrderSelectUrl()} 上覆盖 {@code buy_time[0]}、{@code buy_time[1]}、{@code is_resell}。
*/
private String buildOrderSelectUrl(String buyTimeStart, String buyTimeEnd, Integer isResell) {
UriComponentsBuilder b = UriComponentsBuilder.fromUriString(properties.getOrderSelectUrl());
b.replaceQueryParam("buy_time[0]", buyTimeStart == null ? "" : buyTimeStart);
b.replaceQueryParam("buy_time[1]", buyTimeEnd == null ? "" : buyTimeEnd);
if (isResell != null) {
b.replaceQueryParam("is_resell", isResell);
}
return b.build().encode().toUriString();
}
/**
* 拉取并逐条打日志(一行一条 JSON
*/
public void fetchAndLogEachOrder() throws Exception {
Optional<HxrOrderSelectResponse> opt = fetchOrderSelect();
if (opt.isEmpty()) {
return;
}
HxrOrderSelectResponse body = opt.get();
log.info("未寄卖 order/select ok count={} allMoney={}", body.count(), body.allMoney());
for (HxrOrderRow row : body.data()) {
log.info("hxr order row {}", JSON.writeValueAsString(row));
}
}
private String resolveCookieHeader() {
String c = firstNonBlank(properties.getCookie());
if (c != null) {
return c;
}
String id = firstNonBlank(properties.getPhpsid());
if (id != null) {
return "PHPSID=" + id;
}
return "";
}
private static String firstNonBlank(String s) {
if (s == null) {
return null;
}
String t = s.trim();
return t.isEmpty() ? null : t;
}
private static String abbreviate(String s, int maxLen) {
if (s == null) {
return "";
}
return s.length() <= maxLen ? s : s.substring(0, maxLen) + "...";
}
}

View File

@@ -0,0 +1,31 @@
package com.rj.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.rj.entity.LbOrderRow;
import java.util.Map;
public interface ILbOrderRowService extends IService<LbOrderRow> {
Map<String, Object> add(LbOrderRow entity);
Map<String, Object> update(LbOrderRow entity);
Map<String, Object> deleteById(Long id);
Map<String, Object> pageQuery(
Integer current,
Integer size,
String tenantId,
String orderSn,
Long buyerId,
Long sellerId,
Integer status,
Long merchandiseId);
/**
* 按条件调用 hxrd 后台订单列表接口拉取数据,并 upsert 到 {@code lb_order_row}。
*/
Map<String, Object> syncFromHxrAdmin(
String buyTimeStart, String buyTimeEnd, String tenantId, Integer isResell);
}

View File

@@ -0,0 +1,273 @@
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.dto.hxr.HxrOrderRow;
import com.rj.dto.hxr.HxrOrderSelectResponse;
import com.rj.entity.LbOrderRow;
import com.rj.mapper.LbOrderRowMapper;
import com.rj.service.HxrAdminOrderSelectService;
import com.rj.service.ILbOrderRowService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@Service
public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrderRow> implements ILbOrderRowService {
@Autowired
private HxrAdminOrderSelectService hxrAdminOrderSelectService;
@Override
public Map<String, Object> add(LbOrderRow entity) {
Map<String, Object> result = new HashMap<>();
try {
if (entity.getId() == null) {
result.put("success", false);
result.put("message", "id订单 id不能为空");
return result;
}
if (entity.getTenantId() == null || entity.getTenantId().trim().isEmpty()) {
result.put("success", false);
result.put("message", "tenantId不能为空");
return result;
}
if (entity.getSellerId() == null) {
result.put("success", false);
result.put("message", "sellerId不能为空");
return result;
}
if (entity.getBuyerId() == null) {
result.put("success", false);
result.put("message", "buyerId不能为空");
return result;
}
if (entity.getOrderSn() == null || entity.getOrderSn().trim().isEmpty()) {
result.put("success", false);
result.put("message", "orderSn不能为空");
return result;
}
if (entity.getMerchandiseId() == null) {
result.put("success", false);
result.put("message", "merchandiseId不能为空");
return result;
}
if (this.getById(entity.getId()) != null) {
result.put("success", false);
result.put("message", "该订单 id 已存在");
return result;
}
entity.setTenantId(entity.getTenantId().trim());
entity.setOrderSn(entity.getOrderSn().trim());
if (entity.getStatus() == null) {
entity.setStatus(0);
}
if (entity.getIsResell() == null) {
entity.setIsResell(0);
}
if (entity.getIsShow() == null) {
entity.setIsShow(0);
}
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(LbOrderRow 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;
}
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,
String isResell,
String orderSn,
Long buyerId,
Long sellerId,
Integer status,
Long merchandiseId) {
Map<String, Object> result = new HashMap<>();
try {
if (current == null || current < 1) {
current = 1;
}
if (size == null || size < 1) {
size = 10;
}
LambdaQueryWrapper<LbOrderRow> w = new LambdaQueryWrapper<>();
if (isResell != null && !isResell.trim().isEmpty()) {
w.eq(LbOrderRow::getIsResell, isResell.trim());
}
if (orderSn != null && !orderSn.trim().isEmpty()) {
w.like(LbOrderRow::getOrderSn, orderSn.trim());
}
if (buyerId != null) {
w.eq(LbOrderRow::getBuyerId, buyerId);
}
if (sellerId != null) {
w.eq(LbOrderRow::getSellerId, sellerId);
}
if (status != null) {
w.eq(LbOrderRow::getStatus, status);
}
if (merchandiseId != null) {
w.eq(LbOrderRow::getMerchandiseId, merchandiseId);
}
w.orderByDesc(LbOrderRow::getId);
Page<LbOrderRow> 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
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> syncFromHxrAdmin(
String buyTimeStart, String buyTimeEnd, String tenantId, Integer isResell) {
Map<String, Object> result = new HashMap<>();
try {
if (tenantId == null || tenantId.trim().isEmpty()) {
result.put("success", false);
result.put("message", "tenantId不能为空");
return result;
}
Optional<HxrOrderSelectResponse> opt =
hxrAdminOrderSelectService.fetchOrderSelect(buyTimeStart, buyTimeEnd, isResell);
if (opt.isEmpty()) {
result.put("success", false);
result.put("message", "未拉取到订单(请检查 hxr.admin cookie/phpsid、网络或后台返回");
result.put("synced", 0);
return result;
}
HxrOrderSelectResponse body = opt.get();
List<HxrOrderRow> rows = body.data();
if (rows == null || rows.isEmpty()) {
result.put("success", true);
result.put("message", "接口成功,本页无订单数据");
result.put("synced", 0);
result.put("remoteCount", body.count());
return result;
}
String tid = tenantId.trim();
List<LbOrderRow> entities = new ArrayList<>(rows.size());
for (HxrOrderRow row : rows) {
entities.add(toLbOrderRow(row, tid));
}
boolean ok = this.saveOrUpdateBatch(entities);
result.put("success", ok);
result.put("message", ok ? "同步完成" : "批量保存失败");
result.put("synced", ok ? entities.size() : 0);
result.put("remoteCount", body.count());
result.put("allMoney", body.allMoney());
return result;
} catch (Exception e) {
result.put("success", false);
result.put("message", "同步异常:" + e.getMessage());
result.put("synced", 0);
return result;
}
}
private static LbOrderRow toLbOrderRow(HxrOrderRow row, String tenantId) {
LbOrderRow e = new LbOrderRow();
e.setId(row.id());
e.setOldId(row.oldId());
e.setTenantId(tenantId);
e.setSellerId(row.sellerId());
e.setBuyerId(row.buyerId());
e.setOrderSn(row.orderSn());
e.setTotalMoney(row.totalMoney());
e.setPayTime(row.payTime());
e.setPayImg(row.payImg());
e.setStatus(row.status());
e.setIsResell(row.isResell());
e.setIsShow(row.isShow());
e.setConsignee(row.consignee());
e.setPhone(row.phone());
e.setProvince(row.province());
e.setCity(row.city());
e.setArea(row.area());
e.setAddress(row.address());
e.setMerchandiseId(row.merchandiseId());
e.setConfirmTime(row.confirmTime());
e.setBuyTime(row.buyTime());
e.setCreatedAt(row.createdAt());
e.setUpdatedAt(row.updatedAt());
return e;
}
}