From 07f26b29ec4532349f8d05001d339d909422e401 Mon Sep 17 00:00:00 2001
From: 曾富康 <1067864236@qq.com>
Date: 星期四, 25 六月 2026 16:03:54 +0800
Subject: [PATCH] 新增需求

---
 DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/api/DriverController.java |  166 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 166 insertions(+), 0 deletions(-)

diff --git a/DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/api/DriverController.java b/DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/api/DriverController.java
index a548e9b..019b0d4 100644
--- a/DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/api/DriverController.java
+++ b/DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/api/DriverController.java
@@ -22,6 +22,7 @@
 import com.stylefeng.guns.modular.system.model.*;
 import com.stylefeng.guns.modular.system.model.vo.*;
 import com.stylefeng.guns.modular.system.service.*;
+import com.stylefeng.guns.modular.system.util.GeodesyUtil;
 import com.stylefeng.guns.modular.system.util.ResultUtil;
 import com.stylefeng.guns.modular.system.util.WeChatUtil;
 import com.stylefeng.guns.modular.system.warpper.*;
@@ -131,6 +132,9 @@
     
     @Autowired
     private WeChatUtil weChatUtil;
+
+    @Autowired
+    private GeodesyUtil geodesyUtil;
     
     /**
      * 获取短信验证码
@@ -469,9 +473,171 @@
                 return null;
             }).filter(Objects::nonNull).collect(Collectors.toList());
         }
+//        addMockNearbyDrivers(collect);
         return ResultUtil.success(collect);
     }
 
+    /**
+     * 司机端首页订单热力图。
+     * 热力图统计的是订单起点位置,不统计司机位置;订单坐标统一取 startLon/startLat。
+     * radius 为前端传入的查询半径,单位公里;不传时默认查询 5 公里范围内的可接订单。
+     * 返回结果只包含热力图必要字段,不返回订单ID、乘客信息、地址等敏感数据。
+     */
+    @ResponseBody
+    @PostMapping("/base/driver/queryNearbyOrderHeatMap")
+    @ApiOperation(value = "司机端首页订单热力图", tags = {"司机端-首页"}, notes = "热力图统计订单位置,不统计司机位置")
+    @ApiImplicitParams({
+            @ApiImplicitParam(value = "司机当前位置经度", name = "lon", required = true, dataType = "String"),
+            @ApiImplicitParam(value = "司机当前位置纬度", name = "lat", required = true, dataType = "String"),
+            @ApiImplicitParam(value = "查询半径,单位公里,不传默认5公里", name = "radius", required = false, dataType = "String"),
+            @ApiImplicitParam(value = "订单业务类型:1=专车,2=出租车,3=跨城,4/5=小件物流,不传查询全部", name = "type", required = false, dataType = "int")
+    })
+    public ResultUtil<Map<String, Object>> queryNearbyOrderHeatMap(String lon, String lat, String radius, Integer type) {
+        try {
+            if (ToolUtil.isEmpty(lon) || ToolUtil.isEmpty(lat)) {
+                return ResultUtil.paranErr();
+            }
+            Double centerLon = Double.valueOf(lon);
+            Double centerLat = Double.valueOf(lat);
+            Double radiusKm = ToolUtil.isEmpty(radius) ? 5D : Double.valueOf(radius);
+            if (radiusKm <= 0) {
+                return ResultUtil.paranErr();
+            }
+
+            List<Map<String, Object>> points = new ArrayList<>();
+            String centerLonLat = centerLon + "," + centerLat;
+
+            if (type == null || type == 1) {
+                List<OrderPrivateCar> privateCars = orderPrivateCarService.selectList(new EntityWrapper<OrderPrivateCar>()
+                        .eq("state", 1).isNotNull("startLon").isNotNull("startLat"));
+                addOrderHeatMapPoints(points, privateCars, centerLonLat, radiusKm, 1);
+            }
+            if (type == null || type == 2) {
+                List<OrderTaxi> taxis = orderTaxiService.selectList(new EntityWrapper<OrderTaxi>()
+                        .eq("state", 1).isNotNull("startLon").isNotNull("startLat"));
+                addOrderHeatMapPoints(points, taxis, centerLonLat, radiusKm, 2);
+            }
+            if (type == null || type == 3) {
+                List<OrderCrossCity> crossCities = orderCrossCityService.selectList(new EntityWrapper<OrderCrossCity>()
+                        .eq("state", 1).isNotNull("startLon").isNotNull("startLat"));
+                addOrderHeatMapPoints(points, crossCities, centerLonLat, radiusKm, 3);
+            }
+            if (type == null || type == 4 || type == 5) {
+                Wrapper<OrderLogistics> wrapper = new EntityWrapper<OrderLogistics>()
+                        .eq("state", 1).isNotNull("startLon").isNotNull("startLat");
+                if (type != null) {
+                    wrapper.eq("type", type);
+                }
+                List<OrderLogistics> logistics = orderLogisticsService.selectList(wrapper);
+                addOrderHeatMapPoints(points, logistics, centerLonLat, radiusKm, null);
+            }
+
+            Map<String, Object> data = new HashMap<>();
+//            addMockOrderHeatMapPoints(points);
+            data.put("centerLon", centerLon);
+            data.put("centerLat", centerLat);
+            data.put("radius", radiusKm);
+            data.put("total", points.size());
+            data.put("points", points);
+            return ResultUtil.success(data);
+        } catch (NumberFormatException e) {
+            return ResultUtil.paranErr();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return ResultUtil.runErr();
+        }
+    }
+
+    /**
+     * 将指定业务的订单转换为热力点,并按半径过滤。
+     * 每个订单默认生成一个热力点,count=1;小件物流使用订单自身 type 区分 4/5。
+     */
+    private void addOrderHeatMapPoints(List<Map<String, Object>> points, List<?> orders, String centerLonLat, Double radiusKm, Integer fixedType) {
+        if (ToolUtil.isEmpty(orders)) {
+            return;
+        }
+        for (Object order : orders) {
+            Double startLon = null;
+            Double startLat = null;
+            Integer orderType = fixedType;
+            if (order instanceof OrderPrivateCar) {
+                OrderPrivateCar orderPrivateCar = (OrderPrivateCar) order;
+                startLon = orderPrivateCar.getStartLon();
+                startLat = orderPrivateCar.getStartLat();
+            } else if (order instanceof OrderTaxi) {
+                OrderTaxi orderTaxi = (OrderTaxi) order;
+                startLon = orderTaxi.getStartLon();
+                startLat = orderTaxi.getStartLat();
+            } else if (order instanceof OrderCrossCity) {
+                OrderCrossCity orderCrossCity = (OrderCrossCity) order;
+                startLon = orderCrossCity.getStartLon();
+                startLat = orderCrossCity.getStartLat();
+            } else if (order instanceof OrderLogistics) {
+                OrderLogistics orderLogistics = (OrderLogistics) order;
+                startLon = orderLogistics.getStartLon();
+                startLat = orderLogistics.getStartLat();
+                orderType = orderLogistics.getType();
+            }
+            if (startLon == null || startLat == null) {
+                continue;
+            }
+
+            Map<String, Double> distance = geodesyUtil.getDistance(centerLonLat, startLon + "," + startLat);
+            if (distance == null || distance.get("WGS84") == null || distance.get("WGS84") > radiusKm * 1000) {
+                continue;
+            }
+
+            Map<String, Object> point = new HashMap<>();
+            point.put("lon", startLon);
+            point.put("lat", startLat);
+            point.put("count", 1);
+            point.put("type", orderType);
+            points.add(point);
+        }
+    }
+
+    /**
+     * 测试用司机假数据:在 104.05,30.59 附近补充 5 个司机位置,便于前端联调地图展示。
+     */
+    private void addMockNearbyDrivers(List<Map<String, Object>> collect) {
+        double[][] mockPositions = {
+                {104.0500, 30.5900},
+                {104.0512, 30.5908},
+                {104.0489, 30.5894},
+                {104.0520, 30.5886},
+                {104.0495, 30.5915}
+        };
+        for (int i = 0; i < mockPositions.length; i++) {
+            Map<String, Object> map = new HashMap<>();
+            map.put("driverId", -1001 - i);
+            map.put("name", "测试司机" + (i + 1));
+            map.put("lot", mockPositions[i][0]);
+            map.put("lat", mockPositions[i][1]);
+            collect.add(map);
+        }
+    }
+
+    /**
+     * 测试用订单热力图假数据:在 104.05,30.59 附近补充 5 个订单热力点,便于前端联调热力图展示。
+     */
+    private void addMockOrderHeatMapPoints(List<Map<String, Object>> points) {
+        double[][] mockPositions = {
+                {104.0500, 30.5900},
+                {104.0510, 30.5906},
+                {104.0490, 30.5892},
+                {104.0522, 30.5888},
+                {104.0487, 30.5913}
+        };
+        for (int i = 0; i < mockPositions.length; i++) {
+            Map<String, Object> point = new HashMap<>();
+            point.put("lon", mockPositions[i][0]);
+            point.put("lat", mockPositions[i][1]);
+            point.put("count", 1);
+            point.put("type", i + 1);
+            points.add(point);
+        }
+    }
+
 
     @ResponseBody
     @PostMapping("/api/driver/queryOrderDataFromDriver")

--
Gitblit v1.7.1