wlzboy
2025-09-24 62a079a15b46925283581f6caaf631b5a4558927
ruoyi-ui/src/views/system/gps/mapNeed.vue
@@ -127,7 +127,7 @@
      // 查询参数
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        pageSize: 1000,
        deviceId: null,
        appId: null,
        sign: null,
@@ -175,12 +175,16 @@
  },
  mounted() {
    // 动态加载百度地图API
    this.loadBMapScript().then(() => {
      this.initMap();
      window.initMapFlag=true;
      if(window.loadGpsList){
        this.drawTrack()
    this.initMap().then((success) => {
      if (success) {
        window.initMapFlag = true;
        if (window.loadGpsList) {
          this.drawTrack();
        }
      }
    }).catch(error => {
      console.error("地图初始化失败", error);
      this.$message.error("地图加载失败,请刷新页面重试");
    });
  },
  methods: {
@@ -191,31 +195,28 @@
          resolve(window.BMap);
          return;
        }
        window.initBMap = () => {
          console.log("百度地图API加载成功");
          // 确保BMap对象完全加载
          setTimeout(() => {
            if (window.BMap && window.BMap.Map) {
              resolve(window.BMap);
            } else {
              reject(new Error("百度地图API加载不完整"));
            }
          }, 100);
        };
        const script = document.createElement("script");
        script.type = "text/javascript";
        script.src =
          "https://api.map.baidu.com/api?v=3.0&ak=n5z5pKfAnaP3fYMR4RJOAQsR1wQ2avAn&callback=initBMap";
        script.onerror = reject;
        document.head.appendChild(script);
        window.initBMap = () => {
          // 加载坐标转换库
          const convertorScript = document.createElement("script");
          convertorScript.type = "text/javascript";
          convertorScript.src =
            "https://api.map.baidu.com/getscript?v=3.0&ak=n5z5pKfAnaP3fYMR4RJOAQsR1wQ2avAn&services=&t=20230101100000";
          convertorScript.onload = () => {
            // 加载坐标转换工具
            const toolsScript = document.createElement("script");
            toolsScript.type = "text/javascript";
            toolsScript.src =
              "https://api.map.baidu.com/library/Convertor/1.4/src/Convertor_min.js";
            toolsScript.onload = () => {
              resolve(window.BMap);
            };
            document.head.appendChild(toolsScript);
          };
          document.head.appendChild(convertorScript);
        script.onerror = (error) => {
          console.error("百度地图API加载失败", error);
          reject(error);
        };
        document.head.appendChild(script);
      });
    },
    /** 查询GPS列表 */
@@ -258,18 +259,55 @@
      const seconds = String(time.getSeconds()).padStart(2, '0');
      return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
    },
    async translatePoints(points) {
      // 将WGS84坐标转换为百度坐标
      var translatePoints = [];
      return new Promise((resolve, reject) => {
    /** 初始化地图 */
    async initMap() {
      try {
        await this.loadBMapScript();
        // 确保DOM元素已经准备好
        await this.$nextTick();
        // 确保BMap对象存在
        if (!window.BMap || !window.BMap.Map) {
          throw new Error("百度地图API未正确加载");
        }
        // 创建地图实例
        this.map = new BMap.Map("mapContainer");
        // 设置地图中心点和缩放级别
        this.map.centerAndZoom(new BMap.Point(116.404, 39.915), 11);
        // 启用滚轮放大缩小
        this.map.enableScrollWheelZoom();
        console.log("地图初始化成功");
        return true;
      } catch (error) {
        console.error("地图初始化失败", error);
        this.$message.error("地图加载失败,请刷新页面重试");
        return false;
      }
    },
    /** 坐标转换方法 */
    translatePoint(point) {
      return new Promise((resolve) => {
        // 使用百度地图API内置的坐标转换
        const convertor = new BMap.Convertor();
        convertor.translate(points, 1, 5, (data) => {
        const pointArr = [];
        pointArr.push(point);
        convertor.translate(pointArr, 1, 5, (data) => {
          if (data.status === 0) {
            translatePoints = data.points;
            resolve(translatePoints);
            resolve(data.points[0]);
          } else {
            // 如果转换失败,返回原始坐标
            resolve(point);
          }
        });
      });
    },
    /** 批量坐标转换 */
    async translatePoints(points) {
      const translatePoints = [];
      for (const point of points) {
        const translatedPoint = await this.translatePoint(point);
        translatePoints.push(translatedPoint);
      }
      return translatePoints;
    },
    /** 搜索按钮操作 */
    handleQuery() {
@@ -285,90 +323,117 @@
      this.resetForm("queryForm");
      this.handleQuery();
    },
    /** 初始化地图 */
    initMap() {
      // 创建地图实例
      this.map = new BMap.Map("mapContainer");
      // 设置地图中心点和缩放级别
      this.map.centerAndZoom(new BMap.Point(116.404, 39.915), 11);
      // 启用滚轮放大缩小
      this.map.enableScrollWheelZoom();
      console.log("initMap 初始化地图")
    /** 计算两点之间的距离(米) */
    getDistance(point1, point2) {
      return this.map.getDistance(point1, point2);
    },
     /** 计算两点之间的距离(米) */
     getDistance(point1, point2) {
        return this.map.getDistance(point1, point2);
      },
      /** 计算两点之间的角度 */
      getAngle(point1, point2) {
        const dx = point2.lng - point1.lng;
        const dy = point2.lat - point1.lat;
        return Math.atan2(dy, dx) * 180 / Math.PI;
      },
    /** 计算两点之间的角度 */
    getAngle(point1, point2) {
      const dx = point2.lng - point1.lng;
      const dy = point2.lat - point1.lat;
      return Math.atan2(dy, dx) * 180 / Math.PI;
    },
    /** 绘制轨迹 */
    async drawTrack() {
      // 清除之前的轨迹
      if (this.polyline) {
        this.map.removeOverlay(this.polyline);
      }
      this.markers.forEach((marker) => {
        this.map.removeOverlay(marker);
      });
      this.markers = [];
      if (this.gpsList.length === 0) {
      // 确保地图实例存在
      if (!this.map) {
        console.error("地图实例未初始化");
        return;
      }
      // 按时间排序
      this.gpsList.sort((a, b) => {
        return new Date(a.collectTime) - new Date(b.collectTime);
      });
      try {
        // 清除之前的轨迹
        if (this.polyline) {
          this.map.removeOverlay(this.polyline);
        }
        this.markers.forEach((marker) => {
          this.map.removeOverlay(marker);
        });
        this.markers = [];
      // 计算当前段落的起始和结束索引
      const startIndex = this.segmentIndex * this.segmentSize;
      const endIndex = Math.min(
        startIndex + this.segmentSize,
        this.gpsList.length
      );
      const currentSegment = this.gpsList.slice(startIndex, endIndex);
        if (this.gpsList.length === 0) {
          return;
        }
      //先获得所有坐标数组
      const originPoints = currentSegment.map(
        (item) => new BMap.Point(item.longitude, item.latitude)
      );
      this.gpsList.sort((a, b) => {
        return new Date(b.collectTime) - new Date(a.collectTime);
      }).forEach(item => {
       item.speed=item.speed/1000;
      });
      //批量转换坐标
      var translatePoints = await this.translatePoints(originPoints);
        // 按时间排序
        this.gpsList.sort((a, b) => {
          return new Date(a.collectTime) - new Date(b.collectTime);
        });
      // 创建轨迹点数组
      const points = translatePoints;
      translatePoints.forEach((item, index) => {
        const bdPoint = item;
        // 计算当前段落的起始和结束索引
        const startIndex = this.segmentIndex * this.segmentSize;
        const endIndex = Math.min(
          startIndex + this.segmentSize,
          this.gpsList.length
        );
        const currentSegment = this.gpsList.slice(startIndex, endIndex);
        // 判断起点和终点是否相同
        const isStartPoint = index === 0;
        const isEndPoint = index === translatePoints.length - 1;
        const isStartEndSame = isStartPoint && isEndPoint &&
          translatePoints[0].lng === translatePoints[translatePoints.length - 1].lng &&
          translatePoints[0].lat === translatePoints[translatePoints.length - 1].lat;
        // 获取所有坐标数组
        const originPoints = currentSegment.map(
          (item) => new BMap.Point(item.longitude, item.latitude)
        );
        this.gpsList.sort((a, b) => {
          return new Date(b.collectTime) - new Date(a.collectTime);
        }).forEach(item => {
          item.speed = item.speed/1000;
        });
        // 只在起点和终点创建标记,且起点和终点不同时才显示起点标记
        if ((isStartPoint && !isStartEndSame) || isEndPoint) {
          let marker;
          let direction=currentSegment[index].direction;
          if (isStartPoint && !isStartEndSame) {
            // 起点显示"起"字
            const label = new BMap.Label("起", {
              offset: new BMap.Size(0, 0),
        // 批量转换坐标
        const translatePoints = await this.translatePoints(originPoints);
        // 创建轨迹点数组
        const points = translatePoints;
        for (let index = 0; index < translatePoints.length; index++) {
          const bdPoint = translatePoints[index];
          // 判断起点和终点是否相同
          const isStartPoint = index === 0;
          const isEndPoint = index === translatePoints.length - 1;
          const isStartEndSame = isStartPoint && isEndPoint &&
            translatePoints[0].lng === translatePoints[translatePoints.length - 1].lng &&
            translatePoints[0].lat === translatePoints[translatePoints.length - 1].lat;
          // 只在起点和终点创建标记,且起点和终点不同时才显示起点标记
          if ((isStartPoint && !isStartEndSame) || isEndPoint) {
            let marker;
            let direction = currentSegment[index].direction;
            if (isStartPoint && !isStartEndSame) {
              // 起点显示"起"字
              const label = new BMap.Label("起", {
                offset: new BMap.Size(0, 0),
                position: bdPoint,
              });
              label.setStyle({
                color: "white",
                fontSize: "12px",
                backgroundColor: "#3388ff",
                border: "none",
                padding: "2px 6px",
                borderRadius: "3px",
              });
              marker = new BMap.Marker(bdPoint, {rotation: direction});
              marker.setLabel(label);
            } else {
              // 终点显示车辆图标
              const myIcon = new BMap.Icon(
                "/car_blue.png",
                new BMap.Size(20, 20),
                {
                  imageSize: new BMap.Size(20, 20),
                  anchor: new BMap.Size(10, 10),
                }
              );
              marker = new BMap.Marker(bdPoint, {
                icon: myIcon,
                rotation: direction,
              });
            }
            // 在车图标上显示车牌
            const label = new BMap.Label(currentSegment[index].vehicleNo, {
              offset: new BMap.Size(0, -25),
              position: bdPoint,
            });
            label.setStyle({
@@ -379,81 +444,56 @@
              padding: "2px 6px",
              borderRadius: "3px",
            });
            marker = new BMap.Marker(bdPoint,{rotation:direction});
            marker.setLabel(label);
          } else {
            // 终点显示车辆图标
            const myIcon = new BMap.Icon(
              "/car_blue.png",
              new BMap.Size(20, 20),
              {
                imageSize: new BMap.Size(20, 20),
                anchor: new BMap.Size(10, 10),
            // 获取地址信息
            const geoc = new BMap.Geocoder();
            geoc.getLocation(bdPoint, (rs) => {
              if (rs && rs.addressComponents) {
                const addComp = rs.addressComponents;
                const address =
                  addComp.province +
                  addComp.city +
                  addComp.district +
                  addComp.street +
                  addComp.streetNumber;
                // 添加点击事件监听器
                marker.addEventListener("click", () => {
                  // 创建信息窗口
                  const infoWindow = new BMap.InfoWindow(
                    `车牌号:${currentSegment[index].vehicleNo}<br/>时间:${currentSegment[index].collectTime}<br/>速度:${
                      currentSegment[index].speed
                    }km/h<br/>方向:${currentSegment[index].direction}°<br/>地址:${address}`
                  );
                  this.map.openInfoWindow(infoWindow, bdPoint);
                });
              }
            );
            marker = new BMap.Marker(bdPoint, {
              icon: myIcon,
              rotation: direction,
            });
            this.map.addOverlay(marker);
            this.markers.push(marker);
          }
          //在车图标上显示车牌
          const label = new BMap.Label(currentSegment[index].vehicleNo, {
            offset: new BMap.Size(0, -25), // 向上偏移25像素
            position: bdPoint,
          });
          label.setStyle({
            color: "white",
            fontSize: "12px",
            backgroundColor: "#3388ff",
            border: "none",
            padding: "2px 6px",
            borderRadius: "3px",
          });
          marker.setLabel(label);
          // 获取地址信息
          const geoc = new BMap.Geocoder();
          geoc.getLocation(bdPoint, (rs) => {
            const addComp = rs.addressComponents;
            const address =
              addComp.province +
              addComp.city +
              addComp.district +
              addComp.street +
              addComp.streetNumber;
            // 添加点击事件监听器
            marker.addEventListener("click", () => {
              // 创建信息窗口
              const infoWindow = new BMap.InfoWindow(
                `车牌号:${currentSegment[index].vehicleNo}<br/>时间:${currentSegment[index].collectTime}<br/>速度:${
                  currentSegment[index].speed
                }km/h<br/>方向:${currentSegment[index].direction}°<br/>地址:${address}`
              );
              this.map.openInfoWindow(infoWindow, bdPoint);
          // 如果是最后一个点,绘制轨迹线
          if (index === currentSegment.length - 1) {
            // 创建轨迹线
            this.polyline = new BMap.Polyline(points, {
              strokeColor: "#3388ff",
              strokeWeight: 5,
              strokeOpacity: 0.8,
              strokeStyle: "solid",
            });
          });
            this.map.addOverlay(this.polyline);
          this.map.addOverlay(marker);
          this.markers.push(marker);
            // 调整地图视野以显示完整轨迹
            this.map.setViewport(points);
          }
        }
        // 如果是最后一个点,绘制轨迹线
        if (index === currentSegment.length - 1) {
          // 创建轨迹线
          this.polyline = new BMap.Polyline(points, {
            strokeColor: "#3388ff",
            strokeWeight: 5,
            strokeOpacity: 0.8,
            strokeStyle: "solid",
          });
          this.map.addOverlay(this.polyline);
          // 调整地图视野以显示完整轨迹
          this.map.setViewport(points);
        }
      });
      } catch (error) {
        console.error("绘制轨迹失败", error);
        this.$message.error("绘制轨迹失败,请刷新页面重试");
      }
    },
    /** 点击表格行 */
    handleRowClick(row) {