package com.ruoyi.system.service.impl; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.entity.SysDept; import com.ruoyi.system.domain.VehicleInfo; import com.ruoyi.system.domain.VehicleSyncDTO; import com.ruoyi.system.mapper.SysDeptMapper; import com.ruoyi.system.service.IVehicleInfoService; import com.ruoyi.system.service.IVehicleSyncDataService; import com.ruoyi.system.service.IVehicleSyncService; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 车辆同步服务实现 * * 职责:将从 SQL Server 查询到的车辆数据同步到 MySQL * * 数据流向:接收 DTO → 同步到 MySQL * * @author ruoyi * @date 2025-10-20 */ @Service public class VehicleSyncServiceImpl implements IVehicleSyncService { private static final Logger log = LoggerFactory.getLogger(VehicleSyncServiceImpl.class); @Autowired private IVehicleInfoService vehicleInfoService; @Autowired private SysDeptMapper sysDeptMapper; /** * 同步车辆数据到MySQL * * @param vehicles 从SQL Server查询的车辆列表 * @return 同步结果 */ @Override @Transactional public AjaxResult syncVehicles(List vehicles) { if (vehicles == null || vehicles.isEmpty()) { return AjaxResult.error("车辆数据为空,无法同步"); } try { log.info("开始同步 {} 条车辆数据到 MySQL...", vehicles.size()); int insertCount = 0; int updateCount = 0; int skipCount = 0; Map errorMessages = new HashMap<>(); for (VehicleSyncDTO vehicleDTO : vehicles) { try { // 提取车牌号(去除括号中的内容) String plateNumber = extractPlateNumber(vehicleDTO.getCarLicense()); if (StringUtils.isBlank(plateNumber)) { log.warn("车辆 CarID={} 车牌号为空,跳过同步", vehicleDTO.getCarId()); skipCount++; continue; } // 查询车辆是否存在 VehicleInfo existingVehicle = findVehicleByPlateNumber(plateNumber); // 解析部门信息 Long deptId = parseDeptIdFromCarOrdClass(vehicleDTO.getCarOrdClass()); if (existingVehicle != null) { // 更新车辆信息 existingVehicle.setCarId(vehicleDTO.getCarId()); existingVehicle.setDeptId(deptId); // 可以选择是否更新其他字段 vehicleInfoService.updateVehicleInfo(existingVehicle); updateCount++; log.debug("更新车辆: {} (CarID={}), 部门ID={}", plateNumber, vehicleDTO.getCarId(), deptId); } else { // 新增车辆信息 VehicleInfo newVehicle = new VehicleInfo(); newVehicle.setVehicleNo(plateNumber); newVehicle.setCarId(vehicleDTO.getCarId()); newVehicle.setDeptId(deptId); newVehicle.setStatus("0"); newVehicle.setPlatformCode("LEGACY"); // 标记为旧系统同步 newVehicle.setRemark("从旧系统同步,CarID: " + vehicleDTO.getCarId()); vehicleInfoService.insertVehicleInfo(newVehicle); insertCount++; log.debug("新增车辆: {} (CarID={}), 部门ID={}", plateNumber, vehicleDTO.getCarId(), deptId); } } catch (Exception e) { String errorMsg = String.format("同步车辆 CarID=%d 失败: %s", vehicleDTO.getCarId(), e.getMessage()); log.error(errorMsg, e); errorMessages.put("CarID_" + vehicleDTO.getCarId(), errorMsg); } } String resultMsg = String.format( "车辆同步完成 - 新增: %d, 更新: %d, 跳过: %d, 失败: %d", insertCount, updateCount, skipCount, errorMessages.size()); log.info(resultMsg); Map result = new HashMap<>(); result.put("insertCount", insertCount); result.put("updateCount", updateCount); result.put("skipCount", skipCount); result.put("errorCount", errorMessages.size()); result.put("errors", errorMessages); if (errorMessages.isEmpty()) { return AjaxResult.success(resultMsg, result); } else { return AjaxResult.warn(resultMsg, result); } } catch (Exception e) { log.error("同步车辆数据到 MySQL 失败", e); return AjaxResult.error("同步失败: " + e.getMessage()); } } /** * 提取车牌号(去除括号中的内容) * 例如:浙A12345(奔驰) -> 浙A12345 * * @param carLicense 原始车牌号 * @return 提取后的车牌号 */ private String extractPlateNumber(String carLicense) { if (StringUtils.isBlank(carLicense)) { return null; } // 去除空格 String license = carLicense.trim(); // 查找左括号位置(支持中文和英文括号) int leftBracketIndex = license.indexOf('('); int leftBracketIndexCn = license.indexOf('('); // 取最小的有效括号位置 int bracketIndex = -1; if (leftBracketIndex >= 0 && leftBracketIndexCn >= 0) { bracketIndex = Math.min(leftBracketIndex, leftBracketIndexCn); } else if (leftBracketIndex >= 0) { bracketIndex = leftBracketIndex; } else if (leftBracketIndexCn >= 0) { bracketIndex = leftBracketIndexCn; } // 如果找到括号,截取括号前的部分;否则返回原字符串 if (bracketIndex > 0) { return license.substring(0, bracketIndex).trim(); } return license; } /** * 根据车牌号查找车辆(模糊匹配) * * @param plateNumber 车牌号 * @return 车辆信息 */ private VehicleInfo findVehicleByPlateNumber(String plateNumber) { // 先尝试精确匹配 VehicleInfo vehicle = vehicleInfoService.selectVehicleInfoByPlateNumber(plateNumber); if (vehicle != null) { return vehicle; } // 如果精确匹配失败,尝试模糊匹配(查询所有车辆,找到包含该车牌号的) VehicleInfo query = new VehicleInfo(); List allVehicles = vehicleInfoService.selectVehicleInfoList(query); for (VehicleInfo v : allVehicles) { if (StringUtils.isNotBlank(v.getVehicleNo())) { // 如果数据库中的车牌号包含查询的车牌号,或查询的车牌号包含数据库中的车牌号 String dbPlateNumber = extractPlateNumber(v.getVehicleNo()); if (plateNumber.contains(dbPlateNumber) || dbPlateNumber.contains(plateNumber)) { return v; } } } return null; } /** * 从 CarOrdClass 解析部门ID,并转换为分公司ID * CarOrdClass格式可能是:ZB、HB.TI等 * 需要拆分并在sys_dept中匹配dispatch_order_class字段 * * @param carOrdClass 车辆单据类型编码 * @return 分公司ID,如果未找到返回null */ private Long parseDeptIdFromCarOrdClass(String carOrdClass) { if (StringUtils.isBlank(carOrdClass)) { log.debug("CarOrdClass为空,无法解析部门"); return null; } // 拆分CarOrdClass,可能的分隔符:. , 空格 String[] codes = carOrdClass.split("[.,\\s]+"); for (String code : codes) { if (StringUtils.isBlank(code)) { continue; } code = code.trim(); // 查询匹配dispatch_order_class的部门 SysDept dept = findDeptByDispatchOrderClass(code); if (dept != null) { log.debug("通过dispatch_order_class='{}' 找到部门: {} (ID={})", code, dept.getDeptName(), dept.getDeptId()); // 将部门ID转换为分公司ID Long branchCompanyId = sysDeptMapper.selectBranchCompanyIdByDeptId(dept.getDeptId()); if (branchCompanyId != null) { log.debug("将部门ID {} 转换为分公司ID: {}", dept.getDeptId(), branchCompanyId); return branchCompanyId; } else { log.warn("部门ID {} 无法转换为分公司ID,可能是总公司或数据异常", dept.getDeptId()); return null; } } } log.warn("未找到匹配CarOrdClass='{}' 的部门", carOrdClass); return null; } /** * 根据dispatch_order_class查询部门 * * @param dispatchOrderClass 调度单编码 * @return 部门信息 */ private SysDept findDeptByDispatchOrderClass(String dispatchOrderClass) { if (StringUtils.isBlank(dispatchOrderClass)) { return null; } try { SysDept query = new SysDept(); query.setDispatchOrderClass(dispatchOrderClass); List depts = sysDeptMapper.selectDeptList(query); if (depts != null && !depts.isEmpty()) { // 返回第一个匹配的部门 return depts.get(0); } } catch (Exception e) { log.error("查询dispatch_order_class='{}' 的部门失败", dispatchOrderClass, e); } return null; } }