Browse Source

fix: 调整地图干线协调和勤务路线展示数据贴合实际

sequoia tungfang 4 weeks ago
parent
commit
ec5f2272e2
1 changed files with 128 additions and 101 deletions
  1. 128 101
      src/components/TongzhouTrafficMap.vue

+ 128 - 101
src/components/TongzhouTrafficMap.vue

@@ -58,6 +58,9 @@ export default {
       map: null,
       infoWindow: null,
 
+      trafficLayer: null, // 存储交通图层实例
+      isTrafficVisible: true, // 控制开关状态
+
       routeGroups: {},
       polylines: [],
       privateStyle: {
@@ -230,16 +233,16 @@ export default {
       const dutyData = this.dutyRoutes.flat();
       // 排除路线数据后,剩余数据分配给其他状态
       const remainingData = this.intersectionData;
-      
+
       const normalStatusCount = 6;
       const abnormalStatusCount = 3;
       const chunkSize = Math.floor(remainingData.length / (normalStatusCount + abnormalStatusCount));
       const maxAbnormalCount = 10;
 
       this.statusIntersections = {
-        "中心计划": remainingData.slice(0, chunkSize),
-        "干线协调": trunkData,
-        "勤务路线": dutyData,
+        "中心计划": remainingData.slice(0, 20),
+        "干线协调": [], // 清空,改为动态生成
+        "勤务路线": [], // 清空,改为动态生成
         "定周期控制": remainingData.slice(chunkSize, chunkSize * 2),
         "感应控制": remainingData.slice(chunkSize * 2, chunkSize * 3),
         "自适应控制": remainingData.slice(chunkSize * 3, chunkSize * 4),
@@ -286,25 +289,38 @@ export default {
     async initAMap() {
       if (this._isDestroyed) return;
 
+      // 确保在加载前注入
       window._AMapSecurityConfig = { securityJsCode: this.securityJsCode };
+
       try {
-        // 固定加载需要的插件
         const AMap = await AMapLoader.load({
           key: this.amapKey,
           version: "2.0",
+          // 核心:确保 Driving 插件在此加载
           plugins: ['AMap.Driving']
         });
 
-        // 异步回来后,首先检查组件是否还在
         if (this._isDestroyed) return;
 
         this.AMap = AMap;
         this.map = new AMap.Map(this.$refs.mapContainer, {
-          zoom: 14.5,
+          zoom: 13.8,
           mapStyle: "amap://styles/darkblue",
-          center: [116.663, 39.905],
+          center: [116.663, 39.905], // 通州区中心
+        });
+
+        this.trafficLayer = new AMap.TileLayer.Traffic({
+          autoRefresh: true, // 是否自动刷新,默认为false
+          interval: 180,     // 刷新间隔,单位秒
+          zIndex: 10         // 确保交通线在底层,勤务/干线协调线(zIndex: 15)在其上方
         });
 
+        // 如果默认开启,则添加
+        if (this.isTrafficVisible) {
+          this.map.add(this.trafficLayer);
+        }
+
+        // 建议在地图加载完成后再画线
         this.map.on('complete', () => {
           if (!this._isDestroyed) {
             this.drawStaticRoutes();
@@ -315,123 +331,134 @@ export default {
       }
     },
 
-
-
+    // 1. 修改 drawStaticRoutes 方法
     drawStaticRoutes() {
       if (!this.isMapReady()) return;
 
-      this.statusConfig.forEach((config, index) => {
-        // 使用箭头函数保持 this 指向 Vue 实例
-        setTimeout(() => {
-          if (!this.isMapReady()) return;
-
-          try {
-            const intersections = this.statusIntersections[config.name] || [];
-            const markers = [];
-            const polylines = [];
-
-            // 路线逻辑:对于路线类型,按分段创建连接线
-            if (config.name === "干线协调") {
-              this.trunkRoutes.forEach(route => {
-                if (route.length >= 2) {
-                  const path = route.map(item => [item["位置-经度"], item["位置-纬度"]]);
-                  polylines.push(new this.AMap.Polyline({
-                    path: path,
-                    strokeColor: config.color,
-                    strokeWeight: 6,
-                    strokeOpacity: 0.6,
-                    zIndex: 15
-                  }));
-                }
-              });
-            } else if (config.name === "勤务路线") {
-              this.dutyRoutes.forEach(route => {
-                if (route.length >= 2) {
-                  const path = route.map(item => [item["位置-经度"], item["位置-纬度"]]);
-                  polylines.push(new this.AMap.Polyline({
-                    path: path,
-                    strokeColor: config.color,
-                    strokeWeight: 6,
-                    strokeOpacity: 0.6,
-                    zIndex: 15
-                  }));
-                }
-              });
-            }
+      const realRouteConfigs = {
+        "干线协调": [
+          { start: [116.6421, 39.9172], end: [116.6825, 39.9172], color: "#13C373" },
+          { start: [116.6432, 39.9071], end: [116.6833, 39.9071], color: "#13C373" },
+          { start: [116.6445, 39.8975], end: [116.6846, 39.8975], color: "#13C373" }
+        ],
+        "勤务路线": [
+          { start: [116.6521, 39.9225], end: [116.6521, 39.8971], color: "#BC301D" },
+          { start: [116.6734, 39.9225], end: [116.6734, 39.8971], color: "#BC301D" },
+          { start: [116.6850, 39.9170], end: [116.6850, 39.9000], color: "#BC301D" }
+        ]
+      };
+
+      this.statusConfig.forEach((config) => {
+        // 1. 处理普通非路线状态(从 mock 数据加载)
+        if (!realRouteConfigs[config.name]) {
+          const intersections = this.statusIntersections[config.name] || [];
+          const markers = intersections.map(item =>
+            this.createTrafficLightMarker([item["位置-经度"], item["位置-纬度"]], config)
+          ).filter(Boolean);
+          this.routeGroups[config.name] = markers;
+          if (this.activeLegends.includes(config.name)) this.map.add(markers);
+          return;
+        }
+
+        // 2. 处理路线类(干线/特勤)
+        if (!this.routeGroups[config.name]) this.routeGroups[config.name] = [];
+        const driving = new this.AMap.Driving({ map: null, hideMarkers: true });
+
+        realRouteConfigs[config.name].forEach((line, lineIdx) => {
+          driving.search(line.start, line.end, (status, result) => {
+            if (status === 'complete' && result.routes[0]) {
+              const route = result.routes[0];
+              const fullPath = [];
+
+              // 提取完整路径用于画线
+              route.steps.forEach(step => fullPath.push(...step.path));
 
-            // 为每个路口创建标记
-            intersections.forEach((item, idx) => {
-              const position = [item["位置-经度"], item["位置-纬度"]];
-              const markerConfig = {
-                ...config,
-                name: config.name,
-                id: item["路口编号"],
-                road: item["路口名称"],
-                time: new Date().toLocaleString('zh-CN')
-              };
-              markers.push(this.createTrafficLightMarker(position, markerConfig));
-            });
-
-            const overlays = [...markers, ...polylines].filter(Boolean);
-            this.routeGroups[config.name] = overlays;
-
-            if (this.isMapReady() && this.activeLegends.includes(config.name)) {
-              this.map.add(overlays);
+              const polyline = new this.AMap.Polyline({
+                path: fullPath,
+                strokeColor: line.color,
+                strokeWeight: 6, strokeOpacity: 0.8, zIndex: 15
+              });
+              this.routeGroups[config.name].push(polyline);
+
+              // --- 密集点位生成逻辑 ---
+              // 策略:每隔固定步长从全路径 fullPath 中取点,确保视觉上点位均匀且密集
+              const totalPoints = fullPath.length;
+              // Demo 演示建议每条线显示 10-15 个点,根据路径长度动态调整步长
+              const stepSize = Math.max(Math.floor(totalPoints / 12), 1);
+
+              for (let i = 0; i < totalPoints; i += stepSize) {
+                const p = fullPath[i];
+                const marker = this.createTrafficLightMarker([p.lng, p.lat], {
+                  ...config,
+                  id: `MOCK-${config.name.charAt(0)}-${lineIdx}-${i}`,
+                  road: `${config.name}路口-${i}`
+                });
+                if (marker) this.routeGroups[config.name].push(marker);
+              }
+
+              if (this.activeLegends.includes(config.name)) {
+                this.map.add(this.routeGroups[config.name]);
+              }
             }
-          } catch (e) {
-            console.warn('处理路线数据时出错:', e);
-          }
-        }, index * 200);
+          });
+        });
       });
     },
 
-    createTrafficLightMarker(position, config) {
+    createTrafficLightMarker(position, config, type = 'normal') {
       if (!position || !config) return null;
 
       try {
-        const isAbnormal = ["离线", "降级", "故障"].includes(config.name);
         const lng = Number(position[0] || position.lng);
         const lat = Number(position[1] || position.lat);
-
-        // 验证坐标有效性
         if (isNaN(lng) || isNaN(lat)) return null;
 
-        // 3. 【视觉优化】调整 Marker 大小比例
-        // 异常状态图标略大(为了警示),普通点位略小且半透明
-        const size = isAbnormal ? '18px' : '14px';
-        const opacity = isAbnormal ? '1' : '0.85';
-        const shadow = isAbnormal ? `0 0 10px ${config.color || '#999'}` : `0 0 5px ${config.color || '#999'}`;
+        // 状态文字:起、终、或者状态配置的首字母
+        let displayText = config.name ? config.name.charAt(0) : '';
+        if (type === 'start') displayText = '起';
+        if (type === 'end') displayText = '终';
+
+        const isAbnormal = ["离线", "降级", "故障"].includes(config.name);
+
+        // 动态计算尺寸:起终点最大,异常点次之,普通点最小
+        const size = (type === 'start' || type === 'end') ? '22px' : (isAbnormal ? '18px' : '14px');
+
+        // 边框样式:起终点用实白边框
+        const borderStyle = (type === 'start' || type === 'end')
+          ? '2px solid #fff'
+          : '1.5px solid rgba(255,255,255,0.7)';
 
         const marker = new this.AMap.Marker({
           position: [lng, lat],
-          zIndex: isAbnormal ? 110 : 100, // 异常图标显示在更上层
+          // 这里的 type 已经从参数拿到了,不会报错了
+          zIndex: (type === 'start' || type === 'end') ? 120 : (isAbnormal ? 110 : 100),
           content: `
-          <div class="pure-light-node ${isAbnormal ? 'breathe abnormal-node' : ''}"
-              style="
-                width: ${size};
-                height: ${size};
-                background: ${config.color || '#999'};
-                box-shadow: ${shadow};
-                opacity: ${opacity};
-                border: 1.5px solid rgba(255,255,255,0.7);
-                font-size: 12px;
-                display: flex;
-                justify-content: center;
-                align-items: center;
-                color: #fff;
-                padding: 8px;
-              ">
-            <span style="transform: scale(0.7); font-weight: bold;">${config.name.charAt(0)}</span>
-          </div>
-        `,
-          offset: new this.AMap.Pixel(-8, -8),
+            <div class="pure-light-node ${isAbnormal ? 'breathe' : ''}"
+                style="
+                  width: ${size};
+                  height: ${size};
+                  background: ${config.color || '#999'};
+                  box-shadow: 0 0 8px ${config.color};
+                  border: ${borderStyle};
+                  display: flex;
+                  justify-content: center;
+                  align-items: center;
+                  color: #fff;
+                  border-radius: 50%;
+                  cursor: pointer;
+                  padding: 8px;
+                ">
+              <span style="transform: scale(0.8); font-weight: bold; font-size: 12px;">${displayText}</span>
+            </div>
+          `,
+          offset: new this.AMap.Pixel(-11, -11),
           extData: {
             ...config,
             position: [lng, lat],
             statusColor: config.color || '#999',
             statusLabel: isAbnormal ? config.name : "正常运行",
-            road: config.road || '未知路口',
-            time: config.time || new Date().toLocaleString('zh-CN')
+            road: config.road || '规划路口',
+            time: new Date().toLocaleString('zh-CN')
           }
         });