liujie
2026-03-15 996431875b7f42bdd2e772c847bd6028a20aaf65
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
@@ -324,8 +324,16 @@
        if (Objects.nonNull(evaluate)) {
            vo.setOrderRating(evaluate.getOrderRating());
        }
        //TODO 7.查询mongodb 该订单上传的经纬度轨迹信息
        vo.setOrderPositionList(new ArrayList<>());
        // 7. 查询mongodb 该订单上传的经纬度轨迹信息(按订单id)
        List<OrderTrajectory> trajectories = queryOrderTrajectories(id);
        vo.setOrderPositionList(convertTrajectoriesToPositions(trajectories));
        // 8. 起步价、里程费、时长费、远途费:按订单费用明细聚合
        Map<Integer, BigDecimal> feeMap = sumOrderDetailMoneyByDetailType(id);
        vo.setStartMoney(feeMap.getOrDefault(1, BigDecimal.ZERO));
        vo.setMileageMoney(feeMap.getOrDefault(2, BigDecimal.ZERO));
        vo.setDurationMoney(feeMap.getOrDefault(3, BigDecimal.ZERO));
        vo.setLongDistancemoney(feeMap.getOrDefault(4, BigDecimal.ZERO));
        return vo;
    }
@@ -2489,12 +2497,15 @@
            }
        }
        List<OrderTrajectory> trajectories = mongoTemplate.find(
                new Query(Criteria.where("orderId").is(orderId))
                        .with(Sort.by(Sort.Direction.ASC, "locatetime")),
                OrderTrajectory.class
        );
        List<OrderTrajectory> trajectories = queryOrderTrajectories(orderId);
        orderDetailVo.setTrajectories(trajectories);
        // 起步价、里程费、时长费、远途费:按订单费用明细聚合,覆盖订单表字段
        Map<Integer, BigDecimal> feeMap = sumOrderDetailMoneyByDetailType(orderId);
        orderDetailVo.setStartMoney(feeMap.getOrDefault(1, BigDecimal.ZERO));
        orderDetailVo.setMileageMoney(feeMap.getOrDefault(2, BigDecimal.ZERO));
        orderDetailVo.setDurationMoney(feeMap.getOrDefault(3, BigDecimal.ZERO));
        orderDetailVo.setLongDistancemoney(feeMap.getOrDefault(4, BigDecimal.ZERO));
        if (order.getBoardingTime() != null && order.getTripEnd() != null) {
            // 计算两个时间相差多少分钟
            double exactMinutes = Duration.between(order.getBoardingTime(), order.getTripEnd()).toMillis() / (1000.0 * 60);
@@ -2508,6 +2519,82 @@
        return orderDetailVo;
    }
    /**
     * 查询订单轨迹(mongodb)
     *
     * @param orderId 订单id
     * @return 轨迹列表(按 locatetime 升序)
     */
    private List<OrderTrajectory> queryOrderTrajectories(Long orderId) {
        if (orderId == null) {
            return new ArrayList<>();
        }
        List<OrderTrajectory> trajectories = mongoTemplate.find(
                new Query(Criteria.where("orderId").is(orderId))
                        .with(Sort.by(Sort.Direction.ASC, "locatetime")),
                OrderTrajectory.class
        );
        return trajectories;
    }
    /**
     * 订单费用明细聚合:按 detail_type 汇总 money
     *
     * <p>detail_type:1=起步价 2=里程费 3=时长费 4=远途费</p>
     */
    private Map<Integer, BigDecimal> sumOrderDetailMoneyByDetailType(Long orderId) {
        if (orderId == null) {
            return Collections.emptyMap();
        }
        List<XpOrderDetail> detailList = xpOrderDetailMapper.selectList(
                new LambdaQueryWrapper<XpOrderDetail>()
                        .eq(XpOrderDetail::getOrderId, orderId)
                        .ne(XpOrderDetail::getIsDeleted, true)
        );
        if (CollectionUtils.isEmpty(detailList)) {
            return Collections.emptyMap();
        }
        Map<Integer, BigDecimal> sumMap = new HashMap<>();
        for (XpOrderDetail detail : detailList) {
            if (detail == null || detail.getDetailType() == null) {
                continue;
            }
            BigDecimal money = detail.getMoney() == null ? BigDecimal.ZERO : detail.getMoney();
            sumMap.put(detail.getDetailType(), sumMap.getOrDefault(detail.getDetailType(), BigDecimal.ZERO).add(money));
        }
        return sumMap;
    }
    /**
     * 将轨迹点转换为订单经纬度列表
     */
    private List<XpOrderDetailVO.OrderPosition> convertTrajectoriesToPositions(List<OrderTrajectory> trajectories) {
        if (CollectionUtils.isEmpty(trajectories)) {
            return new ArrayList<>();
        }
        List<XpOrderDetailVO.OrderPosition> positions = new ArrayList<>();
        for (OrderTrajectory trajectory : trajectories) {
            if (trajectory == null || StringUtils.isBlank(trajectory.getLocation())) {
                continue;
            }
            String[] parts = trajectory.getLocation().split(",");
            if (parts.length != 2) {
                continue;
            }
            try {
                double longitude = Double.parseDouble(parts[0].trim());
                double latitude = Double.parseDouble(parts[1].trim());
                XpOrderDetailVO.OrderPosition position = new XpOrderDetailVO.OrderPosition();
                position.setLongitude(longitude);
                position.setLatitude(latitude);
                positions.add(position);
            } catch (Exception e) {
                // ignore invalid point
            }
        }
        return positions;
    }
    @Override
    public R<String> feeDescription(Long orderId, String uid) {
        XpOrder order = this.getById(orderId);