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<VehicleSyncDTO> 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<String, String> 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<String, Object> 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<VehicleInfo> 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<SysDept> 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;
|
}
|
}
|