package com.xiaopeng.vehicleConvoy.controller;
|
|
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
import cn.afterturn.easypoi.excel.ExcelImportUtil;
|
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
import cn.afterturn.easypoi.excel.entity.ImportParams;
|
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.lang.Validator;
|
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSONArray;
|
import com.alibaba.fastjson2.JSONObject;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import com.mongodb.client.MongoCollection;
|
import com.xiaopeng.api.dto.operation.VehiclePositionByVinDto;
|
import com.xiaopeng.api.dto.vehicleConvoy.ServiceVehicleListDto;
|
import com.xiaopeng.api.dto.vehicleConvoy.UpdateVehicleStateDto;
|
import com.xiaopeng.api.dto.vehicleConvoy.VehicleTemperatureDto;
|
import com.xiaopeng.api.feignClient.maintenance.*;
|
import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient;
|
import com.xiaopeng.api.model.account.XpOperationsUser;import com.xiaopeng.api.model.maintenance.XpTask;
|
import com.xiaopeng.api.model.maintenance.XpTaskRule;
|
import com.xiaopeng.api.model.operation.XpOfficialPartner;
|
import com.xiaopeng.api.model.vehicleConvoy.XpFleet;
|
import com.xiaopeng.api.model.vehicleConvoy.XpFleetVehicle;
|
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
|
import com.xiaopeng.api.model.vehicleConvoy.XpVehicleAnnualRecord;
|
import com.xiaopeng.api.vo.automaticPilot.VehiclePosition;
|
import com.xiaopeng.api.vo.operation.VehiclePositionVo;
|
import com.xiaopeng.api.vo.vehicleConvoy.VehicleDoorStatusVo;
|
import com.xiaopeng.api.vo.vehicleConvoy.VehicleStateVo;
|
import com.xiaopeng.api.vo.vehicleConvoy.VehiclesCommandCallbackVo;
|
import com.xiaopeng.common.core.domain.R;
|
import com.xiaopeng.common.core.exception.ServiceException;
|
import com.xiaopeng.common.core.utils.SensitiveDataCryptoUtil;
|
import com.xiaopeng.common.core.utils.WebUtils;
|
import com.xiaopeng.common.core.web.page.PageInfo;
|
import com.xiaopeng.common.log.annotation.AdminOperationLog;
|
import com.xiaopeng.common.log.enums.AdminBusinessType;
|
import com.xiaopeng.common.log.enums.AdminOperationType;
|
import com.xiaopeng.common.security.service.TokenService;
|
import com.xiaopeng.evi.oss.service.AliOssService;
|
import com.xiaopeng.unifiedverification.interceptor.XpClientCheck;
|
import com.xiaopeng.vehicleConvoy.constant.I18nKeyConstant;
|
import com.xiaopeng.vehicleConvoy.model.dto.*;
|
import com.xiaopeng.vehicleConvoy.model.exportExcel.XpVehicleExportExcel;
|
import com.xiaopeng.vehicleConvoy.model.importExcel.XpVehicleImportExcel;
|
import com.xiaopeng.vehicleConvoy.model.query.*;
|
import com.xiaopeng.api.vo.vehicleConvoy.XpVehicleVO;
|
import com.xiaopeng.vehicleConvoy.model.vo.VehiclePositionDto;
|
import com.xiaopeng.vehicleConvoy.service.IXpFleetService;
|
import com.xiaopeng.vehicleConvoy.service.IXpFleetVehicleService;
|
import com.xiaopeng.vehicleConvoy.service.IXpVehicleAnnualRecordService;
|
import com.xiaopeng.vehicleConvoy.service.IXpVehicleService;
|
import com.xiaopeng.vehicleConvoy.util.AliOssDownloadUtil;
|
import io.swagger.annotations.*;
|
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.bson.Document;
|
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.geo.Distance;
|
import org.springframework.data.geo.Metrics;
|
import org.springframework.data.geo.Point;
|
import org.springframework.data.mongodb.core.MongoTemplate;
|
import org.springframework.data.mongodb.core.query.Criteria;
|
import org.springframework.data.mongodb.core.query.Query;
|
import org.springframework.util.CollectionUtils;
|
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.*;
|
import java.net.URLEncoder;
|
import java.time.LocalDateTime;
|
import java.util.*;
|
import java.util.regex.Pattern;
|
import java.util.stream.Collectors;
|
import com.xiaopeng.common.log.annotation.AdminOperationLog;
|
import com.xiaopeng.common.log.enums.AdminBusinessType;
|
import com.xiaopeng.common.log.enums.AdminOperationType;
|
import java.util.stream.Collectors;
|
|
/**
|
* <p>
|
* 车辆管理 前端控制器
|
* </p>
|
*
|
* @author mitao
|
* @since 2026-02-03
|
*/
|
@Slf4j
|
@RestController
|
@Api(tags = "车辆管理")
|
@RequiredArgsConstructor(onConstructor_ = @Lazy)
|
public class XpVehicleController {
|
|
private static final Pattern VEHICLE_CODE_PATTERN = Pattern.compile("^[A-Za-z0-9_]{1,5}$");
|
private static final Pattern VEHICLE_VIN_PATTERN = Pattern.compile("^[A-Z0-9]{17}$");
|
|
private final IXpVehicleService xpVehicleService;
|
private final IXpFleetVehicleService vehicleService;
|
private final IXpFleetService xpFleetService;
|
private final IXpVehicleAnnualRecordService xpVehicleAnnualRecordService;
|
private final XpVehiclePreparationClient xpVehiclePreparationClient;
|
private final XpChargingRecordClient xpChargingRecordClient;
|
private final XpTaskClient xpTaskClient;
|
private final XpTaskRuleClient xpTaskRuleClient;
|
private final MongoTemplate mongoTemplate;
|
private final MessageSource messageSource;
|
private final TokenService tokenService;
|
private final XpVehicleRepairClient xpVehicleRepairClient;
|
private final AliOssService aliOssService;
|
private final AliOssDownloadUtil aliOssDownloadUtil;
|
|
/**
|
* 根据ID列表批量查询车辆信息(内部接口)
|
*
|
* @param ids 车辆ID列表
|
* @return 车辆列表
|
*/
|
@ApiOperation(value = "批量查询车辆信息", tags = {"内部接口"})
|
@PostMapping("/logan/inner/vehicle/listByIds")
|
public R<List<XpVehicle>> listByIds(@RequestBody List<Long> ids) {
|
if (CollectionUtils.isEmpty(ids)) {
|
return R.ok(new ArrayList<>());
|
}
|
return R.ok(xpVehicleService.listByIds(ids));
|
}
|
|
/**
|
* 批量获取车辆列表
|
*
|
* @return 车辆列表
|
*/
|
@ApiOperation(value = "批量查询车辆信息", tags = {"内部接口"})
|
@PostMapping("/logan/inner/vehicle/listVehicle")
|
public R<List<XpVehicle>> listVehicle() {
|
return R.ok(xpVehicleService.list());
|
}
|
|
/**
|
* 根据ID查询车辆信息(内部接口)
|
*
|
* @param id 车辆ID
|
* @return 车辆列表
|
*/
|
@GetMapping("/logan/inner/vehicle/queryById")
|
public R<XpVehicle> queryById(@RequestParam Long id) throws UnsupportedEncodingException {
|
XpVehicle xpVehicle = xpVehicleService.getById(id);
|
if (Objects.nonNull(xpVehicle)) {
|
|
String vehiclePictures = xpVehicle.getVehiclePictures();
|
if (vehiclePictures != null) {
|
JSONObject jsonObject = JSON.parseObject(vehiclePictures);
|
// 1
|
// String downloadUrl = aliOssService.getDownloadUrl(jsonObject.getString("id"), jsonObject.getString("name"), true);
|
// jsonObject.put("url", downloadUrl);
|
jsonObject.put("url", "");
|
xpVehicle.setVehiclePictures(jsonObject.toJSONString());
|
}
|
|
// 获取车队
|
XpFleetVehicle xpFleetVehicle = vehicleService.getOne(new LambdaQueryWrapper<XpFleetVehicle>().eq(XpFleetVehicle::getVehicleId, xpVehicle.getId()));
|
if (Objects.nonNull(xpFleetVehicle)) {
|
xpVehicle.setFleetId(xpFleetVehicle.getFleetId());
|
}
|
}
|
return R.ok(xpVehicle);
|
}
|
|
/**
|
* 修改车辆信息(内部接口)
|
*
|
* @param xpVehicle 车辆信息
|
* @return 车辆
|
*/
|
@PostMapping("/logan/inner/vehicle/updateVehicleById")
|
public R<String> updateVehicleById(@RequestBody XpVehicle xpVehicle) {
|
xpVehicleService.updateById(xpVehicle);
|
return R.ok();
|
}
|
|
/**
|
* 新增车辆
|
*
|
* @param dto 车辆信息
|
* @return 操作结果
|
*/
|
@ApiOperation(value = "新增车辆", tags = {"管理后台-车辆管理-在库车辆管理"})
|
@PostMapping("/api/v1/vehicle/add")
|
@AdminOperationLog(
|
businessType = AdminBusinessType.STOCK_VEHICLE_MANAGEMENT,
|
operationType = AdminOperationType.ADD,
|
content = "新增车辆",
|
appendRequestData = true
|
)
|
public R<?> addVehicle(@Valid @RequestBody VehicleAddDTO dto) {
|
xpVehicleService.addVehicle(dto, null);
|
return R.ok();
|
}
|
|
/**
|
* 编辑车辆
|
*
|
* @param dto 车辆信息
|
* @return 操作结果
|
*/
|
@ApiOperation(value = "编辑车辆", tags = {"管理后台-车辆管理-在库车辆管理"})
|
@PostMapping("/api/v1/vehicle/edit")
|
@AdminOperationLog(
|
businessType = AdminBusinessType.STOCK_VEHICLE_MANAGEMENT,
|
operationType = AdminOperationType.EDIT,
|
content = "编辑车辆",
|
appendRequestData = true
|
)
|
public R<?> editVehicle(@Valid @RequestBody VehicleEditDTO dto) {
|
xpVehicleService.editVehicle(dto, null);
|
return R.ok();
|
}
|
|
/**
|
* 完善/更新车辆信息(保险、年检、运营资质等)
|
*
|
* @param dto 车辆信息
|
* @return 操作结果
|
*/
|
@ApiOperation(value = "完善/更新车辆信息", tags = {"管理后台-车辆管理-在库车辆管理"})
|
@PostMapping("/api/v1/vehicle/improveInfo")
|
@AdminOperationLog(
|
businessType = AdminBusinessType.STOCK_VEHICLE_MANAGEMENT,
|
operationType = AdminOperationType.EDIT,
|
content = "完善/更新车辆信息",
|
appendRequestData = true
|
)
|
public R<?> improveInfo(@RequestBody VehicleImproveInfoDTO dto) {
|
xpVehicleService.improveInfo(dto);
|
return R.ok();
|
}
|
|
/**
|
* 批量运营(在库→运营)
|
*
|
* @param idStr 车辆ID字符串列表
|
* @return 操作结果
|
*/
|
@ApiOperation(value = "批量运营", tags = {"管理后台-车辆管理-在库车辆管理"})
|
@PostMapping("/api/v1/vehicle/batchOperation")
|
@ApiImplicitParam(name = "idStr", value = "车辆ID字符串列表,逗号分隔", required = true, dataTypeClass = String.class)
|
@AdminOperationLog(
|
businessType = AdminBusinessType.STOCK_VEHICLE_MANAGEMENT,
|
operationType = AdminOperationType.EDIT,
|
contentExpression = "'批量运营车辆,ids=' + #p0",
|
appendRequestData = false
|
)
|
public R<?> batchOperation(@RequestParam String idStr) {
|
xpVehicleService.batchOperation(idStr);
|
return R.ok();
|
}
|
|
/**
|
* 批量设置运营区域
|
*
|
* @param dto 批量设置运营区域参数
|
* @return 操作结果
|
*/
|
@ApiOperation(value = "批量设置运营区域", tags = {"管理后台-车辆管理-在库车辆管理"})
|
@PostMapping("/api/v1/vehicle/batchSetElectronic")
|
@AdminOperationLog(
|
businessType = AdminBusinessType.STOCK_VEHICLE_MANAGEMENT,
|
operationType = AdminOperationType.EDIT,
|
content = "批量设置运营区域",
|
appendRequestData = true
|
)
|
public R<?> batchSetElectronic(@Valid @RequestBody VehicleBatchSetElectronicDTO dto) {
|
xpVehicleService.batchSetElectronic(dto.getIds(), dto.getElectronicId());
|
return R.ok();
|
}
|
|
/**
|
* 在库车辆管理分页列表
|
*
|
* @param query 查询参数
|
* @return 分页结果
|
*/
|
@ApiOperation(value = "在库车辆管理分页列表", tags = {"管理后台-车辆管理-在库车辆管理"})
|
@PostMapping("/api/v1/vehicle/pageList")
|
public R<PageInfo<XpVehicle>> vehiclePageList(@RequestBody VehiclePageQuery query) {
|
return R.ok(xpVehicleService.vehiclePageList(query));
|
}
|
|
/**
|
* 导出在库车辆列表
|
*
|
*/
|
@ApiOperation(value = "下载导入模板", tags = {"管理后台-车辆管理-在库车辆管理"})
|
@PostMapping("/api/v1/vehicle/importTemplate")
|
@AdminOperationLog(
|
businessType = AdminBusinessType.STOCK_VEHICLE_MANAGEMENT,
|
operationType = AdminOperationType.EXPORT,
|
content = "下载车辆导入模板",
|
appendRequestData = false
|
)
|
public void importTemplate() {
|
// 1. 查询导出数据
|
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), XpVehicleImportExcel.class, new ArrayList<>());
|
|
// 4. 输出到响应流
|
HttpServletResponse response = WebUtils.response();
|
response.setContentType("application/vnd.ms-excel");
|
response.setCharacterEncoding("utf-8");
|
ServletOutputStream outputStream = null;
|
try {
|
String fileName = URLEncoder.encode("在库车辆导入模板.xlsx", "utf-8");
|
response.setHeader("Content-disposition", "attachment;filename=" + fileName);
|
outputStream = response.getOutputStream();
|
workbook.write(outputStream);
|
} catch (IOException e) {
|
log.error("下载在库车辆导入模板失败", e);
|
} finally {
|
try {
|
if (outputStream != null) {
|
outputStream.close();
|
}
|
} catch (IOException e) {
|
log.error("关闭输出流失败", e);
|
}
|
}
|
}
|
|
/**
|
* 导入车辆
|
*
|
* @param file Excel文件
|
* @return 操作结果
|
*/
|
@ApiOperation(value = "导入", tags = {"管理后台-车辆管理-在库车辆管理"})
|
@PostMapping("/api/v1/vehicle/importExcel")
|
@AdminOperationLog(
|
businessType = AdminBusinessType.STOCK_VEHICLE_MANAGEMENT,
|
operationType = AdminOperationType.IMPORT,
|
content = "导入车辆",
|
appendRequestData = false
|
)
|
public R<?> importExcel(@RequestParam("file") MultipartFile file) {
|
ImportParams params = new ImportParams();
|
params.setHeadRows(1);
|
InputStream inputStream = null;
|
List<XpVehicleImportExcel> importList;
|
try {
|
inputStream = file.getInputStream();
|
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) {
|
try {
|
inputStream.close();
|
} catch (IOException e) {
|
log.error("关闭输入流失败", e);
|
}
|
}
|
}
|
if (CollectionUtils.isEmpty(importList)) {
|
throw new ServiceException("导入数据为空!", I18nKeyConstant.VEHICLE_IMPORT_DATA_EMPTY);
|
}
|
validateImportRequiredFields(importList, params.getHeadRows());
|
validateImportBusinessFields(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.tip");
|
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 validateImportBusinessFields(List<XpVehicleImportExcel> importList, int headRows) {
|
List<String> errors = new ArrayList<>();
|
Locale locale = LocaleContextHolder.getLocale();
|
|
for (int index = 0; index < importList.size(); index++) {
|
XpVehicleImportExcel row = importList.get(index);
|
int excelRowNumber = index + headRows + 1;
|
|
String vehicleCode = trimToNull(row.getVehicleCode());
|
String vehicleVin = normalizeVin(row.getVehicleVin());
|
String plateNumber = trimToNull(row.getPlateNumber());
|
String vehicleColor = trimToNull(row.getVehicleColor());
|
|
row.setVehicleCode(vehicleCode);
|
row.setVehicleVin(vehicleVin);
|
row.setPlateNumber(plateNumber);
|
row.setVehicleColor(vehicleColor);
|
|
if (org.apache.commons.lang3.StringUtils.isNotBlank(vehicleCode) && !VEHICLE_CODE_PATTERN.matcher(vehicleCode).matches()) {
|
errors.add(messageSource.getMessage(I18nKeyConstant.VEHICLE_IMPORT_CODE_INVALID,
|
new Object[]{excelRowNumber, vehicleCode},
|
I18nKeyConstant.VEHICLE_IMPORT_CODE_INVALID,
|
locale));
|
}
|
if (org.apache.commons.lang3.StringUtils.isNotBlank(vehicleVin) && !VEHICLE_VIN_PATTERN.matcher(vehicleVin).matches()) {
|
errors.add(messageSource.getMessage(I18nKeyConstant.VEHICLE_IMPORT_VIN_INVALID,
|
new Object[]{excelRowNumber, vehicleVin},
|
I18nKeyConstant.VEHICLE_IMPORT_VIN_INVALID,
|
locale));
|
}
|
if (org.apache.commons.lang3.StringUtils.isNotBlank(plateNumber) && !Validator.isPlateNumber(plateNumber)) {
|
errors.add(messageSource.getMessage(I18nKeyConstant.VEHICLE_IMPORT_PLATE_INVALID,
|
new Object[]{excelRowNumber, plateNumber},
|
I18nKeyConstant.VEHICLE_IMPORT_PLATE_INVALID,
|
locale));
|
}
|
if (org.apache.commons.lang3.StringUtils.isNotBlank(vehicleColor) && vehicleColor.length() > 3) {
|
errors.add(messageSource.getMessage(I18nKeyConstant.VEHICLE_IMPORT_COLOR_INVALID,
|
new Object[]{excelRowNumber, vehicleColor},
|
I18nKeyConstant.VEHICLE_IMPORT_COLOR_INVALID,
|
locale));
|
}
|
}
|
|
Set<String> duplicatedCodes = findDuplicated(importList.stream()
|
.map(XpVehicleImportExcel::getVehicleCode)
|
.filter(org.apache.commons.lang3.StringUtils::isNotBlank)
|
.collect(java.util.stream.Collectors.toList()));
|
Set<String> duplicatedVins = findDuplicated(importList.stream()
|
.map(XpVehicleImportExcel::getVehicleVin)
|
.filter(org.apache.commons.lang3.StringUtils::isNotBlank)
|
.collect(java.util.stream.Collectors.toList()));
|
Set<String> duplicatedPlates = findDuplicated(importList.stream()
|
.map(XpVehicleImportExcel::getPlateNumber)
|
.filter(org.apache.commons.lang3.StringUtils::isNotBlank)
|
.collect(java.util.stream.Collectors.toList()));
|
|
for (int index = 0; index < importList.size(); index++) {
|
XpVehicleImportExcel row = importList.get(index);
|
int excelRowNumber = index + headRows + 1;
|
if (duplicatedCodes.contains(row.getVehicleCode())) {
|
errors.add(messageSource.getMessage(I18nKeyConstant.VEHICLE_IMPORT_CODE_DUPLICATE,
|
new Object[]{excelRowNumber, row.getVehicleCode()},
|
I18nKeyConstant.VEHICLE_IMPORT_CODE_DUPLICATE,
|
locale));
|
}
|
if (duplicatedVins.contains(row.getVehicleVin())) {
|
errors.add(messageSource.getMessage(I18nKeyConstant.VEHICLE_IMPORT_VIN_DUPLICATE,
|
new Object[]{excelRowNumber, row.getVehicleVin()},
|
I18nKeyConstant.VEHICLE_IMPORT_VIN_DUPLICATE,
|
locale));
|
}
|
if (duplicatedPlates.contains(row.getPlateNumber())) {
|
errors.add(messageSource.getMessage(I18nKeyConstant.VEHICLE_IMPORT_PLATE_DUPLICATE,
|
new Object[]{excelRowNumber, row.getPlateNumber()},
|
I18nKeyConstant.VEHICLE_IMPORT_PLATE_DUPLICATE,
|
locale));
|
}
|
}
|
|
Set<String> codeSet = importList.stream()
|
.map(XpVehicleImportExcel::getVehicleCode)
|
.filter(org.apache.commons.lang3.StringUtils::isNotBlank)
|
.collect(java.util.stream.Collectors.toSet());
|
Set<String> vinSet = importList.stream()
|
.map(XpVehicleImportExcel::getVehicleVin)
|
.filter(org.apache.commons.lang3.StringUtils::isNotBlank)
|
.collect(java.util.stream.Collectors.toSet());
|
Set<String> plateSet = importList.stream()
|
.map(XpVehicleImportExcel::getPlateNumber)
|
.filter(org.apache.commons.lang3.StringUtils::isNotBlank)
|
.collect(java.util.stream.Collectors.toSet());
|
|
Set<String> existsCodes = Collections.emptySet();
|
if (!codeSet.isEmpty()) {
|
existsCodes = xpVehicleService.lambdaQuery()
|
.select(XpVehicle::getVehicleCode)
|
.in(XpVehicle::getVehicleCode, codeSet)
|
.list()
|
.stream()
|
.map(XpVehicle::getVehicleCode)
|
.filter(org.apache.commons.lang3.StringUtils::isNotBlank)
|
.collect(java.util.stream.Collectors.toSet());
|
}
|
Set<String> existsVins = Collections.emptySet();
|
if (!vinSet.isEmpty()) {
|
Set<String> vinQueryValues = vinSet.stream()
|
.flatMap(vin -> SensitiveDataCryptoUtil.queryValues(vin).stream())
|
.collect(java.util.stream.Collectors.toSet());
|
existsVins = xpVehicleService.lambdaQuery()
|
.select(XpVehicle::getVehicleVin)
|
.in(XpVehicle::getVehicleVin, buildVinQueryValues(vinSet))
|
.list()
|
.stream()
|
.map(XpVehicle::getVehicleVin)
|
.map(SensitiveDataCryptoUtil::decryptIfPossible)
|
.filter(org.apache.commons.lang3.StringUtils::isNotBlank)
|
.collect(java.util.stream.Collectors.toSet());
|
}
|
Set<String> existsPlates = Collections.emptySet();
|
if (!plateSet.isEmpty()) {
|
existsPlates = xpVehicleService.lambdaQuery()
|
.select(XpVehicle::getPlateNumber)
|
.in(XpVehicle::getPlateNumber, plateSet)
|
.list()
|
.stream()
|
.map(XpVehicle::getPlateNumber)
|
.filter(org.apache.commons.lang3.StringUtils::isNotBlank)
|
.collect(java.util.stream.Collectors.toSet());
|
}
|
|
for (int index = 0; index < importList.size(); index++) {
|
XpVehicleImportExcel row = importList.get(index);
|
int excelRowNumber = index + headRows + 1;
|
if (existsCodes.contains(row.getVehicleCode())) {
|
errors.add(messageSource.getMessage(I18nKeyConstant.VEHICLE_IMPORT_CODE_EXISTS,
|
new Object[]{excelRowNumber, row.getVehicleCode()},
|
I18nKeyConstant.VEHICLE_IMPORT_CODE_EXISTS,
|
locale));
|
}
|
if (existsVins.contains(row.getVehicleVin())) {
|
errors.add(messageSource.getMessage(I18nKeyConstant.VEHICLE_IMPORT_VIN_EXISTS,
|
new Object[]{excelRowNumber, row.getVehicleVin()},
|
I18nKeyConstant.VEHICLE_IMPORT_VIN_EXISTS,
|
locale));
|
}
|
if (existsPlates.contains(row.getPlateNumber())) {
|
errors.add(messageSource.getMessage(I18nKeyConstant.VEHICLE_IMPORT_PLATE_EXISTS,
|
new Object[]{excelRowNumber, row.getPlateNumber()},
|
I18nKeyConstant.VEHICLE_IMPORT_PLATE_EXISTS,
|
locale));
|
}
|
}
|
|
if (!errors.isEmpty()) {
|
throw new ServiceException("导入校验失败!", I18nKeyConstant.VEHICLE_IMPORT_VALIDATE_FAIL,
|
new Object[]{String.join("\n", errors)});
|
}
|
}
|
|
private static String normalizeVin(String vin) {
|
String trimmed = trimToNull(vin);
|
return trimmed == null ? null : trimmed.toUpperCase(Locale.ROOT);
|
}
|
|
private static String trimToNull(String value) {
|
if (value == null) {
|
return null;
|
}
|
String trimmed = value.trim();
|
return trimmed.isEmpty() ? null : trimmed;
|
}
|
|
private static Set<String> findDuplicated(List<String> values) {
|
if (values == null || values.isEmpty()) {
|
return Collections.emptySet();
|
}
|
Set<String> seen = new HashSet<>();
|
Set<String> duplicated = new HashSet<>();
|
for (String value : values) {
|
if (!seen.add(value)) {
|
duplicated.add(value);
|
}
|
}
|
return duplicated;
|
}
|
|
private static List<String> buildVinQueryValues(Iterable<String> vins) {
|
if (vins == null) {
|
return Collections.emptyList();
|
}
|
List<String> values = new ArrayList<>();
|
for (String vin : vins) {
|
values.addAll(SensitiveDataCryptoUtil.queryValues(vin));
|
}
|
return values.stream().distinct().collect(Collectors.toList());
|
}
|
|
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;
|
}
|
|
/**
|
* 导出在库车辆列表
|
*
|
* @param query 查询参数
|
*/
|
@ApiOperation(value = "导出", tags = {"管理后台-车辆管理-在库车辆管理"})
|
@PostMapping("/api/v1/vehicle/exportExcel")
|
@AdminOperationLog(
|
businessType = AdminBusinessType.STOCK_VEHICLE_MANAGEMENT,
|
operationType = AdminOperationType.EXPORT,
|
content = "导出在库车辆",
|
appendRequestData = true
|
)
|
public void exportExcel(@RequestBody VehicleExportQuery query) {
|
// 1. 查询导出数据
|
List<XpVehicle> dataList = xpVehicleService.vehicleExportList(query);
|
|
// 2. 转换为导出对象
|
List<XpVehicleExportExcel> exportList = BeanUtil.copyToList(dataList, XpVehicleExportExcel.class);
|
for (XpVehicleExportExcel xpVehicleExportExcel : exportList) {
|
if (StringUtils.isNotBlank(xpVehicleExportExcel.getVehiclePictures())) {
|
JSONObject jsonObject = JSONObject.parseObject(xpVehicleExportExcel.getVehiclePictures());
|
xpVehicleExportExcel.setVehiclePictures(jsonObject.getString("url"));
|
}
|
}
|
// 3. 生成Excel
|
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), XpVehicleExportExcel.class, exportList);
|
|
// 4. 输出到响应流
|
HttpServletResponse response = WebUtils.response();
|
response.setContentType("application/vnd.ms-excel");
|
response.setCharacterEncoding("utf-8");
|
ServletOutputStream outputStream = null;
|
try {
|
String fileName = URLEncoder.encode("在库车辆列表.xls", "utf-8");
|
response.setHeader("Content-disposition", "attachment;filename=" + fileName);
|
outputStream = response.getOutputStream();
|
workbook.write(outputStream);
|
} catch (IOException e) {
|
log.error("导出在库车辆列表失败", e);
|
} finally {
|
try {
|
if (outputStream != null) {
|
outputStream.close();
|
}
|
} catch (IOException e) {
|
log.error("关闭输出流失败", e);
|
}
|
}
|
}
|
|
/**
|
* 批量在库(运营→在库)
|
*
|
* @param idStr 车辆ID列表
|
* @return 操作结果
|
*/
|
@ApiOperation(value = "批量在库", tags = {"管理后台-车辆管理-运营车辆管理"})
|
@ApiImplicitParam(name = "idStr", value = "车辆ID字符串列表,逗号分隔", required = true, dataTypeClass = String.class)
|
@PostMapping("/api/v1/vehicle/batchStock")
|
@AdminOperationLog(
|
businessType = AdminBusinessType.OPERATION_VEHICLE_MANAGEMENT,
|
operationType = AdminOperationType.EDIT,
|
contentExpression = "'批量在库车辆,ids=' + #p0",
|
appendRequestData = false
|
)
|
public R<?> batchStock(@RequestParam String idStr) {
|
xpVehicleService.batchStock(idStr);
|
return R.ok();
|
}
|
|
/**
|
* 车辆详情(含围栏名称)
|
*
|
* @param id 车辆ID
|
* @return 车辆详情
|
*/
|
@ApiOperation(value = "车辆详情", tags = {"管理后台-车辆管理-在库车辆管理"})
|
@GetMapping("/api/v1/vehicle/queryById")
|
public R<XpVehicle> getVehicleDetail(@ApiParam(value = "车辆id", required = true) @RequestParam Long id) throws UnsupportedEncodingException {
|
XpVehicle vehicleDetail = xpVehicleService.getVehicleDetail(id);
|
if (vehicleDetail.getVehiclePictures() != null) {
|
JSONObject jsonObject = JSONObject.parseObject(vehicleDetail.getVehiclePictures());
|
String downloadUrl = aliOssService.getDownloadUrl(jsonObject.getString("id"), jsonObject.getString("name"), true);
|
jsonObject.put("url", downloadUrl);
|
String jsonString = jsonObject.toJSONString();
|
vehicleDetail.setVehiclePictures(jsonString);
|
}
|
return R.ok(vehicleDetail);
|
}
|
|
/**
|
* 删除在库车辆
|
*
|
* @param id
|
* @return
|
*/
|
@ApiOperation(value = "删除在库车辆", tags = {"管理后台-车辆管理-在库车辆管理"})
|
@DeleteMapping("/api/v1/vehicle/delete/{id}")
|
@AdminOperationLog(
|
businessType = AdminBusinessType.STOCK_VEHICLE_MANAGEMENT,
|
operationType = AdminOperationType.DELETE,
|
contentExpression = "'删除在库车辆,id=' + #p0",
|
appendRequestData = false
|
)
|
public R<?> delete(@ApiParam(name = "id", value = "车辆ID") @PathVariable Long id) {
|
XpFleetVehicle binding = vehicleService.lambdaQuery()
|
.eq(XpFleetVehicle::getVehicleId, id)
|
.last("limit 1")
|
.one();
|
if (binding != null && binding.getFleetId() != null) {
|
String fleetName = String.valueOf(binding.getFleetId());
|
try {
|
XpFleet fleet = xpFleetService.getById(binding.getFleetId());
|
if (fleet != null && StringUtils.isNotBlank(fleet.getFleetName())) {
|
fleetName = fleet.getFleetName();
|
}
|
} catch (Exception e) {
|
// ignore, fallback to fleetId
|
}
|
throw new ServiceException("当前车辆已关联车队:" + fleetName, I18nKeyConstant.VEHICLE_DELETE_HAS_BOUND_FLEET,
|
new Object[]{fleetName});
|
}
|
xpVehicleService.removeById(id);
|
return R.ok();
|
}
|
|
/**
|
* 运营车辆管理分页列表
|
*
|
* @param query 查询参数
|
* @return 分页结果
|
*/
|
@ApiOperation(value = "运营车辆管理分页列表", tags = {"管理后台-车辆管理-运营车辆管理"})
|
@PostMapping("/api/v1/vehicle/operationPageList")
|
public R<PageInfo<XpVehicle>> operationPageList(@RequestBody OperationVehiclePageQuery query) {
|
return R.ok(xpVehicleService.operationPageList(query));
|
}
|
|
/**
|
* 导出在库车辆列表
|
*
|
* @param query 查询参数
|
*/
|
@ApiOperation(value = "运营车辆管理列表导出", tags = {"管理后台-车辆管理-运营车辆管理"})
|
@PostMapping("/api/v1/vehicle/operationExportExcel")
|
@AdminOperationLog(
|
businessType = AdminBusinessType.OPERATION_VEHICLE_MANAGEMENT,
|
operationType = AdminOperationType.EXPORT,
|
content = "导出运营车辆",
|
appendRequestData = true
|
)
|
public void exportExcel(@RequestBody OperationVehicleExportQuery query) {
|
// 1. 查询导出数据
|
List<XpVehicle> dataList = xpVehicleService.operationVehicleExportList(query);
|
|
// 2. 转换为导出对象
|
List<XpVehicleExportExcel> exportList = BeanUtil.copyToList(dataList, XpVehicleExportExcel.class);
|
for (XpVehicleExportExcel xpVehicleExportExcel : exportList) {
|
if (StringUtils.isNotBlank(xpVehicleExportExcel.getVehiclePictures())) {
|
|
String pictureJSONObject = aliOssDownloadUtil.getPictureJSONObject(xpVehicleExportExcel.getVehiclePictures());
|
if (StringUtils.isNotBlank(pictureJSONObject)) {
|
JSONObject jsonObject = JSONObject.parseObject(pictureJSONObject);
|
xpVehicleExportExcel.setVehiclePictures(jsonObject.containsKey("url") ? jsonObject.getString("url") : "");
|
}
|
}
|
if (Integer.valueOf(2).equals(xpVehicleExportExcel.getStatus()) && Integer.valueOf(1).equals(xpVehicleExportExcel.getOperatingStatus())) {
|
xpVehicleExportExcel.setStatus(4);
|
}
|
}
|
// 3. 生成Excel
|
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), XpVehicleExportExcel.class, exportList);
|
|
// 4. 输出到响应流
|
HttpServletResponse response = WebUtils.response();
|
response.setContentType("application/vnd.ms-excel");
|
response.setCharacterEncoding("utf-8");
|
ServletOutputStream outputStream = null;
|
try {
|
String fileName = URLEncoder.encode("运营车辆列表.xls", "utf-8");
|
response.setHeader("Content-disposition", "attachment;filename=" + fileName);
|
outputStream = response.getOutputStream();
|
workbook.write(outputStream);
|
} catch (IOException e) {
|
log.error("导出在库车辆列表失败", e);
|
} finally {
|
try {
|
if (outputStream != null) {
|
outputStream.close();
|
}
|
} catch (IOException e) {
|
log.error("关闭输出流失败", e);
|
}
|
}
|
}
|
|
@ApiOperation(value = "通过车辆id查询年检分页列表", tags = {"管理后台-车辆管理-运营车辆管理"})
|
@PostMapping("/api/v1/vehicle/queryTaskRoutineByVehicleId")
|
public R<PageInfo<XpVehicleAnnualRecord>> queryTaskRoutineByVehicleId(
|
@Valid @RequestBody XpVehicleAnnualRecordPageQuery query) throws UnsupportedEncodingException {
|
return R.ok(xpVehicleAnnualRecordService.queryTaskRoutineByVehicleId(query));
|
}
|
|
|
|
|
/**
|
* 根据围栏id查询空闲车辆
|
*
|
*/
|
@GetMapping("/logan/inner/vehicle/listByFenceId")
|
public R<List<XpVehicle>> listByFenceId(@RequestParam("fenceId") Long fenceId) {
|
return R.ok(xpVehicleService.listByFenceId(fenceId));
|
}
|
|
@GetMapping("/logan/inner/vehicle/listAllByFenceId")
|
public R<List<XpVehicle>> listAllByFenceId(@RequestParam("fenceId") Long fenceId) {
|
return R.ok(xpVehicleService.listAllByFenceId(fenceId));
|
}
|
|
/**
|
* 查询车辆位置信息 做筛选
|
*
|
* @param dto
|
* @return
|
*/
|
@PostMapping("/logan/inner/vehicle/queryVehiclePositionByVin")
|
public R<List<String>> queryVehiclePositionByVin(@RequestBody VehiclePositionByVinDto dto){
|
List<XpVehicle> list = xpVehicleService.list(new LambdaQueryWrapper<XpVehicle>().eq(XpVehicle::getState, Optional.ofNullable(dto.getStatus()).orElse(0))
|
.eq(XpVehicle::getOperatingStatus, 1).eq(XpVehicle::getElectronicId, dto.getFenceId()).in(XpVehicle::getVehicleVin, buildVinQueryValues(dto.getVinList())));
|
if (list.isEmpty()) {
|
return R.ok(new ArrayList<>());
|
} else {
|
List<String> vehiclePositionVos = new ArrayList<>(list.size());
|
for (XpVehicle xpVehicle : list) {
|
vehiclePositionVos.add(xpVehicle.getVehicleVin());
|
}
|
return R.ok(vehiclePositionVos);
|
}
|
|
}
|
|
|
/**
|
* 查询车辆信息
|
*
|
* @param vehicleVin
|
* @return
|
*/
|
@GetMapping("/logan/inner/vehicle/findByVehicleVin")
|
public R<XpVehicle> findByVehicleVin(@RequestParam("vehicleVin") String vehicleVin){
|
XpVehicle xpVehicle = xpVehicleService.getOne(new LambdaQueryWrapper<XpVehicle>().in(XpVehicle::getVehicleVin, SensitiveDataCryptoUtil.queryValues(vehicleVin)));
|
|
// 获取车队
|
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);
|
}
|
|
|
/**
|
* 根据XPUID查询车辆信息
|
*
|
* @param xpuid
|
* @return
|
*/
|
@GetMapping("/logan/inner/vehicle/findByVehicleXpuId")
|
public R<XpVehicle> findByVehicleXpuId(@RequestParam("xpuid") String xpuid) {
|
XpVehicle xpVehicle = xpVehicleService.getOne(new LambdaQueryWrapper<XpVehicle>().eq(XpVehicle::getXpuId, xpuid));
|
return R.ok(xpVehicle);
|
}
|
|
/**
|
* 修改车辆状态
|
*
|
* @param updateVehicleStateDto
|
* @return
|
*/
|
@PostMapping("/logan/inner/vehicle/updateVehicleStatus")
|
public R<?> updateVehicleStatus(@RequestBody UpdateVehicleStateDto updateVehicleStateDto) {
|
if (StringUtils.isBlank(updateVehicleStateDto.getVin())) {
|
return R.ok();
|
}
|
xpVehicleService.update(new LambdaUpdateWrapper<XpVehicle>().in(XpVehicle::getVehicleVin, SensitiveDataCryptoUtil.queryValues(updateVehicleStateDto.getVin())).set(XpVehicle::getState, updateVehicleStateDto.getState()));
|
return R.ok();
|
}
|
|
/**
|
*
|
* 查询车辆所属车队ID
|
*
|
* @param vehicleId
|
* @return
|
*/
|
@GetMapping("/logan/inner/vehicle/findFleetIdByVehicleId")
|
public R<Long> findFleetIdByVehicleId(@RequestParam Long vehicleId) {
|
XpFleetVehicle xpFleetVehicle = vehicleService.getOne(new LambdaQueryWrapper<XpFleetVehicle>().eq(XpFleetVehicle::getVehicleId, vehicleId));
|
return R.ok(xpFleetVehicle.getFleetId());
|
}
|
|
/**
|
* 查询可改派的车辆列表
|
*
|
* @return 车辆列表
|
*/
|
@ApiOperation(value = "查询可改派的车辆列表", tags = {"管理后台-订单管理"})
|
@GetMapping("/api/v1/vehicle/availableList")
|
@ApiImplicitParams({
|
@ApiImplicitParam(name = "orderId", value = "订单ID", required = true, dataTypeClass = Long.class),
|
@ApiImplicitParam(name = "orderType", value = "订单类型(1=用户单,2=测试单)", required = true, dataTypeClass = Integer.class)
|
})
|
public R<List<XpVehicleVO>> listAvailableVehicles(@RequestParam Long orderId, Integer orderType, String plateNumber, String fleetName) {
|
List<XpVehicleVO> list = xpVehicleService.listAvailableVehicles(orderId, orderType,plateNumber,fleetName);
|
return R.ok(list);
|
}
|
|
/**
|
* 车辆控制消息回调通知
|
* 开关门、设定温度
|
*
|
* @param callbackVo
|
*/
|
@PostMapping("/base/vehicles/command/callback")
|
public void vehiclesCommandCallback(@RequestBody VehiclesCommandCallbackVo callbackVo) {
|
log.info("车辆控制消息回调:{}", JSON.toJSONString(callbackVo));
|
if (null != callbackVo.getMsg_ref()) {
|
//继续执行业务逻辑上的代码
|
}
|
}
|
|
/**
|
* 车辆详情-车辆调度-接单、测试
|
*/
|
@ApiOperation(value = "车辆详情", tags = {"运维APP-车辆管理"})
|
@PostMapping("/maintenance-app/api/v1/vehicle/vehicleDetail")
|
public R<XpVehicleVO> vehicleDetail(@RequestParam Long id) {
|
// 查询车辆
|
XpVehicle xpVehicle = xpVehicleService.getById(id);
|
XpVehicleVO xpVehicleVO = new XpVehicleVO();
|
BeanUtils.copyProperties(xpVehicle, xpVehicleVO);
|
// 查询运维规则 保养周期
|
XpTaskRule xpTaskRule = xpTaskRuleClient.queryDetail().getData();
|
if (Objects.isNull(xpTaskRule)) {
|
return R.ok(xpVehicleVO);
|
}
|
Boolean maintenanceCycle = xpTaskRule.getMaintenanceCycle();
|
Integer maintenanceCycleTime = xpTaskRule.getMaintenanceCycleTime();
|
Integer maintenanceCycleTimeType = xpTaskRule.getMaintenanceCycleTimeType();
|
if (maintenanceCycle) {
|
// 查询车辆上次保养记录
|
XpTask xpTask = xpTaskClient.queryInfoByVehicleId(id).getData();
|
if (Objects.nonNull(xpTask)) {
|
// 存在保养记录
|
LocalDateTime handleTime = xpTask.getCreateTime();
|
switch (maintenanceCycleTimeType) {
|
case 1:
|
handleTime.plusDays(maintenanceCycleTime);
|
break;
|
default:
|
handleTime.plusMonths(maintenanceCycleTime);
|
break;
|
}
|
xpVehicleVO.setNextMaintenanceTime(handleTime.toLocalDate());
|
} else {
|
// 没有保养记录
|
// 入库时间
|
LocalDateTime warehousingTime = xpVehicle.getWarehousingTime();
|
if (Objects.nonNull(warehousingTime)) {
|
switch (maintenanceCycleTimeType) {
|
case 1:
|
warehousingTime.plusDays(maintenanceCycleTime);
|
break;
|
default:
|
warehousingTime.plusMonths(maintenanceCycleTime);
|
break;
|
}
|
xpVehicleVO.setNextMaintenanceTime(warehousingTime.toLocalDate());
|
}
|
}
|
}
|
// 查询车辆的续航里程
|
VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(xpVehicleVO.getVehicleVin())), VehiclePosition.class);
|
if (Objects.nonNull(vehiclePosition)) {
|
xpVehicleVO.setMileageRange(vehiclePosition.getMileageRange());
|
xpVehicleVO.setCurrentElectricity(vehiclePosition.getCurrentElectricity());
|
} else {
|
xpVehicleVO.setMileageRange(0F);
|
xpVehicleVO.setCurrentElectricity(0);
|
}
|
if (StringUtils.isNotBlank(xpVehicleVO.getVehiclePictures())) {
|
JSONObject jsonObject = JSONObject.parseObject(xpVehicleVO.getVehiclePictures());
|
if(jsonObject!=null){
|
String downloadUrl = null;
|
try {
|
downloadUrl= aliOssService.getDownloadUrl(jsonObject.getString("id"), jsonObject.getString("name"), true);
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
jsonObject.put("url", downloadUrl);
|
xpVehicleVO.setVehiclePictures(jsonObject.toJSONString());
|
}
|
}
|
// 判断车辆维修状态
|
Integer maintenanceStatus = xpVehicleRepairClient.getMaintenanceStatus(xpVehicleVO.getId()).getData();
|
xpVehicleVO.setMaintenanceStatus(maintenanceStatus);
|
return R.ok(xpVehicleVO);
|
}
|
|
/**
|
* 车辆管理-地图
|
*
|
* @return 车辆列表
|
*/
|
@ApiOperation(value = "车辆管理-地图", tags = {"运维APP-车辆管理"})
|
@PostMapping("/maintenance-app/api/v1/vehicle/vehicleMap")
|
public R<PageInfo<XpVehicleVO>> vehicleMap(@RequestBody VehicleMapQuery query) {
|
Long operationsUserId = tokenService.getLoginOperationUser().getId();
|
query.setOperationsUserId(operationsUserId);
|
return R.ok(xpVehicleService.pageList(query));
|
}
|
|
/**
|
* 根据车牌号查询车辆信息
|
*
|
* @param plateNumber
|
* @return
|
*/
|
@PostMapping("/logan/inner/vehicle/listByPlateNumber")
|
R<List<XpVehicle>> listByPlateNumber(@RequestParam("plateNumber") String plateNumber) {
|
return R.ok(xpVehicleService.listByPlateNumber(plateNumber));
|
}
|
|
/**
|
* 车辆详情-车门解锁/后备箱解锁
|
*/
|
@ApiOperation(value = "车辆运维-车门解锁/后备箱解锁", tags = {"运维APP-车辆管理"})
|
@PostMapping("/maintenance-app/api/v1/vehicle/unlockByType")
|
public R<String> unlockByType(@RequestBody UnlockByTypeDTO dto) {
|
|
// TODO 车门解锁、后备箱解锁
|
|
return R.ok();
|
}
|
|
/**
|
* 业务流程-车门解锁/后备箱解锁
|
*/
|
@ApiOperation(value = "打开车门解锁/后备箱开关车门", tags = {"小程序-业务流程"})
|
@PostMapping("/api/v1/mini-program/order/vehicle/unlock")
|
@XpClientCheck(checkToken = false, checkOtpToken = true)
|
public R<Integer> unlock(@RequestBody UnlockAppletDTO dto) {
|
return R.ok(xpVehicleService.unlock(dto));
|
}
|
|
/**
|
* 业务流程-打开设置温度
|
*/
|
@ApiOperation(value = "打开设置温度", tags = {"小程序-业务流程"})
|
@PostMapping("/api/v1/mini-program/order/ac/set-temperature")
|
@XpClientCheck(checkToken = false, checkOtpToken = true)
|
public R<Integer> setTemperature(@RequestBody SetTemperatureDTO dto) {
|
return R.ok(xpVehicleService.setTemperature(dto));
|
}
|
|
/**
|
* 业务流程-通过订单id查询当前车辆温度
|
*/
|
@ApiOperation(value = "通过订单id查询当前车辆温度", tags = {"小程序-业务流程"})
|
@GetMapping("/api/v1/mini-program/order/queryTemperatureByOrderId")
|
@XpClientCheck(checkToken = false, checkOtpToken = true)
|
public R<String> queryTemperatureByOrderId(@RequestParam Long orderId, HttpServletRequest request) {
|
String uid = request.getHeader("XP-Uid");
|
// VehicleTemperatureDto vehicleTemperatureDto = xpVehicleService.queryTemperatureByOrderId(orderId, uid);
|
// VehicleStateVo hvacInnerTemp = vehicleTemperatureDto.getStateMap().get("hvacInnerTemp");
|
// if(null == hvacInnerTemp){
|
// return R.fail("查询车内温度失败");
|
// }
|
// return R.ok(hvacInnerTemp.getValue());
|
return R.ok("35.0");
|
}
|
|
|
|
@ApiOperation(value = "通过订单id查询当前车辆车门状态", tags = {"小程序-业务流程"})
|
@GetMapping("/api/v1/mini-program/order/queryVehicleTrunkOpenStatus")
|
public R<VehicleTemperatureDto> queryVehicleTrunkOpenStatus(@RequestParam Long orderId, HttpServletRequest request) {
|
String uid = request.getHeader("XP-Uid");
|
VehicleTemperatureDto vehicleTemperatureDto = xpVehicleService.queryTemperatureByOrderId(orderId,uid);
|
return R.ok(vehicleTemperatureDto);
|
}
|
|
|
/**
|
* 获取车辆不分页列表
|
*
|
* @param query
|
* @return
|
*/
|
@ApiOperation(value = "获取车辆分页列表", tags = {"管理后台-车队管理"})
|
@PostMapping("/api/v1/vehicle/page-list")
|
public R<PageInfo<XpVehicleVO>> getVehiclePageList(@RequestBody VehicleSelectPageQuery query) {
|
return R.ok(xpVehicleService.getVehiclePageList(query));
|
}
|
|
|
/**
|
* 临时用于修改车辆接单状态
|
*
|
* @param updateVehicleStateDto
|
* @return
|
*/
|
public R<?> testUpdateVehicleStatus(@RequestBody UpdateVehicleStateDto updateVehicleStateDto) {
|
if (StringUtils.isBlank(updateVehicleStateDto.getVin())) {
|
return R.ok();
|
}
|
xpVehicleService.update(new LambdaUpdateWrapper<XpVehicle>().in(XpVehicle::getVehicleVin, SensitiveDataCryptoUtil.queryValues(updateVehicleStateDto.getVin())).set(XpVehicle::getState, updateVehicleStateDto.getState()));
|
return R.ok();
|
}
|
|
|
/**
|
* 删除mongodb中的文档
|
*
|
* @param collectionName
|
* @return
|
*/
|
@PostMapping("/base/vi/removeMongodb")
|
public R<?> removeMongodb(String collectionName) {
|
MongoCollection<Document> collection = mongoTemplate.getCollection(collectionName);
|
collection.drop();
|
return R.ok();
|
}
|
|
|
/**
|
* 获取车辆后备箱开关状态
|
*
|
* @param uid
|
* @param id
|
* @return
|
*/
|
@PostMapping("/logan/inner/vi/vehicle/getVehicleTrunkOpenStatus")
|
public R<Boolean> getVehicleTrunkOpenStatus(@RequestParam("uid") Long uid, @RequestParam("id") Long id) {
|
Boolean vehicleTrunkOpenStatus = xpVehicleService.getVehicleTrunkOpenStatus(String.valueOf(uid), id);
|
return R.ok(vehicleTrunkOpenStatus);
|
}
|
|
|
|
|
|
/**
|
* 分页获取运营车辆列表
|
* @param dto
|
* @return
|
*/
|
@PostMapping("/logan/inner/vehicle/getServiceVehicleList")
|
public R<List<XpVehicle>> getServiceVehicleList(@RequestBody ServiceVehicleListDto dto){
|
return R.ok(xpVehicleService.getServiceVehicleList(dto));
|
}
|
|
|
|
|
/**
|
* 业务流程-车门解锁/后备箱解锁
|
*/
|
@ApiOperation(value = "打开车门解锁/后备箱开关车门", tags = {"运维APP-车辆管理"})
|
@PostMapping("/maintenance-app/api/v1/vehicle/unlockDoor")
|
public R<Integer> unlockDoor(@RequestBody UnlockAppDTO dto) {
|
XpOperationsUser xpOperationsUser = tokenService.getLoginOperationUser().getXpOperationsUser();
|
return R.ok(xpVehicleService.unlockDoor(dto, xpOperationsUser));
|
}
|
|
|
|
@ApiOperation(value = "通过订单id查询当前车辆空调状态", tags = {"小程序-业务流程"})
|
@GetMapping("/api/v1/mini-program/order/queryVehicleAirConditionerSwitch")
|
@XpClientCheck(checkToken = false, checkOtpToken = true)
|
public R<Boolean> queryVehicleAirConditionerSwitch(@RequestParam Long orderId, HttpServletRequest request) {
|
String uid = request.getHeader("XP-Uid");
|
Boolean hasKey = xpVehicleService.queryVehicleAirConditionerSwitch(orderId, uid);
|
return R.ok(hasKey);
|
}
|
|
|
/**
|
* 业务流程-车门解锁/后备箱解锁
|
*/
|
@ApiOperation(value = "打开/关闭车内空调", tags = {"小程序-业务流程"})
|
@PostMapping("/api/v1/mini-program/order/airConditionerUnlock")
|
@XpClientCheck(checkToken = false, checkOtpToken = true)
|
public R<Integer> airConditionerUnlock(@RequestBody AirConditionerUnlockDTO dto, HttpServletRequest request) {
|
String uid = request.getHeader("XP-Uid");
|
return R.ok(xpVehicleService.airConditionerUnlock(dto, uid));
|
}
|
|
/**
|
* 根据订单id查询四门三盖状态
|
* @param orderId
|
* @return
|
*/
|
@GetMapping("/logan/inner/vehicle/getVehicleDoorStatus/{orderId}")
|
public R<VehicleDoorStatusVo> getVehicleDoorStatus(@PathVariable Long orderId){
|
VehicleDoorStatusVo vehicleDoorStatus = xpVehicleService.getVehicleDoorStatus(orderId);
|
return R.ok(vehicleDoorStatus);
|
}
|
|
/**
|
* 周围车辆点位查询
|
*/
|
@ApiOperation(value = "周围车辆点位查询", notes = "", tags = {"小程序-周围车辆点位查询"})
|
@GetMapping("/api/v1/mini-program/vehicle/nearby")
|
@XpClientCheck(checkToken = false, checkOtpToken = false)
|
public R<List<XpVehicleVO>> carAround(@RequestParam double lon, @RequestParam double lat) {
|
|
Point point = new Point(lon, lat);
|
Distance distance = new Distance(3, Metrics.KILOMETERS);
|
Criteria criteria = Criteria.where("point")
|
.nearSphere(point)
|
.maxDistance(distance.getNormalizedValue());
|
Query query = new Query(criteria);
|
List<VehiclePositionVo> vehiclePositions = mongoTemplate.find(query, VehiclePositionVo.class);
|
if (CollectionUtils.isEmpty(vehiclePositions)) {
|
return R.ok(new ArrayList<>());
|
}
|
List<XpVehicleVO> xpVehicleList = vehiclePositions.stream()
|
.sorted(Comparator.comparingDouble(VehiclePositionVo::getDistance))
|
.map(vp -> {
|
XpVehicle xpVehicle = xpVehicleService.getOne(new LambdaQueryWrapper<XpVehicle>().in(XpVehicle::getVehicleVin, SensitiveDataCryptoUtil.queryValues(vp.getVin())));
|
if (xpVehicle == null) {
|
return null;
|
}
|
XpVehicleVO vo = new XpVehicleVO();
|
BeanUtils.copyProperties(xpVehicle, vo);
|
vo.setDirection(vp.getCourse());
|
return vo;
|
})
|
.filter(Objects::nonNull)
|
.filter(v -> v.getState() != null && v.getState() == 0)
|
.limit(5)
|
.collect(Collectors.toList());
|
return R.ok(xpVehicleList);
|
}
|
|
|
|
@ApiOperation(value = "新增车辆", tags = {"流量接入-基础信息"})
|
@PostMapping("/drainage/v1/vehicle/addVehicle")
|
@ApiImplicitParams({
|
@ApiImplicitParam(value = "token", name = "token", required = true, paramType = "header")
|
})
|
public R<XpVehicle> addOfficialPartnerVehicle(@Valid @RequestBody VehicleAddDTO dto) {
|
XpOfficialPartner officialPartner = tokenService.getOfficialPartner();
|
XpVehicle vehicle = xpVehicleService.addVehicle(dto, officialPartner.getId());
|
return R.ok(vehicle);
|
}
|
|
|
|
@PostMapping("/drainage/v1/vehicle/editVehicle")
|
@ApiOperation(value = "编辑车辆", tags = {"流量接入-基础信息"})
|
@ApiImplicitParams({
|
@ApiImplicitParam(value = "token", name = "token", required = true, paramType = "header")
|
})
|
public R<?> editOfficialPartnerVehicle(@Valid @RequestBody VehicleEditDTO dto) {
|
XpOfficialPartner officialPartner = tokenService.getOfficialPartner();
|
xpVehicleService.editVehicle(dto, officialPartner.getId());
|
return R.ok();
|
}
|
|
|
/**
|
* 上报车辆实时位置信息
|
* @param dto
|
* @return
|
*/
|
@PostMapping("/drainage/v1/vehicle/reportVehicleLocation")
|
@ApiOperation(value = "上报车辆实时位置信息", notes = "流量接入-基础信息")
|
@ApiImplicitParams({
|
@ApiImplicitParam(value = "token", name = "token", required = true, paramType = "header")
|
})
|
public R<?> reportVehicleLocation(@RequestBody VehiclePositionDto dto){
|
XpOfficialPartner officialPartner = tokenService.getOfficialPartner();
|
xpVehicleService.reportVehicleLocation(dto, officialPartner.getId());
|
return R.ok();
|
}
|
|
|
|
/**
|
* 根据车牌号查询数据
|
* @param plateNumber
|
* @param officialPartnerId
|
* @return
|
*/
|
@PostMapping("/logan/inner/vehicle/getVehicleByPlateNumber")
|
public R<XpVehicle> getVehicleByPlateNumber(@RequestParam("plateNumber") String plateNumber,
|
@RequestParam("officialPartnerId") Integer officialPartnerId){
|
XpVehicle vehicle = xpVehicleService.getOne(new LambdaQueryWrapper<XpVehicle>().eq(XpVehicle::getPlateNumber, plateNumber).eq(XpVehicle::getOfficialPartnerId, officialPartnerId));
|
return R.ok(vehicle);
|
}
|
|
private List<String> buildVinQueryValues(Set<String> vinList) {
|
if (vinList == null || vinList.isEmpty()) {
|
return java.util.Collections.emptyList();
|
}
|
return vinList.stream()
|
.flatMap(vin -> SensitiveDataCryptoUtil.queryValues(vin).stream())
|
.distinct()
|
.collect(Collectors.toList());
|
}
|
}
|