puzhibing
2026-03-05 de5f07fe1acd8d462f9c54d7a04c5c47a87264d1
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpVehicleController.java
@@ -16,7 +16,6 @@
import com.xiaopeng.api.feignClient.maintenance.XpTaskClient;
import com.xiaopeng.api.feignClient.maintenance.XpTaskRuleClient;
import com.xiaopeng.api.feignClient.maintenance.XpVehiclePreparationClient;
import com.xiaopeng.api.feignClient.order.XpOrderClient;
import com.xiaopeng.api.model.maintenance.XpTask;
import com.xiaopeng.api.model.maintenance.XpTaskRule;
import com.xiaopeng.api.model.vehicleConvoy.XpFleetVehicle;
@@ -41,9 +40,12 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.openxml4j.exceptions.NotOfficeXmlFileException;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
@@ -51,15 +53,15 @@
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@@ -87,6 +89,7 @@
    private final XpTaskClient xpTaskClient;
    private final XpTaskRuleClient xpTaskRuleClient;
    private final MongoTemplate mongoTemplate;
    private final MessageSource messageSource;
    /**
     * 根据ID列表批量查询车辆信息(内部接口)
     *
@@ -120,10 +123,12 @@
    @GetMapping("/inner/vehicle/queryById")
    public R<XpVehicle> queryById(@RequestParam Long id) {
        XpVehicle xpVehicle = xpVehicleService.getById(id);
        // 获取车队
        XpFleetVehicle xpFleetVehicle = vehicleService.getOne(new LambdaQueryWrapper<XpFleetVehicle>().eq(XpFleetVehicle::getVehicleId, xpVehicle.getId()));
        if (Objects.nonNull(xpFleetVehicle)) {
            xpVehicle.setFleetId(xpFleetVehicle.getFleetId());
        if (Objects.nonNull(xpVehicle)) {
            // 获取车队
            XpFleetVehicle xpFleetVehicle = vehicleService.getOne(new LambdaQueryWrapper<XpFleetVehicle>().eq(XpFleetVehicle::getVehicleId, xpVehicle.getId()));
            if (Objects.nonNull(xpFleetVehicle)) {
                xpVehicle.setFleetId(xpFleetVehicle.getFleetId());
            }
        }
        return R.ok(xpVehicle);
    }
@@ -224,7 +229,7 @@
    @PostMapping("/api/v1/vehicle/importTemplate")
    public void importTemplate() {
        // 1. 查询导出数据
        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), XpVehicleExportExcel.class, new ArrayList<>());
        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), XpVehicleImportExcel.class, new ArrayList<>());
        // 4. 输出到响应流
        HttpServletResponse response = WebUtils.response();
@@ -232,7 +237,7 @@
        response.setCharacterEncoding("utf-8");
        ServletOutputStream outputStream = null;
        try {
            String fileName = URLEncoder.encode("在库车辆导入模板.xls", "utf-8");
            String fileName = URLEncoder.encode("在库车辆导入模板.xlsx", "utf-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName);
            outputStream = response.getOutputStream();
            workbook.write(outputStream);
@@ -266,6 +271,9 @@
            importList = ExcelImportUtil.importExcel(inputStream, XpVehicleImportExcel.class, params);
        } catch (Exception e) {
            log.error("车辆导入失败:{}", e.getMessage(), e);
            if (e instanceof NotOfficeXmlFileException || e.getCause() instanceof NotOfficeXmlFileException) {
                throw new ServiceException("上传文件不是有效的Excel(.xlsx)文件!", I18nKeyConstant.VEHICLE_IMPORT_FAILED);
            }
            throw new ServiceException("车辆导入失败!", I18nKeyConstant.VEHICLE_IMPORT_FAILED);
        } finally {
            if (inputStream != null) {
@@ -279,10 +287,60 @@
        if (CollectionUtils.isEmpty(importList)) {
            throw new ServiceException("导入数据为空!", I18nKeyConstant.VEHICLE_IMPORT_DATA_EMPTY);
        }
        validateImportRequiredFields(importList, params.getHeadRows());
        uploadVehiclePicture(importList);
        xpVehicleService.importVehicles(importList);
        return R.ok();
    }
    private void validateImportRequiredFields(List<XpVehicleImportExcel> importList, int headRows) {
        for (int index = 0; index < importList.size(); index++) {
            XpVehicleImportExcel row = importList.get(index);
            List<String> missingFields = new ArrayList<>();
            addIfBlank(missingFields, row.getVehicleCode(), "vehicle.import.field.vehicleCode");
            addIfBlank(missingFields, row.getVehicleVin(), "vehicle.import.field.vehicleVin");
            addIfBlank(missingFields, row.getPlateNumber(), "vehicle.import.field.plateNumber");
            addIfBlank(missingFields, row.getVehicleModel(), "vehicle.import.field.vehicleModel");
            addIfBlank(missingFields, row.getVehicleColor(), "vehicle.import.field.vehicleColor");
            addIfBlank(missingFields, row.getVehiclePictures(), "vehicle.import.field.vehiclePictures");
            addIfBlank(missingFields, row.getProcurementSource(), "vehicle.import.field.procurementSource");
            if (!missingFields.isEmpty()) {
                int excelRowNumber = index + headRows + 1;
                String missing = String.join(", ", missingFields);
                throw new ServiceException("导入数据必填字段为空!", I18nKeyConstant.VEHICLE_IMPORT_FIELDS_REQUIRED,
                        new Object[]{excelRowNumber, missing});
            }
        }
    }
    private void addIfBlank(List<String> missingFields, String value, String fieldNameKey) {
        if (StringUtils.isBlank(value)) {
            String fieldName = messageSource.getMessage(fieldNameKey, null, fieldNameKey, LocaleContextHolder.getLocale());
            missingFields.add(fieldName);
        }
    }
    private void uploadVehiclePicture(List<XpVehicleImportExcel> importList) {
        for (XpVehicleImportExcel xpVehicleImportExcel : importList) {
            xpVehicleImportExcel.setVehiclePictures(getOssUrl(xpVehicleImportExcel.getVehiclePictures()));
        }
    }
    private String getOssUrl(String filePath) {
        try {
            // 获取到暂存的文件
            File tmpFile = new File(filePath);
            FileInputStream fileInputStream = new FileInputStream(tmpFile);
            // TODO 上传oss
            JSONObject res = new JSONObject();
            res.put("url", "https://we-park-life.oss-cn-beijing.aliyuncs.com/img/K4vqtLmVc6.png");
            res.put("id", "1");
            res.put("name", "测试.png");
            return res.toJSONString();
        } catch (Exception e) {
            log.error("广告物料整体项目结算表导入图片上传oss异常", e);
        }
        return null;
    }
    /**
     * 导出在库车辆列表
     *
@@ -394,7 +452,8 @@
        for (XpVehicleExportExcel xpVehicleExportExcel : exportList) {
            if (StringUtils.isNotBlank(xpVehicleExportExcel.getVehiclePictures())) {
                JSONObject jsonObject = JSONObject.parseObject(xpVehicleExportExcel.getVehiclePictures());
                xpVehicleExportExcel.setVehiclePictures(jsonObject.getString("url"));
                // xpVehicleExportExcel.setVehiclePictures(jsonObject.getString("url"));
                xpVehicleExportExcel.setVehiclePictures(null);
            }
        }
        // 3. 生成Excel
@@ -446,7 +505,7 @@
     */
    @PostMapping("/inner/vehicle/queryVehiclePositionByVin")
    public R<List<String>> queryVehiclePositionByVin(@RequestBody VehiclePositionByVinDto dto){
        List<XpVehicle> list = xpVehicleService.list(new LambdaQueryWrapper<XpVehicle>().eq(XpVehicle::getState, 0).eq(XpVehicle::getStatus, 1).eq(XpVehicle::getElectronicId, dto.getFenceId()).in(XpVehicle::getVehicleVin,
        List<XpVehicle> list = xpVehicleService.list(new LambdaQueryWrapper<XpVehicle>().eq(XpVehicle::getState, 0).eq(XpVehicle::getOperatingStatus, 1).eq(XpVehicle::getElectronicId, dto.getFenceId()).in(XpVehicle::getVehicleVin,
                dto.getVinList()));
        if(list.isEmpty()){
            return R.ok(new ArrayList<>());