package com.xiaopeng.operation.service.impl; import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient; import com.xiaopeng.api.model.operation.XpElectronicFenceArea; import com.xiaopeng.api.model.vehicleConvoy.XpVehicle; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.operation.config.UidVinBindingConfig; import com.xiaopeng.operation.dto.PriorityMatchResult; import com.xiaopeng.operation.dto.PriorityMatchResult.FailReason; import com.xiaopeng.operation.service.IXpElectronicFenceAreaService; import com.xiaopeng.operation.service.UidVinPriorityMatcher; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.Objects; /** * UID-VIN 优先匹配执行器实现 *

* 匹配流程:查绑定配置 → 查询车辆状态 → 校验可用条件 → 返回结果 *

*/ @Slf4j @Service public class UidVinPriorityMatcherImpl implements UidVinPriorityMatcher { @Resource private UidVinBindingConfig uidVinBindingConfig; @Resource private XpVehicleClient xpVehicleClient; @Resource private IXpElectronicFenceAreaService xpElectronicFenceAreaService; @Override public PriorityMatchResult tryPriorityMatch(String uid, String orderNo, String electronicAreaId) { log.info("[人车订单绑定测试] ===== 开始优先匹配, uid={}, orderNo={}, electronicAreaId={} =====", uid, orderNo, electronicAreaId); // 1. 查询绑定配置 log.info("[人车订单绑定测试] 步骤1: 查询UID绑定配置, uid={}", uid); String vin = uidVinBindingConfig.getBoundVin(uid); if (vin == null) { log.info("[人车订单绑定测试] 步骤1结果: 该UID无绑定VIN, uid={}, orderNo={}", uid, orderNo); return PriorityMatchResult.fail(FailReason.NO_BINDING); } log.info("[人车订单绑定测试] 步骤1结果: 找到绑定关系, uid={}, vin={}", uid, vin); // 2. 查询车辆状态 log.info("[人车订单绑定测试] 步骤2: 调用车队服务查询车辆状态, vin={}", vin); R vehicleR = xpVehicleClient.findByVehicleVin(vin); log.info("[人车订单绑定测试] 步骤2: 车队服务返回, code={}, data={}", vehicleR.getCode(), vehicleR.getData() != null ? "有数据" : "null"); if (vehicleR.getCode() != R.SUCCESS || vehicleR.getData() == null) { log.info("[人车订单绑定测试] 步骤2结果: 车辆不存在或查询失败, uid={}, vin={}, orderNo={}, responseCode={}", uid, vin, orderNo, vehicleR.getCode()); return PriorityMatchResult.fail(FailReason.VEHICLE_NOT_FOUND); } XpVehicle vehicle = vehicleR.getData(); log.info("[人车订单绑定测试] 步骤2结果: 车辆信息获取成功, vin={}, plateNumber={}, operatingStatus={}, state={}, vehicleType={}, electronicId={}", vin, vehicle.getPlateNumber(), vehicle.getOperatingStatus(), vehicle.getState(), vehicle.getVehicleType(), vehicle.getElectronicId()); // 3. 校验车辆可用条件:operatingStatus=1, state=0, vehicleType!=1 log.info("[人车订单绑定测试] 步骤3: 校验车辆可用条件 (operatingStatus==1 && state==0 && vehicleType!=1)"); if (!isVehicleAvailable(vehicle)) { if (!Objects.equals(vehicle.getState(), 0)) { log.info("[人车订单绑定测试] 步骤3结果: 车辆已接单(state={}), 当前有未完成订单, 无法指派, uid={}, vin={}, plateNumber={}, orderNo={}", vehicle.getState(), uid, vin, vehicle.getPlateNumber(), orderNo); } else { log.info("[人车订单绑定测试] 步骤3结果: 车辆不可用, uid={}, vin={}, orderNo={}, operatingStatus={}, state={}, vehicleType={}", uid, vin, orderNo, vehicle.getOperatingStatus(), vehicle.getState(), vehicle.getVehicleType()); } return PriorityMatchResult.fail(FailReason.VEHICLE_UNAVAILABLE); } log.info("[人车订单绑定测试] 步骤3结果: 车辆可用条件校验通过"); // 4. 校验电子围栏一致性:将 areaId 转换为 fenceId,与车辆的 electronicId 比较 log.info("[人车订单绑定测试] 步骤4: 校验电子围栏一致性, 订单围栏区域ID={}, 车辆围栏ID={}", electronicAreaId, vehicle.getElectronicId()); if (!isSameElectronicFence(vehicle, electronicAreaId)) { log.info("[人车订单绑定测试] 步骤4结果: 围栏不一致, uid={}, vin={}, orderNo={}, vehicleElectronicId={}, electronicAreaId={}", uid, vin, orderNo, vehicle.getElectronicId(), electronicAreaId); return PriorityMatchResult.fail(FailReason.WRONG_AREA); } log.info("[人车订单绑定测试] 步骤4结果: 围栏校验通过"); // 5. 所有校验通过 log.info("[人车订单绑定测试] ===== 匹配成功, uid={}, vin={}, orderNo={} =====", uid, vin, orderNo); return PriorityMatchResult.success(vin); } /** * 校验车辆是否可用:运营中(1)、空闲(0)、非测试车(!=1) */ private boolean isVehicleAvailable(XpVehicle vehicle) { return Objects.equals(vehicle.getOperatingStatus(), 1) && Objects.equals(vehicle.getState(), 0) && !Objects.equals(vehicle.getVehicleType(), 1); } /** * 校验车辆是否在同一电子围栏内 *

* electronicAreaId 是围栏区域ID,需要通过 IXpElectronicFenceAreaService 查询 * 对应的围栏ID(electronicId),再与车辆的 electronicId 比较。 */ private boolean isSameElectronicFence(XpVehicle vehicle, String electronicAreaId) { if (electronicAreaId == null || vehicle.getElectronicId() == null) { log.info("[人车订单绑定测试] 围栏校验: 参数为空, electronicAreaId={}, vehicleElectronicId={}", electronicAreaId, vehicle.getElectronicId()); return false; } try { XpElectronicFenceArea area = xpElectronicFenceAreaService.getById(Long.parseLong(electronicAreaId)); if (area == null || area.getElectronicId() == null) { log.info("[人车订单绑定测试] 围栏校验: 围栏区域不存在或无关联围栏, electronicAreaId={}", electronicAreaId); return false; } boolean same = Objects.equals(vehicle.getElectronicId(), area.getElectronicId()); log.info("[人车订单绑定测试] 围栏校验: 车辆围栏ID={}, 区域关联围栏ID={}, 是否一致={}", vehicle.getElectronicId(), area.getElectronicId(), same); return same; } catch (NumberFormatException e) { log.info("[人车订单绑定测试] 围栏校验: electronicAreaId格式异常, electronicAreaId={}", electronicAreaId); return false; } } }