USER-20250308PZ\Administrator 8 ay önce
ebeveyn
işleme
665f0aca46

+ 11 - 0
bus-biz/src/main/java/bus/service/BBusInfoService.java

@@ -2,6 +2,7 @@ package bus.service;
 
 import bus.model.dto.*;
 import bus.model.dto.page.BBusInfoPageDto;
+import bus.model.dto.req.BTrackLocalReqDto;
 import bus.model.po.BBusInfoPo;
 import com.baomidou.mybatisplus.extension.service.IService;
 
@@ -67,4 +68,14 @@ public interface BBusInfoService extends IService<BBusInfoPo> {
      */
     BBusTrackInfoDto getTrackInfo(String busId);
 
+
+    /**
+     * 根据车辆ID获取车辆实时追踪信息
+     * @return
+     *
+     * @param bTrackLocalReqDto
+     * @return
+     */
+    BTrackLocalDto getLocalBusInfo(BTrackLocalReqDto bTrackLocalReqDto);
+
 }

+ 202 - 4
bus-biz/src/main/java/bus/service/impl/BBusInfoServiceImpl.java

@@ -3,11 +3,9 @@ package bus.service.impl;
 import bus.model.SnowflakeUtil;
 import bus.model.dto.*;
 import bus.model.dto.page.BBusInfoPageDto;
-import bus.model.po.BCourseBusPo;
-import bus.model.po.BCourseInfoPo;
-import bus.model.po.BCourseStationPo;
+import bus.model.dto.req.BTrackLocalReqDto;
+import bus.model.po.*;
 import bus.model.vo.BBusInfoVo;
-import bus.model.po.BBusInfoPo;
 import bus.mapper.BBusInfoMapper;
 
 import bus.service.*;
@@ -26,6 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.BeanUtils;
 
 import javax.annotation.Resource;
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
@@ -268,6 +267,180 @@ public class BBusInfoServiceImpl extends ServiceImpl<BBusInfoMapper,BBusInfoPo>
         return dto;
     }
 
+    /**
+     * 根据车辆ID获取车辆实时追踪信息
+     * @param bTrackLocalReqDto 车辆位置请求信息
+     * @return 车辆位置和相邻站点信息
+     */
+    @Override
+    public BTrackLocalDto getLocalBusInfo(BTrackLocalReqDto bTrackLocalReqDto) {
+        // 1. 根据车牌号获取车辆信息
+        QueryWrapper<BBusInfoPo> busQuery = new QueryWrapper<>();
+        busQuery.eq("bus_no", bTrackLocalReqDto.getBusNo())
+                .eq("is_delete", 0);
+        BBusInfoPo busInfo = this.getOne(busQuery);
+        if (busInfo == null) {
+            throw new BusinessException("车辆不存在");
+        }
+
+        // 2. 获取车辆所在路线
+        QueryWrapper<BCourseBusPo> courseQuery = new QueryWrapper<>();
+        courseQuery.eq("bus_id", busInfo.getId())
+                .eq("is_delete", 0)
+                .orderByDesc("create_time")
+                .last("LIMIT 1");
+        BCourseBusPo courseBus = bCourseBusService.getOne(courseQuery);
+        if (courseBus == null) {
+            throw new BusinessException("该车辆未分配路线");
+        }
+
+        // 3. 获取路线所有站点
+        List<BCourseStationPo> stationList = bCourseStationService.getListByCourse(courseBus.getCourseId());
+        if (CollectionUtil.isEmpty(stationList)) {
+            throw new BusinessException("路线站点信息不存在");
+        }
+
+        // 4. 获取所有站点信息
+        List<String> stationIds = stationList.stream()
+                .map(BCourseStationPo::getStationId)
+                .collect(Collectors.toList());
+        List<BStationInfoPo> stations = bStationInfoService.listByIds(stationIds);
+
+        // 按路线顺序排序站点
+        Map<String, BStationInfoPo> stationMap = stations.stream()
+                .collect(Collectors.toMap(BStationInfoPo::getId, station -> station));
+        List<BStationInfoPo> orderedStations = stationList.stream()
+                .map(station -> stationMap.get(station.getStationId()))
+                .collect(Collectors.toList());
+
+        // 5. 找出车辆当前位置的前后站点
+        BStationInfoPo prevStation = null;
+        BStationInfoPo nextStation = null;
+        double minDistance = Double.MAX_VALUE;
+        int currentIndex = -1;
+
+        for (int i = 0; i < orderedStations.size() - 1; i++) {
+            BStationInfoPo station1 = orderedStations.get(i);
+            BStationInfoPo station2 = orderedStations.get(i + 1);
+
+            // 计算车辆到这两个站点的距离
+            double dist1 = calculateDistance(
+                bTrackLocalReqDto.getLocalLatitude().doubleValue(),
+                bTrackLocalReqDto.getLocalLongitude().doubleValue(),
+                station1.getLatitude().doubleValue(),
+                station1.getLongitude().doubleValue()
+            );
+            double dist2 = calculateDistance(
+                bTrackLocalReqDto.getLocalLatitude().doubleValue(),
+                bTrackLocalReqDto.getLocalLongitude().doubleValue(),
+                station2.getLatitude().doubleValue(),
+                station2.getLongitude().doubleValue()
+            );
+
+            // 计算车辆是否在这两个站点之间
+            // 使用三角形不等式判断:如果车辆在两站点之间,那么到两站点的距离之和应该接近两站点之间的距离
+            double stationDistance = calculateDistance(
+                station1.getLatitude().doubleValue(),
+                station1.getLongitude().doubleValue(),
+                station2.getLatitude().doubleValue(),
+                station2.getLongitude().doubleValue()
+            );
+
+            double totalDistance = dist1 + dist2;
+            // 允许5%的误差
+            if (Math.abs(totalDistance - stationDistance) < stationDistance * 0.05
+                    && totalDistance < minDistance) {
+                minDistance = totalDistance;
+                prevStation = station1;
+                nextStation = station2;
+                currentIndex = i;
+            }
+        }
+
+        // 6. 构建返回数据
+        BTrackLocalDto result = new BTrackLocalDto();
+
+        // 设置当前位置信息
+        result.setLocalLatitude(bTrackLocalReqDto.getLocalLatitude());
+        result.setLocalLongitude(bTrackLocalReqDto.getLocalLongitude());
+        result.setLocalSpeed(bTrackLocalReqDto.getLocalSpeed());
+
+        if (prevStation != null && nextStation != null) {
+            // 设置站点信息
+            result.setLastStationId(prevStation.getId());
+            result.setLastStationName(prevStation.getName());
+            result.setNextStationId(nextStation.getId());
+            result.setNextStationName(nextStation.getName());
+
+            // 计算到下一站的距离(米)
+            double distanceToNext = calculateDistance(
+                bTrackLocalReqDto.getLocalLatitude().doubleValue(),
+                bTrackLocalReqDto.getLocalLongitude().doubleValue(),
+                nextStation.getLatitude().doubleValue(),
+                nextStation.getLongitude().doubleValue()
+            );
+
+            // 设置到下一站的距离和预计时间
+            result.setToNextStationDistance(String.format("%.0f", distanceToNext));
+
+            // 如果有速度信息,计算预计到达时间
+            if (bTrackLocalReqDto.getLocalSpeed() != null && bTrackLocalReqDto.getLocalSpeed().compareTo(BigDecimal.ZERO) > 0) {
+                // 速度转换为米/秒
+                double speedMps = bTrackLocalReqDto.getLocalSpeed().doubleValue() * 1000 / 3600;
+                // 计算预计时间(秒)
+                int estimatedSeconds = (int) (distanceToNext / speedMps);
+                // 转换为分钟
+                int estimatedMinutes = Math.max(1, estimatedSeconds / 60);
+                result.setToNextStationTime(String.format("%d", estimatedMinutes));
+            }
+
+            // 设置行驶方向(0表示向下,1表示向上)
+            result.setBusDirection("0"); // 因为我们是按照路线顺序遍历的,所以一定是向下
+        } else {
+            // 如果没有找到合适的站点对,找最近的站点
+            BStationInfoPo nearestStation = findNearestStation(
+                bTrackLocalReqDto.getLocalLatitude().doubleValue(),
+                bTrackLocalReqDto.getLocalLongitude().doubleValue(),
+                orderedStations
+            );
+            if (nearestStation != null) {
+                result.setLastStationId(nearestStation.getId());
+                result.setNextStationName(nearestStation.getName());
+                // 设置一个默认距离
+                result.setToNextStationDistance("未知");
+                result.setToNextStationTime("未知");
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * 找出最近的站点
+     */
+    private BStationInfoPo findNearestStation(double lat, double lon, List<BStationInfoPo> stations) {
+        if (CollectionUtil.isEmpty(stations)) {
+            return null;
+        }
+        
+        BStationInfoPo nearest = null;
+        double minDistance = Double.MAX_VALUE;
+        
+        for (BStationInfoPo station : stations) {
+            double distance = calculateDistance(
+                lat, lon,
+                station.getLatitude().doubleValue(),
+                station.getLongitude().doubleValue()
+            );
+            if (distance < minDistance) {
+                minDistance = distance;
+                nearest = station;
+            }
+        }
+        
+        return nearest;
+    }
+
     @Override
     public BTrackStationDto getPoint(String busId) {
         BTrackStationDto dto = new BTrackStationDto();
@@ -309,4 +482,29 @@ public class BBusInfoServiceImpl extends ServiceImpl<BBusInfoMapper,BBusInfoPo>
             }
         }
     }
+
+    /**
+     * 计算两个地理坐标点之间的距离(米)
+     * 使用球面余弦定理计算,计算量更少,对于城市内短距离计算精度足够
+     * @param lat1 第一个点的纬度
+     * @param lon1 第一个点的经度
+     * @param lat2 第二个点的纬度
+     * @param lon2 第二个点的经度
+     * @return 两点之间的距离,单位:米
+     */
+    private double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
+        // 将经纬度转换为弧度
+        lat1 = Math.toRadians(lat1);
+        lon1 = Math.toRadians(lon1);
+        lat2 = Math.toRadians(lat2);
+        lon2 = Math.toRadians(lon2);
+
+        // 使用球面余弦定理计算
+        double distance = Math.acos(
+            Math.sin(lat1) * Math.sin(lat2) +
+            Math.cos(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1)
+        ) * 6371000; // 6371000是地球平均半径(米)
+
+        return distance;
+    }
 }

+ 17 - 4
bus-common/src/main/java/bus/model/dto/BTrackLocalDto.java

@@ -9,13 +9,26 @@ import java.math.BigDecimal;
 public class BTrackLocalDto
 {
     @ApiModelProperty("上一个标记点id")
-    private String upStationId;
+    private String lastStationId;
     @ApiModelProperty("上一个标记点名称")
-    private String upStationName;
+    private String lastStationName;
     @ApiModelProperty("下个标记点id")
-    private String downStationId;
+    private String nextStationId;
     @ApiModelProperty("上一个标记点名称")
-    private String downStationName;
+    private String nextStationName;
     @ApiModelProperty("当前")
     private BigDecimal localSpeed;
+    @ApiModelProperty("当前方向 0向下 1向上")
+    private String busDirection;
+    @ApiModelProperty("当前经度")
+    private BigDecimal localLongitude;
+    @ApiModelProperty("当前纬度")
+    private BigDecimal localLatitude;
+    @ApiModelProperty("详细地址")
+    private String detailAddress;
+    @ApiModelProperty("离下一个标记点距离")
+    private String toNextStationDistance;
+    @ApiModelProperty("离下一个标记点时间")
+    private String toNextStationTime;
+
 }

+ 4 - 1
bus-common/src/main/java/bus/model/dto/req/BTrackLocalReqDto.java

@@ -13,5 +13,8 @@ public class BTrackLocalReqDto
     @ApiModelProperty("当前纬度")
     private BigDecimal localLatitude;
     @ApiModelProperty("当前速度")
-    private BigDecimal localSpeed; 
+    private BigDecimal localSpeed;
+    @ApiModelProperty("车辆编号")
+    private String busNo;
+
 }

+ 9 - 15
bus-web/src/main/java/bus/controller/biz/BBusLocationController.java

@@ -1,6 +1,8 @@
 package bus.controller.biz;
 
 import bus.model.dto.BBusTrackByBusDto;
+import bus.model.dto.BTrackLocalDto;
+import bus.model.dto.req.BTrackLocalReqDto;
 import bus.service.BBusInfoService;
 import com.qzwisdom.qzframework.core.tool.base.controller.BaseController;
 import io.swagger.annotations.Api;
@@ -27,19 +29,11 @@ public class BBusLocationController implements BaseController {
     @Autowired
     private BBusInfoService bBusInfoService;
 
-//    @ApiOperation("更新车辆实时位置")
-//    @PostMapping(value = "updateLocation")
-//    public void updateLocation(
-//            @RequestParam String busId,
-//            @RequestParam BigDecimal longitude,
-//            @RequestParam BigDecimal latitude,
-//            @RequestParam(required = false) String address) {
-//        bBusInfoService.updateLocation(busId, longitude, latitude, address);
-//    }
-//
-//    @ApiOperation("获取车辆当前位置信息")
-//    @GetMapping(value = "getCurrentLocation")
-//    public BBusTrackByBusDto getCurrentLocation(@RequestParam String busId) {
-//        return bBusInfoService.getCurrentLocation(busId);
-//    }
+
+
+    @ApiOperation("获取车辆实时追踪信息")
+    @PostMapping(value = "getLocalBusInfo")
+    public BTrackLocalDto getLocalBusInfo(@RequestBody BTrackLocalReqDto reqDto) {
+        return bBusInfoService.getLocalBusInfo(reqDto);
+    }
 }