Bläddra i källkod

提交全图监控

chenxiaofei 1 månad sedan
förälder
incheckning
f5fac6295c

+ 200 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/LocUtils.java

@@ -1,9 +1,16 @@
 package com.sckw.core.utils;
 
 import java.io.IOException;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.sckw.core.model.constant.Global;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpResponse;
 import org.apache.http.client.HttpClient;
@@ -11,6 +18,7 @@ import org.apache.http.client.methods.HttpGet;
 import org.apache.http.impl.client.HttpClients;
 import org.apache.http.util.EntityUtils;
 
+@Slf4j
 public class LocUtils {
 
     static String GD_KEY = "739ace2ede6fe1e2f4ae3bcba890833c";
@@ -51,6 +59,198 @@ public class LocUtils {
         return null;
     }
 
+    /**
+     * 调用高德驾车路径规划API,获取路径上均匀分布的轨迹点位
+     *
+     * @param startLng    起点经度
+     * @param startLat    起点纬度
+     * @param endLng      终点经度
+     * @param endLat      终点纬度
+     * @param pointCount  需要生成的轨迹点数量
+     * @return 轨迹点位列表(JSON字符串格式)
+     */
+    public static String getDrivingRoutePoints(String startLng, String startLat, 
+                                                String endLng, String endLat, int pointCount) {
+        RouteResult result = getDrivingRoutePointsWithDuration(startLng, startLat, endLng, endLat, pointCount);
+        return result != null ? result.getPointInfo() : null;
+    }
+
+    /**
+     * 调用高德驾车路径规划API,获取路径上均匀分布的轨迹点位以及耗时信息
+     *
+     * @param startLng    起点经度
+     * @param startLat    起点纬度
+     * @param endLng      终点经度
+     * @param endLat      终点纬度
+     * @param pointCount  需要生成的轨迹点数量
+     * @return 包含轨迹点位和耗时的结果对象
+     */
+    public static RouteResult getDrivingRoutePointsWithDuration(String startLng, String startLat, 
+                                                                 String endLng, String endLat, int pointCount) {
+        if (StringUtils.isBlank(startLng) || StringUtils.isBlank(startLat) 
+                || StringUtils.isBlank(endLng) || StringUtils.isBlank(endLat)) {
+            return null;
+        }
+        
+        // 构建高德驾车路径规划API请求
+        StringBuilder requestUrl = new StringBuilder();
+        requestUrl.append("https://restapi.amap.com/v3/direction/driving?");
+        requestUrl.append("origin=").append(startLng).append(",").append(startLat);
+        requestUrl.append("&destination=").append(endLng).append(",").append(endLat);
+        requestUrl.append("&extensions=all&output=json");
+        requestUrl.append("&key=").append(GD_KEY);
+
+        try {
+            HttpClient httpClient = HttpClients.createDefault();
+            HttpGet httpGet = new HttpGet(requestUrl.toString());
+            HttpResponse response = httpClient.execute(httpGet);
+            HttpEntity entity = response.getEntity();
+            String responseStr = EntityUtils.toString(entity, "UTF-8");
+            
+            log.info("高德驾车路径规划API响应: {}", responseStr);
+            
+            JSONObject resultJson = responseStr != null ? JSON.parseObject(responseStr) : null;
+            if (resultJson == null || !"1".equals(resultJson.getString("status"))) {
+                log.warn("高德API调用失败");
+                return null;
+            }
+            
+            // 解析耗时信息(单位:秒)
+            String duration = parseDuration(resultJson);
+            
+            // 解析路径点位
+            List<RoutePoint> allPoints = parseRoutePoints(resultJson);
+            if (allPoints.isEmpty()) {
+                return null;
+            }
+            
+            // 从所有点位中均匀选取指定数量的点
+            List<RoutePoint> selectedPoints = selectUniformPoints(allPoints, pointCount);
+            
+            RouteResult result = new RouteResult();
+            result.setPointInfo(JSON.toJSONString(selectedPoints));
+            result.setDuration(duration);
+            
+            return result;
+        } catch (Exception e) {
+            log.error("调用高德驾车路径规划API异常", e);
+        }
+        return null;
+    }
+
+    /**
+     * 解析高德API返回的路径耗时(单位:秒)
+     */
+    private static String parseDuration(JSONObject resultJson) {
+        try {
+            JSONObject route = resultJson.getJSONObject("route");
+            if (route == null) return null;
+            
+            JSONArray paths = route.getJSONArray("paths");
+            if (paths == null || paths.isEmpty()) return null;
+            
+            JSONObject path = paths.getJSONObject(0);
+            // duration字段表示预计行驶时间,单位:秒
+            return path.getString("duration");
+        } catch (Exception e) {
+            log.error("解析路径耗时异常", e);
+            return null;
+        }
+    }
+
+    /**
+     * 解析高德路径规划返回的所有路径点位
+     */
+    private static List<RoutePoint> parseRoutePoints(JSONObject resultJson) {
+        List<RoutePoint> allPoints = new ArrayList<>();
+        
+        try {
+            JSONObject route = resultJson.getJSONObject("route");
+            if (route == null) return allPoints;
+            
+            JSONArray paths = route.getJSONArray("paths");
+            if (paths == null || paths.isEmpty()) return allPoints;
+            
+            JSONObject path = paths.getJSONObject(0);
+            JSONArray steps = path.getJSONArray("steps");
+            if (steps == null || steps.isEmpty()) return allPoints;
+            
+            for (int i = 0; i < steps.size(); i++) {
+                JSONObject step = steps.getJSONObject(i);
+                String polyline = step.getString("polyline");
+                if (StringUtils.isNotBlank(polyline)) {
+                    String[] pointStrs = polyline.split(";");
+                    for (String pointStr : pointStrs) {
+                        String[] coords = pointStr.split(",");
+                        if (coords.length == 2) {
+                            RoutePoint point = new RoutePoint();
+                            point.setLongitude(coords[0]);
+                            point.setLatitude(coords[1]);
+                            allPoints.add(point);
+                        }
+                    }
+                }
+            }
+        } catch (Exception e) {
+            log.error("解析高德路径点位异常", e);
+        }
+        
+        return allPoints;
+    }
+
+    /**
+     * 从所有点位中均匀选取指定数量的点
+     */
+    private static List<RoutePoint> selectUniformPoints(List<RoutePoint> allPoints, int pointCount) {
+        List<RoutePoint> selectedPoints = new ArrayList<>();
+        
+        if (allPoints.isEmpty()) return selectedPoints;
+        
+        if (allPoints.size() <= pointCount) {
+            LocalDateTime now = LocalDateTime.now();
+            for (int i = 0; i < allPoints.size(); i++) {
+                RoutePoint point = allPoints.get(i);
+                point.setTs(now.plusMinutes(i * 5L));
+                selectedPoints.add(point);
+            }
+            return selectedPoints;
+        }
+        
+        double interval = (double) (allPoints.size() - 1) / (pointCount - 1);
+        LocalDateTime now = LocalDateTime.now();
+        
+        for (int i = 0; i < pointCount; i++) {
+            int index = (int) Math.round(i * interval);
+            if (index >= allPoints.size()) index = allPoints.size() - 1;
+            RoutePoint point = allPoints.get(index);
+            point.setTs(now.plusMinutes(i * 5L));
+            selectedPoints.add(point);
+        }
+        
+        return selectedPoints;
+    }
+
+    /**
+     * 路径点位信息
+     */
+    @Data
+    public static class RoutePoint {
+        private LocalDateTime ts;
+        private String longitude;
+        private String latitude;
+    }
+
+    /**
+     * 路径结果信息(包含轨迹点位和耗时)
+     */
+    @Data
+    public static class RouteResult {
+        /** 轨迹点位JSON字符串 */
+        private String pointInfo;
+        /** 预计耗时(单位:秒) */
+        private String duration;
+    }
+
     public static void main(String[] args) {
         String res = regeo("118.879289", "38.052237");
         System.out.println(res);

+ 2 - 0
sckw-modules-api/sckw-transport-api/src/main/java/com/sckw/transport/api/dubbo/TransportRemoteService.java

@@ -199,4 +199,6 @@ public interface TransportRemoteService {
     WaybillOrderTaskVO queryWaybillOrderTaskByDriverId(Long entId, Long driverId);
 
 
+    RWaybillOrderVo queryWaybillOrderByWayBillOrderId(Long wayBillOrderId);
+
 }

+ 27 - 0
sckw-modules-api/sckw-transport-api/src/main/java/com/sckw/transport/api/model/vo/RWaybillOrderVo.java

@@ -1,6 +1,8 @@
 package com.sckw.transport.api.model.vo;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -100,4 +102,29 @@ public class RWaybillOrderVo implements Serializable {
     @JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date departureTime;
+
+
+    /**
+     * 装货地址经度
+     */
+
+    private String startLng;
+
+    /**
+     * 装货地址纬度
+     */
+
+    private String startLat;
+
+    /**
+     * 卸货地址经度
+     */
+
+    private String endLng;
+
+    /**
+     * 卸货地址纬度
+     */
+    private String endLat;
+
 }

+ 6 - 0
sckw-modules/sckw-fleet/src/main/java/com/sckw/fleet/model/request/QueryTruckRouteByDriverReq.java

@@ -1,6 +1,7 @@
 package com.sckw.fleet.model.request;
 
 import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
 import jakarta.validation.constraints.NotNull;
 import lombok.Data;
 
@@ -36,4 +37,9 @@ public class QueryTruckRouteByDriverReq implements Serializable {
     @NotNull(message = "卸货地址不能为空")
     @Schema(description = "卸货地址")
     private String unloadingPoint;
+    /**
+     * 运单id
+     */
+    @Schema(description = "运单id")
+    private Long wayBillOrderId;
 }

+ 80 - 7
sckw-modules/sckw-fleet/src/main/java/com/sckw/fleet/service/KwfTruckRouteService.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.sckw.core.model.base.BaseModel;
 import com.sckw.core.utils.DateUtils;
+import com.sckw.core.utils.LocUtils;
 import com.sckw.core.utils.StringUtils;
 import com.sckw.core.web.context.LoginUserHolder;
 import com.sckw.core.web.response.result.PageDataResult;
@@ -17,11 +18,14 @@ import com.sckw.fleet.model.request.TruckRoteDetailReq;
 import com.sckw.fleet.model.vo.QueryTruckRoteVo;
 import com.sckw.fleet.model.vo.TruckRoteDetailVo;
 import com.sckw.fleet.repository.*;
+import com.sckw.transport.api.dubbo.TransportRemoteService;
+import com.sckw.transport.api.model.vo.RWaybillOrderVo;
 import jakarta.annotation.Resource;
 import jakarta.validation.Valid;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.CollectionUtils;
+import org.apache.dubbo.config.annotation.DubboReference;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDateTime;
@@ -43,7 +47,8 @@ public class KwfTruckRouteService {
     private final KwfTruckRepository truckRepository;
     @Resource
     private  KwfFleetRepository fleetRepository;
-
+    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 8000)
+    private TransportRemoteService transportRemoteService;
 
     public PageDataResult<QueryTruckRoteVo> pageTruckRoute(QueryTruckRoteReq req) {
         log.info("分页查询车辆惯用路线,参数:{}", JSON.toJSONString(req));
@@ -184,7 +189,6 @@ public class KwfTruckRouteService {
      */
     public QueryTruckRoteVo queryTruckRouteByDriver(QueryTruckRouteByDriverReq req) {
         log.info("根据司机ID和装货卸货地址查询常用路线,请求参数 :{}", JSON.toJSONString(req));
-        
         // 查询常用路线
         KwfTruckRoute truckRoute = truckRouteRepository.queryByDriverIdAndAddress(
                 req.getDriverId(), 
@@ -193,11 +197,25 @@ public class KwfTruckRouteService {
         );
         
         if (Objects.isNull(truckRoute)) {
-            log.info("未查询到司机ID:{},装货地址:{},卸货地址:{} 的常用路线", 
+
+            try {
+                log.info("未查询到,开始mock数据司机ID:{},装货地址:{},卸货地址:{} 的常用路线",
+                        req.getDriverId(), req.getStartPoint(), req.getUnloadingPoint());
+                saveTruckRote(req);
+                truckRoute = truckRouteRepository.queryByDriverIdAndAddress(
+                        req.getDriverId(),
+                        req.getStartPoint(),
+                        req.getUnloadingPoint()
+                );
+            } catch (Exception e) {
+                log.error("新增常用路线异常", e);
+            }
+        }
+        if (Objects.isNull(truckRoute)){
+            log.info("未查询到司机ID:{},装货地址:{},卸货地址:{} 的常用路线",
                     req.getDriverId(), req.getStartPoint(), req.getUnloadingPoint());
-            return null;
+            return new QueryTruckRoteVo();
         }
-        
         // 组装返回数据
         QueryTruckRoteVo vo = new QueryTruckRoteVo();
         vo.setId(truckRoute.getId());
@@ -224,18 +242,73 @@ public class KwfTruckRouteService {
             vo.setDriverName(driver.getName());
         }
 
+        // 使用更新后的轨迹点
         String pointInfo = truckRoute.getPointInfo();
         if (StringUtils.isNotBlank(pointInfo)) {
             List<QueryTruckRoteVo.TruckRoteDetail> truckRoteDetails = JSON.parseArray(pointInfo, QueryTruckRoteVo.TruckRoteDetail.class);
-            truckRoteDetails =truckRoteDetails.stream()
+            truckRoteDetails = truckRoteDetails.stream()
                     .sorted(Comparator.comparing(QueryTruckRoteVo.TruckRoteDetail::getTs))
                     .collect(Collectors.toList());
-
             vo.setTruckRoteDetails(truckRoteDetails);
         }
 
         return vo;
     }
 
+    private void saveTruckRote(QueryTruckRouteByDriverReq req) {
+        RWaybillOrderVo rWaybillOrderVo = transportRemoteService.queryWaybillOrderByWayBillOrderId(req.getWayBillOrderId());
+        KwfFleetTruck kwfFleetTruck = fleetTruckRepository.findFleetByTruckId(rWaybillOrderVo.getTruckId(),LoginUserHolder.getEntId());
+        // 在查询惯用路线之前,调用高德API生成装货地址和卸货地址之间的20个轨迹点位
+        LocUtils.RouteResult routeResult = generateRoutePointsWithDuration(rWaybillOrderVo);
+        KwfTruckRoute kwfTruckRoute = new KwfTruckRoute();
+        kwfTruckRoute.setFleetId(Optional.ofNullable(kwfFleetTruck).map(KwfFleetTruck::getFleetId).orElse(0L));
+        kwfTruckRoute.setDriverId(req.getDriverId());
+        kwfTruckRoute.setEntId(LoginUserHolder.getEntId());
+        kwfTruckRoute.setStartPoint(req.getStartPoint());
+        kwfTruckRoute.setUnloadingPoint(req.getUnloadingPoint());
+        // 设置装货点和卸货点的耗时时间(单位:秒)
+        if (routeResult != null && StringUtils.isNotBlank(routeResult.getDuration())) {
+            kwfTruckRoute.setShortestTime(routeResult.getDuration());
+        }
+        // 如果生成了轨迹点,更新到数据库的point_info字段
+        if (routeResult != null && StringUtils.isNotBlank(routeResult.getPointInfo())) {
+            kwfTruckRoute.setPointInfo(routeResult.getPointInfo());
+        }
+        kwfTruckRoute.setTruckNo(rWaybillOrderVo.getTruckNo());
+        kwfTruckRoute.setTruckId(rWaybillOrderVo.getTruckId());
+        truckRouteRepository.save(kwfTruckRoute);
+    }
+
+    /**
+     * 调用高德API生成装货地址和卸货地址之间的20个轨迹点位信息和耗时
+     * @param req 请求参数
+     * @return 轨迹点位和耗时信息
+     */
+    private LocUtils.RouteResult generateRoutePointsWithDuration(RWaybillOrderVo req) {
+        try {
+            log.info("开始调用高德API生成轨迹点位和耗时,起点: {},{} 终点: {},{}", 
+                    req.getStartLng(), req.getStartLat(), req.getEndLng(), req.getEndLat());
+            
+            // 调用高德驾车路径规划API,生成20个轨迹点位和耗时
+            LocUtils.RouteResult routeResult = com.sckw.core.utils.LocUtils.getDrivingRoutePointsWithDuration(
+                    req.getStartLng(), 
+                    req.getStartLat(),
+                    req.getEndLng(), 
+                    req.getEndLat(),
+                    20
+            );
+            
+            if (routeResult != null && StringUtils.isNotBlank(routeResult.getPointInfo())) {
+                log.info("高德API生成轨迹点位成功,耗时: {}秒", routeResult.getDuration());
+            } else {
+                log.warn("高德API生成轨迹点位失败或返回空数据");
+            }
+            
+            return routeResult;
+        } catch (Exception e) {
+            log.error("调用高德API生成轨迹点位异常", e);
+            return null;
+        }
+    }
 
 }

+ 44 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/dubbo/TransportServiceImpl.java

@@ -13,6 +13,7 @@ import com.sckw.core.common.enums.enums.DictTypeEnum;
 import com.sckw.core.exception.BusinessException;
 import com.sckw.core.model.constant.Global;
 import com.sckw.core.model.constant.NumberConstant;
+import com.sckw.core.model.enums.AddressTypeEnum;
 import com.sckw.core.model.enums.CarWaybillEnum;
 import com.sckw.core.model.enums.CarWaybillV1Enum;
 import com.sckw.core.model.enums.LogisticsOrderEnum;
@@ -137,6 +138,7 @@ public class TransportServiceImpl implements TransportRemoteService {
     private final KwtAcceptCarriageOrderService kwtAcceptCarriageOrderService;
     private final KwtLogisticsConsignmentService logisticsConsignmentService;
     private final KwtLogisticsOrderGoodsRepository logisticsOrderGoodsRepository;
+    private final KwtLogisticsOrderAddressRepository logisticsOrderAddressRepository;
 
     // 定义禁止关联车辆删除的状态集合
     private static final List<Integer> FORBIDDEN_STATUSES = Arrays.asList(
@@ -1412,4 +1414,46 @@ public class TransportServiceImpl implements TransportRemoteService {
         return taskVO;
     }
 
+    @Override
+    public RWaybillOrderVo queryWaybillOrderByWayBillOrderId(Long wayBillOrderId) {
+        KwtWaybillOrder waybillOrder = waybillOrderRepository.queryByBillOrderId(wayBillOrderId);
+        if (Objects.isNull(waybillOrder)){
+            return new RWaybillOrderVo();
+        }
+        //查询子运单
+        KwtWaybillOrderSubtask subtasks = waybillOrderSubtaskRepository.queryByWOrderId(waybillOrder.getId());
+        List<KwtLogisticsOrderAddress> addressList =null;
+        if (Objects.nonNull(subtasks) && Objects.nonNull(subtasks.getLOrderId())){
+            addressList = logisticsOrderAddressRepository.queryByLogOrderId(subtasks.getLOrderId());
+        }
+        RWaybillOrderVo rWaybillOrderVo = new RWaybillOrderVo();
+        rWaybillOrderVo.setId(waybillOrder.getId());
+        rWaybillOrderVo.setEntId(waybillOrder.getEntId());
+        rWaybillOrderVo.setLOrderId(waybillOrder.getLOrderId());
+        rWaybillOrderVo.setWOrderNo(waybillOrder.getWOrderNo());
+        rWaybillOrderVo.setType(waybillOrder.getType());
+        rWaybillOrderVo.setTruckId(waybillOrder.getTruckId());
+        rWaybillOrderVo.setTruckNo(waybillOrder.getTruckNo());
+        rWaybillOrderVo.setDriverId(waybillOrder.getDriverId());
+        rWaybillOrderVo.setDriverName(waybillOrder.getDriverName());
+        rWaybillOrderVo.setDriverPhone(waybillOrder.getDriverPhone());
+        rWaybillOrderVo.setDriverIdcard(waybillOrder.getDriverIdcard());
+        rWaybillOrderVo.setStartTime(waybillOrder.getStartTime());
+        rWaybillOrderVo.setEndTime(waybillOrder.getEndTime());
+        rWaybillOrderVo.setStatus(waybillOrder.getStatus());
+        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(addressList)){
+            addressList.forEach(address -> {
+                if (Objects.equals(address.getAddressType(), AddressTypeEnum.SHIPMENT.getCode())){
+                    rWaybillOrderVo.setStartLng(address.getLng());
+                    rWaybillOrderVo.setStartLat(address.getLat());
+                }else if (Objects.equals(address.getAddressType(), AddressTypeEnum.TAKE.getCode())){
+                    rWaybillOrderVo.setEndLng(address.getLng());
+                    rWaybillOrderVo.setEndLat(address.getLat());
+                }
+            });
+        }
+
+        return rWaybillOrderVo;
+    }
+
 }

+ 6 - 1
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/KwtVehicleException.java

@@ -44,7 +44,12 @@ public class KwtVehicleException implements Serializable {
      */
     @TableField("truck_no")
     private String truckNo;
-    
+
+    /**
+     * 运单ID
+     */
+    @TableField("w_order_id")
+    private Long wOrderId;
     /**
      * 运单号
      */

+ 25 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/vo/MapVehicleVo.java

@@ -1,6 +1,7 @@
 package com.sckw.transport.model.vo;
 
 import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
 import lombok.Data;
 
 import java.io.Serial;
@@ -104,4 +105,28 @@ public class MapVehicleVo implements Serializable {
     private String loadAddress;
     @Schema(description = "卸货地址")
     private String unloadAddress;
+
+    /**
+     * 装货地址经度
+     */
+    @Schema(description = "装货地址经度")
+    private String startLng;
+
+    /**
+     * 装货地址纬度
+     */
+    @Schema(description = "装货地址纬度")
+    private String startLat;
+
+    /**
+     * 卸货地址经度
+     */
+    @Schema(description = "卸货地址经度")
+    private String endLng;
+
+    /**
+     * 卸货地址纬度
+     */
+    @Schema(description = "卸货地址纬度")
+    private String endLat;
 }

+ 39 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/vo/VehicleExceptionVo.java

@@ -80,6 +80,11 @@ public class VehicleExceptionVo {
      */
     @Schema(description = "速度(km/h)")
     private String speed;
+    /**
+     * 司机id
+     */
+    @Schema(description = "司机id")
+    private Long driverId;
 
     /**
      * 司机姓名
@@ -91,4 +96,38 @@ public class VehicleExceptionVo {
      */
     @Schema(description = "司机电话")
     private String driverPhone;
+
+    /**
+     * 装货地址
+     */
+    @Schema(description = "装货地址")
+    private String loadAddress;
+    /**
+     * 卸货地址
+     */
+    @Schema(description = "卸货地址")
+    private String unloadAddress;
+    /**
+     * 装货地址经度
+     */
+    @Schema(description = "装货地址经度")
+    private String startLng;
+
+    /**
+     * 装货地址纬度
+     */
+    @Schema(description = "装货地址纬度")
+    private String startLat;
+
+    /**
+     * 卸货地址经度
+     */
+    @Schema(description = "卸货地址经度")
+    private String endLng;
+
+    /**
+     * 卸货地址纬度
+     */
+    @Schema(description = "卸货地址纬度")
+    private String endLat;
 }

+ 14 - 3
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/service/KwtWaybillOrderV1Service.java

@@ -3440,9 +3440,18 @@ public class KwtWaybillOrderV1Service {
         Map<String, KwtWaybillOrderTicket> ticketMap = orderTicketList.stream().collect(
                 Collectors.toMap(ticket -> ticket.getWOrderId() + "-" + ticket.getType(),
                         Function.identity(), (x, y) -> x));
+        //查询字典
+        List<SysDictResDto> sysDictResDtos = remoteSystemService.queryDictByType(DictTypeEnum.PRODUCT_NAME_TYPE.getType());
+        Map<String, SysDictResDto> dictValueAndDictResDtoMap = new HashMap<>();
+        if (CollectionUtils.isNotEmpty(sysDictResDtos)){
+            //字典value映射字典
+            dictValueAndDictResDtoMap = sysDictResDtos.stream()
+                    .collect(Collectors.toMap(SysDictResDto::getValue, Function.identity()));
+
+        }
 
         return getWaybillOrderDetailResp( subtask,billOrder, logOrder, truck, fleet, goods,
-                keyAndAddressMap,kwpGoods,logisticsOrderUnitMap,nodeList,userCacheResDto,billOrders,ticketMap);
+                keyAndAddressMap,kwpGoods,logisticsOrderUnitMap,nodeList,userCacheResDto,billOrders,ticketMap,dictValueAndDictResDtoMap);
     }
 
     @NotNull
@@ -3457,7 +3466,8 @@ public class KwtWaybillOrderV1Service {
                                                                      List<KwtWaybillOrderNode> nodeList,
                                                                      UserCacheResDto userCacheResDto,
                                                                      List<KwtWaybillOrder> billOrders,
-                                                                     Map<String, KwtWaybillOrderTicket> ticketMap) {
+                                                                     Map<String, KwtWaybillOrderTicket> ticketMap,
+                                                                     Map<String, SysDictResDto> dictValueAndDictResDtoMap) {
         WaybillOrderDetailResp waybillOrderDetailResp = new WaybillOrderDetailResp();
         waybillOrderDetailResp.setWaybillOrderId(String.valueOf(billOrder.getId()));
         waybillOrderDetailResp.setWaybillOrderNo(billOrder.getWOrderNo());
@@ -3472,7 +3482,8 @@ public class KwtWaybillOrderV1Service {
         waybillOrderDetailResp.setDriverPhone(billOrder.getDriverPhone());
         waybillOrderDetailResp.setDriverIdCard(billOrder.getDriverIdcard());
         if (Objects.nonNull(kwpGoods)){
-            waybillOrderDetailResp.setGoodsName(kwpGoods.getName()+ "/" +goods.getGoodsType()+"/"+ kwpGoods.getSpec());
+            SysDictResDto sysDictResDto = dictValueAndDictResDtoMap.getOrDefault(goods.getGoodsType(), new SysDictResDto());
+            waybillOrderDetailResp.setGoodsName(kwpGoods.getName()+ "/" +sysDictResDto.getLabel()+"/"+ kwpGoods.getSpec());
         }
         KwtWaybillOrderAddress loadAdd = keyAndAddressMap.getOrDefault(billOrder.getId() + "-" + AddressTypeEnum.SHIPMENT.getCode(), new KwtWaybillOrderAddress());
         waybillOrderDetailResp.setLoadAddress(loadAdd.getDetailAddress());

+ 79 - 6
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/service/VehicleExceptionService.java

@@ -1,16 +1,23 @@
 package com.sckw.transport.service;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.sckw.core.model.enums.AddressTypeEnum;
 import com.sckw.core.web.response.BaseIotResult;
 import com.sckw.core.web.response.result.PageDataResult;
 import com.sckw.transport.api.feign.VehicleTraceClient;
 import com.sckw.transport.api.model.dto.VehicleDataDTO;
 import com.sckw.transport.api.model.dto.VehicleReturnData;
+import com.sckw.transport.model.KwtLogisticsOrderAddress;
 import com.sckw.transport.model.KwtVehicleException;
+import com.sckw.transport.model.KwtWaybillOrderSubtask;
 import com.sckw.transport.model.dto.VehicleExceptionQueryReq;
 import com.sckw.transport.model.enuma.VehicleExceptionTypeEnum;
 import com.sckw.transport.model.vo.VehicleExceptionVo;
+import com.sckw.transport.repository.KwtLogisticsOrderAddressRepository;
 import com.sckw.transport.repository.KwtVehicleExceptionRepository;
+import com.sckw.transport.repository.KwtWaybillOrderSubtaskRepository;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.CollectionUtils;
@@ -19,6 +26,7 @@ import org.springframework.stereotype.Service;
 
 import java.time.LocalDateTime;
 import java.util.*;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 /**
@@ -33,6 +41,8 @@ public class VehicleExceptionService {
     
     private final KwtVehicleExceptionRepository exceptionImageRepository;
     private final VehicleTraceClient vehicleTraceClient;
+    private final KwtWaybillOrderSubtaskRepository waybillOrderSubtaskRepository;
+    private final KwtLogisticsOrderAddressRepository logisticsOrderAddressRepository;
     
     /**
      * 分页查询车辆异常图片信息
@@ -65,11 +75,37 @@ public class VehicleExceptionService {
             
             truckLocationStatusMap = queryVehicleLocationStatus(truckNos);
         }
-        
+        List<Long> waybillOrderNos = records.stream()
+                .map(KwtVehicleException::getWOrderId)
+                .distinct()
+                .collect(Collectors.toList());
+        Map<String, KwtLogisticsOrderAddress> logisticsOrderAddressMap = Maps.newHashMap();
+        Map<Long, KwtWaybillOrderSubtask> waybillOrderSubtaskMap = Maps.newHashMap();
+        if (CollectionUtils.isNotEmpty(waybillOrderNos)){
+            //查询运单
+            List<KwtWaybillOrderSubtask> subtasks = waybillOrderSubtaskRepository.queryByWOrderIds(waybillOrderNos);
+            List<Long> logisticOrderIds = Lists.newArrayList();
+            if (CollectionUtils.isNotEmpty(subtasks)){
+                logisticOrderIds = subtasks.stream().map(KwtWaybillOrderSubtask::getLOrderId)
+                        .distinct()
+                        .collect(Collectors.toList());
+                waybillOrderSubtaskMap = subtasks.stream()
+                        .collect(Collectors.toMap(KwtWaybillOrderSubtask::getWOrderId, Function.identity(), (k1, k2) -> k1));
+            }
+            if (CollectionUtils.isNotEmpty(logisticOrderIds)){
+                //查询地址
+                List<KwtLogisticsOrderAddress> logisticOrderAddresses = logisticsOrderAddressRepository.queryByLogOrderIds(logisticOrderIds);
+                logisticsOrderAddressMap = Optional.ofNullable(logisticOrderAddresses)
+                        .orElse(List.of())
+                        .stream().collect(Collectors.toMap(x -> x.getLOrderId() + "_" + x.getAddressType(), Function.identity(), (k1, k2) -> k1));
+            }
+        }
         // 转换为VO
         final Map<String, Integer> finalLocationStatusMap = truckLocationStatusMap;
+        Map<String, KwtLogisticsOrderAddress> finalLogisticsOrderAddressMap = logisticsOrderAddressMap;
+        Map<Long, KwtWaybillOrderSubtask> finalWaybillOrderSubtaskMap = waybillOrderSubtaskMap;
         List<VehicleExceptionVo> voList = records.stream()
-                .map(image -> buildVehicleExceptionVo(image, finalLocationStatusMap))
+                .map(image -> buildVehicleExceptionVo(image, finalLocationStatusMap,finalWaybillOrderSubtaskMap, finalLogisticsOrderAddressMap))
                 .filter(Objects::nonNull)
                 .collect(Collectors.toList());
         
@@ -91,7 +127,9 @@ public class VehicleExceptionService {
      * @return VO对象
      */
     private VehicleExceptionVo buildVehicleExceptionVo(KwtVehicleException image,
-                                                       Map<String, Integer> locationStatusMap) {
+                                                       Map<String, Integer> locationStatusMap,
+                                                       Map<Long, KwtWaybillOrderSubtask> waybillOrderSubtaskMap ,
+                                                       Map<String, KwtLogisticsOrderAddress> logisticsOrderAddressMap) {
         VehicleExceptionVo vo = new VehicleExceptionVo();
         
         vo.setId(image.getId());
@@ -110,6 +148,7 @@ public class VehicleExceptionService {
         vo.setLatitude(image.getLatitude());
         vo.setLocation(image.getLocation());
         vo.setDescription(image.getDescription());
+        vo.setDriverId(image.getDriverId());
         vo.setDriverName(image.getDriverName());
         vo.setDriverPhone(image.getDriverPhone());
         
@@ -122,7 +161,15 @@ public class VehicleExceptionService {
             vo.setLocationStatus(0);
             vo.setLocationStatusDesc("离线");
         }
-        
+        KwtWaybillOrderSubtask subtask = waybillOrderSubtaskMap.getOrDefault(image.getWOrderId(), new KwtWaybillOrderSubtask());
+        KwtLogisticsOrderAddress loadAdd = logisticsOrderAddressMap.getOrDefault(subtask.getLOrderId() + "_" + AddressTypeEnum.SHIPMENT.getCode(), new KwtLogisticsOrderAddress());
+        KwtLogisticsOrderAddress unLoadAdd = logisticsOrderAddressMap.getOrDefault(subtask.getLOrderId() + "_" + AddressTypeEnum.TAKE.getCode(), new KwtLogisticsOrderAddress());
+        vo.setLoadAddress(loadAdd.getDetailAddress());
+        vo.setStartLng(loadAdd.getLng());
+        vo.setStartLat(loadAdd.getLat());
+        vo.setUnloadAddress(unLoadAdd.getDetailAddress());
+        vo.setEndLng(unLoadAdd.getLng());
+        vo.setEndLat(unLoadAdd.getLat());
         return vo;
     }
     
@@ -189,11 +236,37 @@ public class VehicleExceptionService {
 
             truckLocationStatusMap = queryVehicleLocationStatus(truckNos);
         }
-
+        List<Long> waybillOrderNos = records.stream()
+                .map(KwtVehicleException::getWOrderId)
+                .distinct()
+                .collect(Collectors.toList());
+        Map<String, KwtLogisticsOrderAddress> logisticsOrderAddressMap = Maps.newHashMap();
+        Map<Long, KwtWaybillOrderSubtask> waybillOrderSubtaskMap = Maps.newHashMap();
+        if (CollectionUtils.isNotEmpty(waybillOrderNos)){
+            //查询运单
+            List<KwtWaybillOrderSubtask> subtasks = waybillOrderSubtaskRepository.queryByWOrderIds(waybillOrderNos);
+            List<Long> logisticOrderIds = Lists.newArrayList();
+            if (CollectionUtils.isNotEmpty(subtasks)){
+               logisticOrderIds = subtasks.stream().map(KwtWaybillOrderSubtask::getLOrderId)
+                       .distinct()
+                       .collect(Collectors.toList());
+                waybillOrderSubtaskMap = subtasks.stream()
+                        .collect(Collectors.toMap(KwtWaybillOrderSubtask::getWOrderId, Function.identity(), (k1, k2) -> k1));
+            }
+            if (CollectionUtils.isNotEmpty(logisticOrderIds)){
+                //查询地址
+                List<KwtLogisticsOrderAddress> logisticOrderAddresses = logisticsOrderAddressRepository.queryByLogOrderIds(logisticOrderIds);
+                logisticsOrderAddressMap = Optional.ofNullable(logisticOrderAddresses)
+                        .orElse(List.of())
+                        .stream().collect(Collectors.toMap(x -> x.getLOrderId() + "_" + x.getAddressType(), Function.identity(), (k1, k2) -> k1));
+            }
+        }
         // 转换为VO
         final Map<String, Integer> finalLocationStatusMap = truckLocationStatusMap;
+        Map<String, KwtLogisticsOrderAddress> finalLogisticsOrderAddressMap = logisticsOrderAddressMap;
+        Map<Long, KwtWaybillOrderSubtask> finalWaybillOrderSubtaskMap = waybillOrderSubtaskMap;
         List<VehicleExceptionVo> voList = records.stream()
-                .map(image -> buildVehicleExceptionVo(image, finalLocationStatusMap))
+                .map(image -> buildVehicleExceptionVo(image, finalLocationStatusMap, finalWaybillOrderSubtaskMap, finalLogisticsOrderAddressMap))
                 .filter(Objects::nonNull)
                 .collect(Collectors.toList());
 

+ 4 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/service/kwfTruckTraceService.java

@@ -1253,6 +1253,10 @@ public class kwfTruckTraceService {
         vo.setEnergyType(Objects.isNull(truckVo.getEnergyType())? "":String.valueOf(truckVo.getEnergyType()));
         SysDictResDto dictResDto = energyTypeMap.getOrDefault(String.valueOf(truckVo.getEnergyType()), new SysDictResDto());
         vo.setEnergyTypeDesc(dictResDto.getLabel());
+        vo.setStartLng(loadAdd.getLng());
+        vo.setStartLat(loadAdd.getLat());
+        vo.setEndLng(unLoadAdd.getLng());
+        vo.setEndLat(unLoadAdd.getLat());
         return vo;
     }