From fa93c9eefcbfcb7ba8b7a9d0b41ba2b4e3523ae5 Mon Sep 17 00:00:00 2001
From: xuhy <3313886187@qq.com>
Date: 星期三, 22 四月 2026 11:07:23 +0800
Subject: [PATCH] [fix] 胶囊改进

---
 xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java |   57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 57 insertions(+), 0 deletions(-)

diff --git a/xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java b/xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
index 154beb7..ddbdef1 100644
--- a/xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
+++ b/xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
@@ -31,6 +31,7 @@
 import com.xiaopeng.api.dto.vehicleConvoy.BaseVehicleUserDto;
 import com.xiaopeng.api.feignClient.account.SysGroupMenuClient;
 import com.xiaopeng.api.feignClient.account.UserResourcesClient;
+import com.xiaopeng.api.feignClient.account.XpAppUserCollectAddrClient;
 import com.xiaopeng.api.feignClient.account.XpAppUserCouponClient;
 import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient;
 import com.xiaopeng.api.feignClient.automaticPilot.VehicleBuriedPointClient;
@@ -49,6 +50,7 @@
 import com.xiaopeng.api.vo.automaticPilot.VehiclePosition;
 import com.xiaopeng.api.vo.automaticPilot.protobuf.OrderOperationType;
 import com.xiaopeng.api.vo.automaticPilot.protobuf.OrderStatus;
+import com.xiaopeng.api.vo.operation.NearestNextVo;
 import com.xiaopeng.api.vo.operation.RouteVo;
 import com.xiaopeng.api.vo.order.*;
 import com.xiaopeng.api.vo.vehicleConvoy.AddTaxiPassengerVo;
@@ -96,6 +98,8 @@
 import lombok.extern.slf4j.Slf4j;
 import org.apache.shardingsphere.transaction.annotation.ShardingSphereTransactionType;
 import org.apache.shardingsphere.transaction.core.TransactionType;
+import org.gavaghan.geodesy.Ellipsoid;
+import org.gavaghan.geodesy.GlobalCoordinates;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
@@ -1311,6 +1315,59 @@
         return null;
     }
 
+    @Resource
+    private XpAppUserCollectAddrClient xpAppUserCollectAddrClient;
+    @Override
+    public NearestNextVo quickCapsule(String uid, Long startPointId) {
+
+        Long userId = Long.valueOf(uid);
+        // - 新用户处理: 历史订单数 < 3单或无匹配数据时,隐藏该胶囊。
+        Long validHistoryCount = this.baseMapper.countUserValidHistoryOrders(userId);
+        if (validHistoryCount == null || validHistoryCount < 3) return null;
+
+        LocalDateTime now = LocalDateTime.now();
+        LocalTime startMoment = now.minusHours(1).toLocalTime();
+        LocalTime endMoment = now.plusHours(1).toLocalTime();
+        LocalDate startDate = now.minusMonths(1).toLocalDate();
+        LocalDateTime endDate = now.plusMonths(1);
+
+        // 时段强相关目的地(场景触发)当前时间点(当前时间 ± 1小时)内,过去30天内前往次数最多的目的地。
+        List<Long> endPointId = this.baseMapper.timeSceneOrders(startDate, endDate, startMoment, endMoment, userId);
+        // 判定条件: 若当前时段内无明显的规律性目的地(例如:用户在周六下午偶尔出门,且目的地不固定),则推荐用户过去30天内订单总量最高的前1名地址(需排除当前起点)。
+        endPointId.addAll(this.baseMapper.frequencyOrders(startDate, endDate, startMoment, endMoment, userId));
+
+        Integer minOrderDistance = getMinOrderDistanceSafely(uid, startPointId);
+        if (minOrderDistance == null) return null;//获取用户最短可发单距离失败
+        XpPoint start = getPointById(startPointId);
+        GlobalCoordinates startCoordinates = new GlobalCoordinates(start.getPointLon(), start.getPointLat());
+        List<Long> pointIdsByUserId = Optional.ofNullable(xpAppUserCollectAddrClient.getPointIdsByUserId(Long.valueOf(uid)).getData())
+                .orElse(new ArrayList<>());
+        for (Long pointId : endPointId) {
+            XpPoint endPoint = getPointById(pointId);
+            // 计算直线距离,如果endPoint到startPoint的距离大于minOrderDistance,则返回该点
+            GlobalCoordinates endCoordinates = new GlobalCoordinates(endPoint.getPointLon(), endPoint.getPointLat());
+            double distanceMeter = GeodesyUtil.getDistanceMeter(startCoordinates, endCoordinates, Ellipsoid.WGS84);
+            if (distanceMeter > minOrderDistance) {
+                NearestNextVo ret = new NearestNextVo();
+                ret.setId(endPoint.getId());
+                ret.setName(endPoint.getPointName());
+                ret.setLatitude(endPoint.getPointLat());
+                ret.setLongitude(endPoint.getPointLon());
+                ret.setDistance(new BigDecimal(distanceMeter).setScale(2, RoundingMode.HALF_UP).doubleValue());
+                ret.setAddress(endPoint.getPointAddress());
+                ret.setTime(endPoint.getParkingTimeLimit());
+                ret.setElectronicAreaId(endPoint.getElectronicAreaId());
+                // 判断是否收藏
+                if(pointIdsByUserId.contains(endPoint.getId())){
+                    ret.setIsCollect(1);
+                }
+                return ret;
+            }
+        }
+        return null;
+    }
+
+
     private RecommendationCandidate buildSceneCandidate(List<XpOrder> recentOrders, LocalDateTime now, XpPoint startPoint, Integer minOrderDistance) {
         DaySceneType currentSceneType = resolveDaySceneType(now.toLocalDate());
         Set<Integer> targetHours = buildTargetHours(now.getHour());

--
Gitblit v1.7.1