wlzboy
2025-10-26 2c86a8bd60deed0dd0e044bad6fb83f75d19a332
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleSyncServiceImpl.java
New file
@@ -0,0 +1,319 @@
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;
    }
}