xuhy
2026-03-05 a8f79a74b1d6ba53d159b77f2226e40454186b91
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
package com.xiaopeng.map.controller;
 
 
import com.xiaopeng.api.dto.map.OrderRouteAndFareDto;
import com.xiaopeng.api.dto.map.RouteAndFareDto;
import com.xiaopeng.api.dto.operation.LonLatDto;
import com.xiaopeng.api.feignClient.order.XpOrderClient;
import com.xiaopeng.api.model.order.XpOrder;
import com.xiaopeng.api.vo.map.PointByIpVo;
import com.xiaopeng.api.vo.map.XpDistanceAndDurationVo;
import com.xiaopeng.api.vo.operation.RouteVo;
import com.xiaopeng.common.core.constant.CacheConstants;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.redis.service.RedisService;
import com.xiaopeng.map.mangodb.model.GeoPoint;
import com.xiaopeng.map.mangodb.service.XpGeoFencingPolygonService;
import com.xiaopeng.map.utils.AmapWalkingRouteUtil;
import com.xiaopeng.map.utils.GDMapGeocodingUtil;
import com.xiaopeng.map.utils.mangoUtils.MongoGeoFenceUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
 
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
 
@Slf4j
@RestController
@RequestMapping("/base/v1/mini-program")
@Api(tags = "地图调用服务")
public class XpMapController {
 
 
    private final GDMapGeocodingUtil gdMapGeocodingUtil;
    private final XpGeoFencingPolygonService xpGeoFencingPolygonService;
    private final RedisService redisService;
    private final XpOrderClient xpOrderClient;
    private final MongoTemplate mongoTemplate;
 
    public XpMapController(GDMapGeocodingUtil gdMapGeocodingUtil, XpGeoFencingPolygonService xpGeoFencingPolygonService, RedisService redisService, XpOrderClient xpOrderClient, MongoTemplate mongoTemplate) {
        this.gdMapGeocodingUtil = gdMapGeocodingUtil;
        this.xpGeoFencingPolygonService = xpGeoFencingPolygonService;
        this.redisService = redisService;
        this.xpOrderClient = xpOrderClient;
        this.mongoTemplate = mongoTemplate;
    }
 
 
    @PostMapping("/map/getDistanceAndDuration")
    public R<RouteVo> getDistanceAndDuration(@RequestBody RouteAndFareDto dto){
        // 获取电子围栏的禁行区域点位
        GeoPoint startPoint = new GeoPoint(dto.getOrigin().getLongitude(),dto.getOrigin().getLatitude());
        List<String> operatingArea = xpGeoFencingPolygonService.findFencesContainingPoint(startPoint, "operating_area", "points");
        String fenceId = operatingArea.get(0);
 
        List<Document> pointsInFence = xpGeoFencingPolygonService.findPointsByParentId(fenceId, "fenceId", "prohibited_area");
 
        // 避让区域
        ArrayList<String> pointStrParam = new ArrayList<>();
        try {
            for (Document document : pointsInFence) {
                // 获取points字段(它是GeoJSON对象)
                Document geoJsonDoc = document.get("points", Document.class);
 
                if (geoJsonDoc != null && "Polygon".equals(geoJsonDoc.getString("type"))) {
                    // 获取coordinates数组
                    List<List<List<Double>>> coordinates = (List<List<List<Double>>>) geoJsonDoc.get("coordinates");
 
                    if (coordinates != null && !coordinates.isEmpty()) {
                        // 获取第一个多边形环(通常只有一个)
                        List<List<Double>> polygonPoints = coordinates.get(0);
 
                        // 转换为经纬度字符串
                        ArrayList<String> pointStr = new ArrayList<>();
                        for (List<Double> point : polygonPoints) {
                            if (point.size() >= 2) {
                                pointStr.add(point.get(0) + "," + point.get(1));
                            }
                        }
 
                        if (!pointStr.isEmpty()) {
                            pointStrParam.add(String.join(";", pointStr));
                        }
                    }
                }
            }
            RouteVo routeVo = gdMapGeocodingUtil.getDistanceAndTime(dto.getOrigin(), dto.getDestination(), String.join("|", pointStrParam), fenceId,dto.getRoutePlanRule());
            if(routeVo==null){
                return R.fail("没有找到路线");
            }
 
            return R.ok(routeVo);
        }catch (Exception e){
            e.printStackTrace();
        }
        return R.fail("没有找到路线");
 
 
    }
 
 
    /**
     * 获取订单距离和时长
     * @param dto
     * @return
     */
    @PostMapping("/map/getOrderDistanceAndDuration")
    public R<RouteVo> getOrderDistanceAndDuration(@Validated @RequestBody OrderRouteAndFareDto dto){
        // 获取电子围栏的禁行区域点位
        GeoPoint startPoint = new GeoPoint(dto.getOrigin().getLongitude(),dto.getOrigin().getLatitude());
        List<String> operatingArea = xpGeoFencingPolygonService.findFencesContainingPoint(startPoint, "operating_area", "points");
        // 避让区域
        ArrayList<String> pointStrParam = new ArrayList<>();
        String fenceId = null;
        if(!operatingArea.isEmpty()){
            fenceId = operatingArea.get(0);
            List<Document> pointsInFence = xpGeoFencingPolygonService.findPointsByParentId(fenceId, "parentId", "prohibited_area");
            for (Document document : pointsInFence) {
                List<GeoPoint> points = document.getList("points", GeoPoint.class);
                // 一个区域的点位
                ArrayList<String> pointStr = new ArrayList<>();
                for (GeoPoint point : points) {
                    pointStr.add( point.getLongitude()+","+point.getLatitude());
                }
                if(!pointStr.isEmpty()){
                    pointStrParam.add(String.join(";", pointStr));
                }
            }
        }
 
        RouteVo routeVo = gdMapGeocodingUtil.getDistanceAndTime(dto.getOrigin(), dto.getDestination(), String.join("|", pointStrParam), fenceId,dto.getRoutePlanRule());
        if(routeVo==null){
            return R.fail("没有找到路线");
        }
 
        // 存储redis
        redisService.setCacheObject(CacheConstants.ORDER_ROUTE + "_" + dto.getOrderId() + "_" +dto.getRouteType(), routeVo);
        // 存储路线偏离缓存,后续进行轨迹截取
//        redisService.setCacheObject(CacheConstants.ORDER_ROUTE_CAPTURE + "_" + dto.getOrderId() + "_" +dto.getRouteType(), routeVo);
 
        return R.ok(routeVo);
    }
 
    /**
     * 根据导航ID获取车端需要的导航数据
     * @param routedID
     * @return
     */
    @PostMapping("/map/queryRouted")
    public R<String> getOrderDistanceAndDuration(@RequestParam("routedID") String routedID){
        return R.ok(gdMapGeocodingUtil.routed(routedID));
    }
 
 
    /**
     * 根据ip获取点位
     */
    @ApiOperation(value = "根据ip获取点位", tags = {"小程序-站点导航"})
    @GetMapping("/point/getPointByIp")
    public R<PointByIpVo> getPointByIp(HttpServletRequest request) throws IOException {
        String ip = request.getRemoteAddr();
        PointByIpVo pointByIpVo = AmapWalkingRouteUtil.ipLocation(ip);
        return R.ok(pointByIpVo);
    }
 
}