package com.xiaopeng.order.controller; import cn.afterturn.easypoi.excel.ExcelExportUtil; import cn.afterturn.easypoi.excel.entity.ExportParams; import cn.hutool.core.bean.BeanUtil; import com.alibaba.fastjson2.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.xiaopeng.api.dto.QueryOrderRouteDTO; import com.xiaopeng.api.dto.operation.LonLatDto; import com.xiaopeng.api.dto.order.GetOrderNumDto; import com.xiaopeng.api.dto.order.PopOrderDto; import com.xiaopeng.api.dto.statistics.OrderStatisticsDTO; import com.xiaopeng.api.dto.statistics.StatisticsQueryDTO; import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient; import com.xiaopeng.api.model.order.XpOrder; import com.xiaopeng.api.model.vehicleConvoy.XpVehicle; import com.xiaopeng.api.vo.automaticPilot.VehiclePosition; import com.xiaopeng.api.vo.operation.RouteVo; import com.xiaopeng.api.vo.order.*; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.utils.WebUtils; import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.common.redis.service.RedisService; import com.xiaopeng.order.mangodb.model.OrderTrajectory; import com.xiaopeng.order.model.dto.XpOrderCommentDto; import com.xiaopeng.order.model.dto.XpOrderOperateDTO; import com.xiaopeng.order.model.dto.XpOrderPayDto; import com.xiaopeng.order.model.dto.XpOrderReassignDTO; import com.xiaopeng.order.model.exportExcel.XpOrderExportExcel; import com.xiaopeng.order.model.query.XpHistoryOrderListQuery; import com.xiaopeng.order.model.query.XpOrderExcelQuery; import com.xiaopeng.order.model.query.XpOrderPageQuery; import com.xiaopeng.order.model.query.XpTestOrderPageQuery; import com.xiaopeng.order.model.vo.*; import com.xiaopeng.order.service.IXpOrderService; import com.xiaopeng.order.service.IXpTestOrderService; import com.xiaopeng.order.vo.OrderDetailVo; import com.xiaopeng.unifiedverification.interceptor.XpClientCheck; import io.swagger.annotations.*; import lombok.RequiredArgsConstructor; import org.apache.poi.ss.usermodel.Workbook; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.data.domain.Sort; 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.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.math.BigDecimal; import java.math.RoundingMode; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** *

* 订单 前端控制器 *

* * @author mitao * @since 2026-02-03 */ @RestController @Api(tags = "测试订单") @RequiredArgsConstructor(onConstructor_ = @Lazy) public class XpTestOrderController { private final IXpTestOrderService xpTestOrderService; private final RedisService redisService; @Autowired private MongoTemplate mongoTemplate; @Autowired private XpVehicleClient xpVehicleClient; /** * 订单分页列表 * * @param query 分页查询参数 * @return 分页结果 */ @ApiOperation(value = "订单分页列表", tags = {"管理后台-测试计划"}) @PostMapping("/api/v1/testOrder/pageList") public R> pageList(@Validated @RequestBody XpTestOrderPageQuery query) { PageInfo pageInfo = xpTestOrderService.pageList(query); return R.ok(pageInfo); } /** * 订单详情 * * @param id 订单ID * @return 订单详情 */ @ApiOperation(value = "订单详情", tags = {"管理后台-测试计划"}) @GetMapping("/api/v1/order/queryById") public R queryById(@ApiParam(value = "订单id", required = true) @RequestParam Long id) { XpTestOrderDetailVO detail = xpTestOrderService.getOrderDetail(id); return R.ok(detail); } /** * 删除订单 * * @param id 订单ID * @return 操作结果 */ @ApiOperation(value = "删除订单", tags = {"管理后台-测试计划"}) @DeleteMapping("/api/v1/order/deleteById") public R deleteById(@ApiParam(value = "订单id", required = true) @RequestParam Long id) { xpTestOrderService.deleteOrder(id); return R.ok(); } /** * 取消/关闭订单 * * @param dto 操作请求参数 * @return 操作结果 */ @ApiOperation(value = "取消/关闭订单", tags = {"管理后台-测试计划"}) @PostMapping("/api/v1/order/cancelAndCloseById") public R cancelAndCloseById(@Validated @RequestBody XpOrderOperateDTO dto) { xpTestOrderService.cancelOrCloseOrder(dto.getOrderId(), dto.getType()); return R.ok(); } /** * 改派订单 * * @param dto 改派请求参数 * @return 操作结果 */ @ApiOperation(value = "改派订单", tags = {"管理后台-交易管理-订单管理"}, notes = "车辆列表在vehicleConvoy服务") @PostMapping("/api/v1/order/reassignById") public R reassignById(@Validated @RequestBody XpOrderReassignDTO dto) { xpOrderService.reassignOrder( dto.getOrderId(), dto.getVehicleId(), dto.getReassignReason() ); return R.ok(); } @ApiOperation(value = "订单改价", tags = {"管理后台-交易管理-订单管理"}) @PostMapping("/api/v1/order/changeAmount") @ApiImplicitParams({ @ApiImplicitParam(name = "id", value = "订单ID", required = true, dataType = "Long"), @ApiImplicitParam(name = "amount", value = "新的订单金额", required = true, dataType = "BigDecimal") }) public R changeAmount(@RequestParam("id") Long id, @RequestParam("amount") BigDecimal amount) { xpOrderService.changeAmount(id, amount); return R.ok(); } /** * 获取用户快捷胶囊 历史 时段 终点高点 */ @ApiOperation(value = "获取用户快捷胶囊 历史 时段 终点高点", tags = {"小程序-获取用户快捷胶囊 历史 时段 终点高点"}) @GetMapping("/api/v1/mini-program/order/getUserQuickCapsule") @XpClientCheck(checkToken = false, checkOtpToken = true) public R getUserQuickCapsule(HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); return R.ok(xpOrderService.getUserQuickCapsule(uid)); } /** * 获取订单详情 */ @PutMapping("/api/v1/mini-program/order/orderDetail/{orderId}") @ApiOperation(value = "获取订单详情", tags = {"小程序-获取订单详情"}) @XpClientCheck(checkToken = false, checkOtpToken = true) public R orderDetail(@PathVariable("orderId") Long orderId, HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); OrderDetailVo orderDetailVo = xpOrderService.orderDetail(orderId, uid); BigDecimal orderMoney = orderDetailVo.getOrderMoney(); if(orderMoney==null){ orderDetailVo.setOrderMoneyStr("0.00"); }else { orderDetailVo.setOrderMoneyStr(orderMoney.setScale(2, RoundingMode.HALF_UP).toString()); } return R.ok(orderDetailVo); } /** * 获取历史下单成功起点10条数据列表 */ @ApiOperation(value = "获取历史下单成功起点10条数据列表", tags = {"小程序-获取历史下单成功起点10条数据列表"}) @GetMapping("/base/v1/mini-program/history/startPoints") @XpClientCheck(checkToken = false, checkOtpToken = true) public R> getHistoryStartPoints(double lon, double lat,Long electronicAreaId, HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); return R.ok(xpOrderService.getHistoryStartPoints(uid, lon, lat,electronicAreaId)); } /** * 获取历史下单成功终点点10条数据列表 */ @ApiOperation(value = "获取历史下单成功终点10条数据列表", tags = {"小程序-获取历史下单成功终点10条数据列表"}) @GetMapping("/base/v1/mini-program/history/endPoints") @XpClientCheck(checkToken = false, checkOtpToken = true) public R> getHistoryEndPoints(double lon, double lat,Long electronicAreaId, HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); return R.ok(xpOrderService.getHistoryEndPoints(uid, lon, lat,electronicAreaId)); } /** * 获取正在进行中的订单 */ @ApiOperation(value = "获取正在进行中的订单", tags = {"小程序-获取正在进行中的订单"}) @GetMapping("/api/v1/mini-program/order/active") @XpClientCheck(checkToken = false, checkOtpToken = true) public R getActiveOrder(HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); return R.ok(xpOrderService.getActiveOrder(uid)); } /** * 查询历史订单列表 */ @ApiOperation(value = "查询历史订单列表", tags = {"小程序-查询历史订单列表"}) @PostMapping("/api/v1/mini-program/order/history/list") @XpClientCheck(checkToken = false, checkOtpToken = true) public R getHistoryOrderList(@RequestBody XpHistoryOrderListQuery query, HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); return R.ok(xpOrderService.getHistoryOrderList(query, uid)); } /** * + * 取消订单 */ @PutMapping("/api/v1/mini-program/order/cancel/{orderId}") @ApiOperation(value = "取消订单", tags = {"小程序-取消订单"}) @XpClientCheck(checkToken = false, checkOtpToken = true) public R cancelOrder(@PathVariable("orderId") Long orderId, HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); xpOrderService.cancelOrder(orderId, uid); return R.ok(); } /** * + * 手动结束订单 */ @PutMapping("/api/v1/mini-program/order/endTrip/{orderId}") @ApiOperation(value = "结束行程", tags = {"小程序-结束行程"}) @XpClientCheck(checkToken = false, checkOtpToken = true) public R endTrip(@PathVariable("orderId") Long orderId, HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); try { Boolean b = xpOrderService.endTrip(orderId, uid); return R.ok(b); } catch (Exception e) { return R.ok(); } } /** * + * 获取行程费用明细 */ @PutMapping("/api/v1/mini-program/order/fare-breakdown/{orderId}") @ApiOperation(value = "获取行程费用明细", tags = {"小程序-获取行程费用明细"}) @XpClientCheck(checkToken = false, checkOtpToken = true) public R fareBreakdown(@PathVariable("orderId") Long orderId, HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); return xpOrderService.fareBreakdown(orderId, uid); } /** * + * 获取行程费用明细 */ @PutMapping("/api/v1/mini-program/order/feeDescription/{orderId}") @ApiOperation(value = "获取费用说明", tags = {"小程序-获取费用说明"}) @XpClientCheck(checkToken = false, checkOtpToken = true) public R feeDescription(@PathVariable("orderId") Long orderId, HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); return xpOrderService.feeDescription(orderId, uid); } /** * 订单评价 */ @PostMapping("/api/v1/mini-program/order/payment") @ApiOperation(value = "发起支付", tags = {"小程序-发起支付"}) @XpClientCheck(checkToken = false, checkOtpToken = true) public R payment(@Validated @RequestBody XpOrderPayDto dto, HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); return xpOrderService.payment(dto, uid); } /** * 订单评价 */ @PostMapping("/api/v1/mini-program/order/comment") @ApiOperation(value = "订单评价", tags = {"小程序-订单评价"}) @XpClientCheck(checkToken = false, checkOtpToken = true) public R comment(@Validated @RequestBody XpOrderCommentDto dto, HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); xpOrderService.comment(dto, uid); return R.ok(); } /** * 订单状态修改-车控消息推送我方调用(内部接口) */ @ApiOperation(value = "订单状态推送修改") @PostMapping("/inner/v1/order/updateOrderStatus") public R updateOrderStatus(@RequestParam Long orderId, @RequestParam Integer status) { return xpOrderService.updateOrderStatus(orderId, status); } /** * 业务流程-通过订单id查询车辆信息 */ @ApiOperation(value = "通过订单id查询车辆信息", tags = {"小程序-业务流程"}) @XpClientCheck(checkToken = false, checkOtpToken = true) @GetMapping("/api/v1/mini-program/order/queryVehicleByOrderId") public R queryVehicleByOrderId(@RequestParam Long orderId, HttpServletRequest request) { String uid = request.getHeader("XP-Uid"); return R.ok(xpOrderService.queryVehicleByOrderId(orderId, uid)); } /** * 订单车辆定位实时存储-订单车辆定位实时存储(内部接口) */ @ApiOperation(value = "订单车辆定位实时存储") @PostMapping("/inner/v1/order/saveVehicleLocation") public R saveVehicleLocation(@RequestBody OrderTrajectoryVo vo) { OrderTrajectory orderTrajectory = new OrderTrajectory(); BeanUtils.copyProperties(vo, orderTrajectory); xpOrderService.saveVehicleLocation(orderTrajectory); return R.ok(); } /** * 订单查询实时轨迹路线 */ @ApiOperation(value = "订单查询实时轨迹路线") @PostMapping("/api/v1/mini-program/order/queryOrderRoute") public R queryOrderRoute(@Validated @RequestBody QueryOrderRouteDTO dto, HttpServletRequest request) { String uid = request.getHeader("XP-Uid"); // 查询订单信息 XpOrder xpOrder = xpOrderService.getById(dto.getOrderId()); // 获取路线规划 // RouteVo routeVo = redisService.getCacheObject(CacheConstants.ORDER_ROUTE_CAPTURE + "_" + dto.getOrderId() + "_" +dto.getRouteType()); String key = ""; //接驾情况,获取车辆位置到起点的导航 if (xpOrder.getStatus() < 5) { key = "ORDER_NAVIGATION_START_DATA:" + xpOrder.getAppUserId(); } //服务中,获取起点到终点的导航数据 if (xpOrder.getStatus() >= 5) { key = "ORDER_NAVIGATION_END_DATA:" + xpOrder.getAppUserId(); } Object cacheObject = redisService.getCacheObject(key); RouteVo routeVo = JSON.parseObject(cacheObject.toString(), RouteVo.class); XpVehicle xpVehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData(); VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class); routeVo.setDirection(null != vehiclePosition ? vehiclePosition.getCourse() : 90); return R.ok(routeVo); } /** * 订单查询轨迹路线 */ @ApiOperation(value = "订单查询轨迹路线") @GetMapping("/api/v1/mini-program/order/queryOrderTrajectory") public R queryOrderTrajectory(@RequestParam String orderId, HttpServletRequest request) { String uid = request.getHeader("XP-Uid"); List trajectories = mongoTemplate.find( new Query(Criteria.where("orderId").is(Long.valueOf(orderId))) .with(Sort.by(Sort.Direction.ASC, "locatetime")), OrderTrajectory.class ); // 封装信息 RouteVo routeVo = new RouteVo(); List polyline = new ArrayList<>(); if(!CollectionUtils.isEmpty(trajectories)){ for (OrderTrajectory trajectory : trajectories) { LonLatDto lonLatDto = new LonLatDto(); String[] split = trajectory.getLocation().split(","); lonLatDto.setLongitude(Double.valueOf(split[0])); lonLatDto.setLatitude(Double.valueOf(split[1])); polyline.add(lonLatDto); } } routeVo.setPolyline(polyline); return R.ok(routeVo); } }