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); } }