Commit b8dd5a8ba1be322462ae906bf76e3d49dfa3595a
1 parent
8a764994
完善以运输单创建轨迹的功能逻辑,新增路径规划、轨迹点解析及轨迹点上传功能
Showing
1 changed file
with
138 additions
and
27 deletions
sl-express-ms-track-service/src/main/java/com/sl/ms/track/service/impl/TrackServiceImpl.java
| 1 | package com.sl.ms.track.service.impl; | 1 | package com.sl.ms.track.service.impl; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 3 | import cn.hutool.core.convert.Convert; | 4 | import cn.hutool.core.convert.Convert; |
| 4 | import cn.hutool.core.map.MapUtil; | 5 | import cn.hutool.core.map.MapUtil; |
| 5 | import cn.hutool.core.util.StrUtil; | 6 | import cn.hutool.core.util.StrUtil; |
| @@ -18,9 +19,15 @@ import com.sl.ms.track.service.TrackService; | @@ -18,9 +19,15 @@ import com.sl.ms.track.service.TrackService; | ||
| 18 | import com.sl.ms.work.api.TransportOrderFeign; | 19 | import com.sl.ms.work.api.TransportOrderFeign; |
| 19 | import com.sl.ms.work.domain.dto.TransportOrderDTO; | 20 | import com.sl.ms.work.domain.dto.TransportOrderDTO; |
| 20 | import org.springframework.beans.factory.annotation.Autowired; | 21 | import org.springframework.beans.factory.annotation.Autowired; |
| 22 | +import org.springframework.data.geo.Point; | ||
| 21 | import org.springframework.data.mongodb.core.MongoTemplate; | 23 | import org.springframework.data.mongodb.core.MongoTemplate; |
| 24 | +import org.springframework.data.mongodb.core.geo.GeoJsonLineString; | ||
| 25 | +import org.springframework.data.mongodb.core.geo.GeoJsonPoint; | ||
| 26 | +import org.springframework.data.mongodb.core.query.Criteria; | ||
| 27 | +import org.springframework.data.mongodb.core.query.Query; | ||
| 22 | import org.springframework.stereotype.Service; | 28 | import org.springframework.stereotype.Service; |
| 23 | 29 | ||
| 30 | +import java.util.ArrayList; | ||
| 24 | import java.util.List; | 31 | import java.util.List; |
| 25 | import java.util.Map; | 32 | import java.util.Map; |
| 26 | 33 | ||
| @@ -39,49 +46,115 @@ public class TrackServiceImpl implements TrackService { | @@ -39,49 +46,115 @@ public class TrackServiceImpl implements TrackService { | ||
| 39 | @Autowired | 46 | @Autowired |
| 40 | private EagleMapTemplate eagleMapTemplate; | 47 | private EagleMapTemplate eagleMapTemplate; |
| 41 | 48 | ||
| 49 | + /** | ||
| 50 | + * 创建运输轨迹 | ||
| 51 | + * 根据运输单ID获取起止位置,调用高德地图API规划路线,并保存轨迹信息到MongoDB | ||
| 52 | + * | ||
| 53 | + * @param transportOrderId 运输单ID | ||
| 54 | + * @return 创建成功返回true,失败返回false | ||
| 55 | + */ | ||
| 42 | @Override | 56 | @Override |
| 43 | public boolean create(String transportOrderId) { | 57 | public boolean create(String transportOrderId) { |
| 58 | + // 1. 获取运输单和订单位置信息 | ||
| 44 | TransportOrderDTO transportOrderDTO = transportOrderFeign.findById(transportOrderId); | 59 | TransportOrderDTO transportOrderDTO = transportOrderFeign.findById(transportOrderId); |
| 45 | - | ||
| 46 | OrderLocationDTO orderLocationDTO = orderFeign.findOrderLocationByOrderId(transportOrderDTO.getOrderId()); | 60 | OrderLocationDTO orderLocationDTO = orderFeign.findOrderLocationByOrderId(transportOrderDTO.getOrderId()); |
| 47 | 61 | ||
| 48 | - TrackEntity trackEntity = new TrackEntity(); | ||
| 49 | - trackEntity.setTransportOrderId(transportOrderId); | ||
| 50 | - | ||
| 51 | - String sendLocation = orderLocationDTO.getSendLocation(); | ||
| 52 | - String receiveLocation = orderLocationDTO.getReceiveLocation(); | 62 | + // 2. 解析起止坐标(格式:经度,纬度) |
| 63 | + Coordinate origin = parseCoordinate(orderLocationDTO.getSendLocation()); | ||
| 64 | + Coordinate destination = parseCoordinate(orderLocationDTO.getReceiveLocation()); | ||
| 53 | 65 | ||
| 54 | - double sendLnt = Double.parseDouble(sendLocation.split(",")[0]); | ||
| 55 | - double sendLat = Double.parseDouble(sendLocation.split(",")[1]); | 66 | + // 3. 调用高德地图API进行路径规划 |
| 67 | + Map<String, Object> param = MapUtil.<String, Object>builder() | ||
| 68 | + .put("show_fields", "polyline") // 返回详细路径坐标 | ||
| 69 | + .build(); | ||
| 70 | + String driving = this.eagleMapTemplate.opsForDirection() | ||
| 71 | + .driving(ProviderEnum.AMAP, origin, destination, param); | ||
| 56 | 72 | ||
| 57 | - | ||
| 58 | - double receiveLnt = Double.parseDouble(receiveLocation.split(",")[0]); | ||
| 59 | - double receiveLat = Double.parseDouble(receiveLocation.split(",")[1]); | ||
| 60 | - | ||
| 61 | - Coordinate origin = new Coordinate(sendLnt, sendLat); | ||
| 62 | - Coordinate destination = new Coordinate(receiveLnt, receiveLat); | ||
| 63 | - | ||
| 64 | - //设置高德地图参数,默认是不返回预计耗时的,需要额外设置参数 | ||
| 65 | - Map<String, Object> param = MapUtil.<String, Object>builder().put("show_fields", "polyline").build(); | ||
| 66 | - String driving = this.eagleMapTemplate.opsForDirection().driving(ProviderEnum.AMAP, origin, destination, param); | 73 | + // 如果路径规划失败,直接返回 |
| 67 | if (StrUtil.isEmpty(driving)) { | 74 | if (StrUtil.isEmpty(driving)) { |
| 68 | return false; | 75 | return false; |
| 69 | } | 76 | } |
| 70 | - JSONObject jsonObject = JSONUtil.parseObj(driving); | ||
| 71 | 77 | ||
| 72 | - //距离,单位:米 | ||
| 73 | - Double distance = Convert.toDouble(jsonObject.getByPath("route.paths[0].distance"), -1d); | 78 | + // 4. 解析高德地图返回的路径数据 |
| 79 | + JSONObject routeData = JSONUtil.parseObj(driving); | ||
| 80 | + Double distance = Convert.toDouble(routeData.getByPath("route.paths[0].distance"), -1d); | ||
| 81 | + JSONArray steps = routeData.getByPath("route.paths[0].steps", JSONArray.class); | ||
| 82 | + | ||
| 83 | + // 5. 从路径数据中提取所有轨迹点 | ||
| 84 | + List<Point> trackPoints = collectTrackPoints(steps); | ||
| 85 | + | ||
| 86 | + // 6. 构建轨迹实体对象 | ||
| 87 | + TrackEntity trackEntity = new TrackEntity(); | ||
| 88 | + trackEntity.setTransportOrderId(transportOrderId); | ||
| 74 | trackEntity.setDistance(distance); | 89 | trackEntity.setDistance(distance); |
| 75 | trackEntity.setStatus(TrackStatusEnum.NEW); | 90 | trackEntity.setStatus(TrackStatusEnum.NEW); |
| 76 | trackEntity.setType(TrackTypeEnum.COURIER); | 91 | trackEntity.setType(TrackTypeEnum.COURIER); |
| 77 | 92 | ||
| 78 | - JSONArray steps = jsonObject.getByPath("route.paths[0].steps", JSONArray.class); | 93 | + // 7. 如果轨迹点足够(至少2个点),设置规划路线 |
| 94 | + if (trackPoints.size() >= 2) { | ||
| 95 | + trackEntity.setPlanGeoJsonLine(new GeoJsonLineString(trackPoints)); | ||
| 96 | + trackEntity.setLastPoint((GeoJsonPoint) trackPoints.get(0)); | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + // 8. 保存轨迹信息到MongoDB | ||
| 100 | + mongoTemplate.save(trackEntity); | ||
| 101 | + return true; | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | + /** | ||
| 105 | + * 解析坐标字符串 | ||
| 106 | + * 将"经度,纬度"格式的字符串转换为Coordinate对象 | ||
| 107 | + * | ||
| 108 | + * @param location 位置字符串,格式:经度,纬度(例如:116.397128,39.916527) | ||
| 109 | + * @return Coordinate对象 | ||
| 110 | + */ | ||
| 111 | + private Coordinate parseCoordinate(String location) { | ||
| 112 | + String[] parts = location.split(","); | ||
| 113 | + double lng = Double.parseDouble(parts[0]); | ||
| 114 | + double lat = Double.parseDouble(parts[1]); | ||
| 115 | + return new Coordinate(lng, lat); | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | + /** | ||
| 119 | + * 从高德地图路径steps中收集所有轨迹点 | ||
| 120 | + * 遍历每个step的polyline字段,解析出所有坐标点 | ||
| 121 | + * | ||
| 122 | + * @param steps 高德地图返回的路径步骤数组 | ||
| 123 | + * @return 轨迹点列表 | ||
| 124 | + */ | ||
| 125 | + private List<Point> collectTrackPoints(JSONArray steps) { | ||
| 126 | + List<Point> points = new ArrayList<>(); | ||
| 127 | + | ||
| 79 | for (int i = 0; i < steps.size(); i++) { | 128 | for (int i = 0; i < steps.size(); i++) { |
| 80 | - JSONObject entries = steps.getJSONObject(i); | ||
| 81 | - String polyline = entries.getStr("polyline"); | 129 | + JSONObject step = steps.getJSONObject(i); |
| 130 | + String polyline = step.getStr("polyline"); | ||
| 131 | + | ||
| 132 | + if (StrUtil.isEmpty(polyline)) { | ||
| 133 | + continue; | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + // polyline格式:经度1,纬度1;经度2,纬度2;经度3,纬度3... | ||
| 137 | + String[] coordPairs = polyline.split(";"); | ||
| 138 | + for (String coordPair : coordPairs) { | ||
| 139 | + if (StrUtil.isEmpty(coordPair)) { | ||
| 140 | + continue; | ||
| 141 | + } | ||
| 142 | + | ||
| 143 | + // 解析单个坐标点 | ||
| 144 | + String[] coords = coordPair.split(","); | ||
| 145 | + if (coords.length == 2) { | ||
| 146 | + try { | ||
| 147 | + double lng = Double.parseDouble(coords[0].trim()); | ||
| 148 | + double lat = Double.parseDouble(coords[1].trim()); | ||
| 149 | + points.add(new GeoJsonPoint(lng, lat)); | ||
| 150 | + } catch (NumberFormatException e) { | ||
| 151 | + // 忽略无法解析的坐标点 | ||
| 152 | + } | ||
| 153 | + } | ||
| 154 | + } | ||
| 82 | } | 155 | } |
| 83 | 156 | ||
| 84 | - return false; | 157 | + return points; |
| 85 | } | 158 | } |
| 86 | 159 | ||
| 87 | @Override | 160 | @Override |
| @@ -91,16 +164,54 @@ public class TrackServiceImpl implements TrackService { | @@ -91,16 +164,54 @@ public class TrackServiceImpl implements TrackService { | ||
| 91 | 164 | ||
| 92 | @Override | 165 | @Override |
| 93 | public TrackEntity queryByTransportOrderId(String transportOrderId) { | 166 | public TrackEntity queryByTransportOrderId(String transportOrderId) { |
| 94 | - return null; | 167 | + Query query = Query.query(Criteria.where("transportOrderId").is(transportOrderId)); |
| 168 | + return mongoTemplate.findOne(query, TrackEntity.class); | ||
| 95 | } | 169 | } |
| 96 | 170 | ||
| 171 | + /** | ||
| 172 | + * 上传车辆轨迹点信息 | ||
| 173 | + * | ||
| 174 | + * @param transportTaskId 运输任务id | ||
| 175 | + * @param lng 经度 | ||
| 176 | + * @param lat 纬度 | ||
| 177 | + * @return 上传成功返回true,失败返回false | ||
| 178 | + */ | ||
| 97 | @Override | 179 | @Override |
| 98 | public boolean uploadFromTruck(Long transportTaskId, double lng, double lat) { | 180 | public boolean uploadFromTruck(Long transportTaskId, double lng, double lat) { |
| 99 | return false; | 181 | return false; |
| 100 | } | 182 | } |
| 101 | 183 | ||
| 184 | + /** | ||
| 185 | + * 从快递员上传轨迹点信息 | ||
| 186 | + * | ||
| 187 | + * @param transportOrderIds 运输单ID列表 | ||
| 188 | + * @param lng 经度 | ||
| 189 | + * @param lat 纬度 | ||
| 190 | + * @return 上传成功返回true,失败返回false | ||
| 191 | + */ | ||
| 102 | @Override | 192 | @Override |
| 103 | public boolean uploadFromCourier(List<String> transportOrderIds, double lng, double lat) { | 193 | public boolean uploadFromCourier(List<String> transportOrderIds, double lng, double lat) { |
| 104 | - return false; | 194 | + // 1. 校验运输单ID列表是否为空 |
| 195 | + if (CollUtil.isEmpty(transportOrderIds)) { | ||
| 196 | + return false; | ||
| 197 | + } | ||
| 198 | + | ||
| 199 | + // 2. 查询运输单对应的轨迹信息 | ||
| 200 | + Query query = Query.query(Criteria.where("transportOrderId").in(transportOrderIds)); | ||
| 201 | + List<TrackEntity> tracks = mongoTemplate.find(query, TrackEntity.class); | ||
| 202 | + | ||
| 203 | + // 3. 如果没有找到对应的轨迹信息,返回false | ||
| 204 | + if (tracks.isEmpty()) { | ||
| 205 | + return false; | ||
| 206 | + } | ||
| 207 | + | ||
| 208 | + // 4. 创建新的轨迹点并更新所有轨迹的最新位置 | ||
| 209 | + GeoJsonPoint newPoint = new GeoJsonPoint(lng, lat); | ||
| 210 | + for (TrackEntity track : tracks) { | ||
| 211 | + track.setLastPoint(newPoint); | ||
| 212 | + mongoTemplate.save(track); | ||
| 213 | + } | ||
| 214 | + | ||
| 215 | + return true; | ||
| 105 | } | 216 | } |
| 106 | } | 217 | } |