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 com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.xiaopeng.api.dto.vehicleConvoy.VehicleTemperatureDto;
import com.xiaopeng.api.feignClient.order.XpOrderClient;
import com.xiaopeng.api.model.order.XpOrder;
import com.xiaopeng.api.feignClient.maintenance.XpVehiclePreparationClient;
import com.xiaopeng.api.model.query.XpVehiclePreparationPageQuery;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.vo.vehicleConvoy.VehicleTemperatureVo;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicleAnnualRecord;
import com.xiaopeng.api.vo.maintenance.XpVehiclePreparationDetailVO;
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.WebUtils;
import com.xiaopeng.common.core.web.page.PageInfo;
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.vehicleConvoy.service.IXpVehicleAnnualRecordService;
import com.xiaopeng.vehicleConvoy.service.IXpVehicleService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.context.annotation.Lazy;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
*
* 车辆管理 前端控制器
*
*
* @author mitao
* @since 2026-02-03
*/
@Slf4j
@RestController
@Api(tags = "车辆管理")
@RequiredArgsConstructor(onConstructor_ = @Lazy)
public class XpVehicleController {
private final IXpVehicleService xpVehicleService;
private final XpOrderClient xpOrderClient;
private final IXpVehicleAnnualRecordService xpVehicleAnnualRecordService;
private final XpVehiclePreparationClient xpVehiclePreparationClient;
/**
* 根据ID列表批量查询车辆信息(内部接口)
*
* @param ids 车辆ID列表
* @return 车辆列表
*/
@ApiOperation(value = "批量查询车辆信息", tags = {"内部接口"})
@PostMapping("/inner/vehicle/listByIds")
public R> listByIds(@RequestBody List ids) {
if (CollectionUtils.isEmpty(ids)) {
return R.ok(new ArrayList<>());
}
return R.ok(xpVehicleService.listByIds(ids));
}
/**
* 根据ID查询车辆信息(内部接口)
*
* @param id 车辆ID
* @return 车辆列表
*/
@GetMapping("/inner/vehicle/queryById")
public R queryById(Long id) {
return R.ok(xpVehicleService.getById(id));
}
/**
* 修改车辆信息(内部接口)
*
* @param xpVehicle 车辆信息
* @return 车辆
*/
@PostMapping("/inner/vehicle/updateVehicleById")
public R updateVehicleById(@RequestBody XpVehicle xpVehicle){
xpVehicleService.updateById(xpVehicle);
return R.ok();
}
/**
* 新增车辆
*
* @param dto 车辆信息
* @return 操作结果
*/
@ApiOperation(value = "新增车辆", tags = {"管理后台-车辆车队管理-在库车辆管理"})
@PostMapping("/api/v1/vehicle/add")
public R> addVehicle(@Valid @RequestBody VehicleAddDTO dto) {
xpVehicleService.addVehicle(dto);
return R.ok();
}
/**
* 编辑车辆
*
* @param dto 车辆信息
* @return 操作结果
*/
@ApiOperation(value = "编辑车辆", tags = {"管理后台-车辆车队管理-在库车辆管理"})
@PostMapping("/api/v1/vehicle/edit")
public R> editVehicle(@Valid @RequestBody VehicleEditDTO dto) {
xpVehicleService.editVehicle(dto);
return R.ok();
}
/**
* 完善/更新车辆信息(保险、年检、运营资质等)
*
* @param dto 车辆信息
* @return 操作结果
*/
@ApiOperation(value = "完善/更新车辆信息", tags = {"管理后台-车辆车队管理-在库车辆管理"})
@PostMapping("/api/v1/vehicle/improveInfo")
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)
public R> batchOperation(@RequestParam String idStr) {
xpVehicleService.batchOperation(idStr);
return R.ok();
}
/**
* 批量设置运营区域
*
* @param dto 批量设置运营区域参数
* @return 操作结果
*/
@ApiOperation(value = "批量设置运营区域", tags = {"管理后台-车辆车队管理-在库车辆管理"})
@PostMapping("/api/v1/vehicle/batchSetElectronic")
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> vehiclePageList(@RequestBody VehiclePageQuery query) {
return R.ok(xpVehicleService.vehiclePageList(query));
}
/**
* 导入车辆
*
* @param file Excel文件
* @return 操作结果
*/
@ApiOperation(value = "导入", tags = {"管理后台-车辆车队管理-在库车辆管理"})
@PostMapping("/api/v1/vehicle/importExcel")
public R> importExcel(@RequestPart("file") MultipartFile file) {
ImportParams params = new ImportParams();
params.setHeadRows(1);
InputStream inputStream = null;
List importList;
try {
inputStream = file.getInputStream();
importList = ExcelImportUtil.importExcel(inputStream, XpVehicleImportExcel.class, params);
} catch (Exception e) {
log.error("车辆导入失败:{}", e.getMessage(), e);
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);
}
xpVehicleService.importVehicles(importList);
return R.ok();
}
/**
* 导出在库车辆列表
*
* @param query 查询参数
*/
@ApiOperation(value = "导出", tags = {"管理后台-车辆车队管理-在库车辆管理"})
@PostMapping("/api/v1/vehicle/exportExcel")
public void exportExcel(@RequestBody VehicleExportQuery query) {
// 1. 查询导出数据
List dataList = xpVehicleService.vehicleExportList(query);
// 2. 转换为导出对象
List 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")
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 getVehicleDetail(@ApiParam(value = "车辆id", required = true) @RequestParam Long id) {
return R.ok(xpVehicleService.getVehicleDetail(id));
}
/**
* 删除在库车辆
* @param id
* @return
*/
@ApiOperation(value = "删除在库车辆")
@DeleteMapping("/api/v1/vehicle/delete/{id}")
public R> delete(@ApiParam(name = "id", value = "车辆ID") @PathVariable Long id) {
xpVehicleService.removeById(id);
return R.ok();
}
/**
* 运营车辆管理分页列表
*
* @param query 查询参数
* @return 分页结果
*/
@ApiOperation(value = "运营车辆管理分页列表", tags = {"管理后台-车辆车队管理-运营车辆管理"})
@PostMapping("/api/v1/vehicle/operationPageList")
public R> operationPageList(@RequestBody OperationVehiclePageQuery query) {
return R.ok(xpVehicleService.operationPageList(query));
}
/**
* 导出在库车辆列表
*
* @param query 查询参数
*/
@ApiOperation(value = "运营车辆管理列表导出", tags = {"管理后台-车辆车队管理-在库车辆管理"})
@PostMapping("/api/v1/vehicle/operationExportExcel")
public void exportExcel(@RequestBody OperationVehicleExportQuery query) {
// 1. 查询导出数据
List dataList = xpVehicleService.operationVehicleExportList(query);
// 2. 转换为导出对象
List 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);
}
}
}
@ApiOperation(value = "通过车辆id查询年检分页列表", tags = {"管理后台-车辆车队管理-运营车辆管理"})
@PostMapping("/api/v1/vehicle/queryTaskRoutineByVehicleId")
public R> queryTaskRoutineByVehicleId(@RequestBody XpVehicleAnnualRecordPageQuery query){
return R.ok(xpVehicleAnnualRecordService.queryTaskRoutineByVehicleId(query));
}
/**
* 通过车辆id查询整备分页列表
*
* @param query 查询参数
* @return 整备记录分页列表
*/
@ApiOperation(value = "通过车辆id查询整备分页列表", tags = {"管理后台-车辆车队管理-运营车辆管理"})
@PostMapping("/api/v1/vehicle/queryPreparationByVehicleId")
public R> queryPreparationByVehicleId(
@Valid @RequestBody XpVehiclePreparationPageQuery query) {
return xpVehiclePreparationClient.queryByVehicleId(query);
}
/**
* 根据围栏id查询空闲车辆
*
*/
@GetMapping("/inner/vehicle/listByFenceId")
public R> listByFenceId(@RequestParam("fenceId") Long fenceId){
return R.ok(xpVehicleService.listByFenceId(fenceId));
}
/**
* 查询可改派的车辆列表
*
* @return 车辆列表
*/
@ApiOperation(value = "查询可改派的车辆列表", tags = {"管理后台-订单管理"})
@GetMapping("/api/v1/vehicle/availableList")
public R> listAvailableVehicles() {
List list = xpVehicleService.listAvailableVehicles();
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("/api/v1/vehicle/vehicleDetail")
public R vehicleDetail(@RequestParam Long id) {
// 查询车辆
XpVehicle xpVehicle = xpVehicleService.getById(id);
return R.ok(xpVehicle);
}
/**
* 车辆管理-地图
* @return 车辆列表
*/
@ApiOperation(value = "车辆管理-地图", tags = {"运维APP-车辆管理"})
@PostMapping("/api/v1/vehicle/vehicleMap")
public R> vehicleMap(@RequestBody VehicleMapQuery query) {
return R.ok(xpVehicleService.pageList(query));
}
/**
* 根据车牌号查询车辆信息
* @param plateNumber
* @return
*/
@PostMapping("/inner/vehicle/listByPlateNumber")
R> listByPlateNumber(@RequestParam("plateNumber") String plateNumber){
return R.ok(xpVehicleService.listByPlateNumber(plateNumber));
}
/**
* 车辆详情-车门解锁/后备箱解锁
*/
@ApiOperation(value = "车辆运维-车门解锁/后备箱解锁", tags = {"运维APP-车辆管理"})
@PostMapping("/api/v1/vehicle/unlockByType")
public R unlockByType(@RequestBody UnlockByTypeDTO dto) {
// TODO 车门解锁、后备箱解锁
return R.ok();
}
/**
* 业务流程-车门解锁/后备箱解锁
*/
@ApiOperation(value = "打开车门操作", tags = {"小程序-业务流程"})
@PostMapping("/api/v1/order/vehicle/unlock")
public R unlock(@RequestBody UnlockAppletDTO dto) {
return R.ok(xpVehicleService.unlock(dto));
}
/**
* 业务流程-打开设置温度
*/
@ApiOperation(value = "打开设置温度", tags = {"小程序-业务流程"})
@PostMapping("/api/v1/order/ac/set-temperature")
public R setTemperature(@RequestBody SetTemperatureDTO dto) {
return R.ok(xpVehicleService.setTemperature(dto));
}
/**
* 业务流程-通过订单id查询当前车辆温度
*/
@ApiOperation(value = "通过订单id查询当前车辆温度", tags = {"小程序-业务流程"})
@GetMapping("/api/v1/order/queryTemperatureByOrderId")
public R queryTemperatureByOrderId(@RequestParam Long orderId, HttpServletRequest request) {
String uid = request.getHeader("XP-Uid");
VehicleTemperatureDto vehicleTemperatureVo = xpVehicleService.queryTemperatureByOrderId(orderId,uid);
return R.ok(vehicleTemperatureVo);
}
}