From f7ddeac884b4bdc5c608e5f34cf8f3c9d7c5e588 Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期二, 23 九月 2025 09:15:23 +0800
Subject: [PATCH] feat:优化 custome

---
 ruoyi-ui/src/views/system/gps/map.vue |  382 +++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 275 insertions(+), 107 deletions(-)

diff --git a/ruoyi-ui/src/views/system/gps/map.vue b/ruoyi-ui/src/views/system/gps/map.vue
index 854d9b0..6d0035e 100644
--- a/ruoyi-ui/src/views/system/gps/map.vue
+++ b/ruoyi-ui/src/views/system/gps/map.vue
@@ -26,6 +26,8 @@
           range-separator="-"
           start-placeholder="寮�濮嬫棩鏈�"
           end-placeholder="缁撴潫鏃ユ湡"
+          :default-time="['00:00:00', '23:59:59']"
+          @change="handleDateRangeChange"
         ></el-date-picker>
       </el-form-item>
       <el-form-item>
@@ -56,7 +58,9 @@
           >
             <el-table-column label="鏃堕棿" align="center" prop="collectTime" />
             <el-table-column label="閫熷害(km/h)" align="center" prop="speed" />
-            
+            <el-table-column label="缁忓害" align="center" prop="longitude" />
+            <el-table-column label="绾害" align="center" prop="latitude" />
+            <el-table-column label="鏂瑰悜(掳)" align="center" prop="direction" />
           </el-table>
         </el-card>
       </el-col>
@@ -104,7 +108,7 @@
 </template>
 
 <script>
-import { listGps } from "@/api/system/gps";
+import { anonymousList } from "@/api/system/gps";
 
 export default {
   name: "GpsMap",
@@ -126,9 +130,28 @@
       dateRange: [],
       // 鏌ヨ鍙傛暟
       queryParams: {
-        vehicleNo: undefined,
-        orderByColumn: "collect_time",
-        isAsc: "desc",
+        pageNum: 1,
+        pageSize: 1000,
+        deviceId: null,
+        appId: null,
+        sign: null,
+        timestamp: null,
+        vehicleNo: null,
+        beginTime: null,
+        endTime: null
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {
+        vehicleNo: null
+      },
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        vehicleNo: [
+          { required: true, message: "杞︾墝鍙蜂笉鑳戒负绌�", trigger: "blur" }
+        ],
+        dateRange: [
+          { required: true, message: "璇烽�夋嫨鏃堕棿鑼冨洿", trigger: "change" }
+        ]
       },
       // 鍦板浘瀵硅薄
       map: null,
@@ -151,17 +174,56 @@
     };
   },
   created() {
-    // 鑾峰彇URL鍙傛暟涓殑杞︾墝鍙�
-    const vehicleNo = this.$route.query.vehicleNo;
-    if (vehicleNo) {
-      this.queryParams.vehicleNo = vehicleNo;
+    // 鑾峰彇URL鍙傛暟
+    const query = this.$route.query;
+    // if (query.vehicleNo) {
+    //   this.queryParams.vehicleNo = query.vehicleNo;
+    // } else {
+    //   this.$message.error('缂哄皯杞︾墝鍙峰弬鏁�');
+    //   return;
+    // }
+    //鑾峰彇璁㈠崟鍙�
+    this.queryParams.orderId = query.orderId;
+    if(this.queryParams.orderId==null)
+    {
+      this.$message.error('缂哄皯璁㈠崟鍙峰弬鏁�');
+      return;
     }
+
+    // 妫�鏌ユ椂闂村弬鏁�
+    // if (query.beginTime && query.endTime) {
+    //   // 鏍煎紡鍖栨椂闂�
+    //   this.dateRange = [
+    //     this.formatDateTime(query.beginTime),
+    //     this.formatDateTime(query.endTime)
+    //   ];
+    //   this.queryParams.beginTime = this.dateRange[0];
+    //   this.queryParams.endTime = this.dateRange[1];
+    // } else {
+    //   this.$message.error('缂哄皯鏃堕棿鑼冨洿鍙傛暟');
+    //   return;
+    // }
+
+    // 璁剧疆璁よ瘉鍙傛暟
+    if (query.appId) {
+      this.queryParams.appId = query.appId;
+    }
+    if (query.sign) {
+      this.queryParams.sign = query.sign;
+    }
+    if (query.timestamp) {
+      this.queryParams.timestamp = query.timestamp;
+    }
+    
     this.getList();
   },
   mounted() {
     // 鍔ㄦ�佸姞杞界櫨搴﹀湴鍥続PI
-    this.loadBMapScript().then(() => {
-      this.initMap();
+    this.initMap().then(() => {
+      window.initMapFlag = true;
+      if (window.loadGpsList) {
+        this.drawTrack();
+      }
     });
   },
   methods: {
@@ -172,76 +234,155 @@
           resolve(window.BMap);
           return;
         }
+        
+        window.initBMap = () => {
+          console.log("鐧惧害鍦板浘API鍔犺浇鎴愬姛");
+          resolve(window.BMap);
+        };
+
         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);
       });
+    },
+    /** 鏍煎紡鍖栨椂闂� */
+    parseTime(time) {
+      const year = time.getFullYear();
+      const month = String(time.getMonth() + 1).padStart(2, '0');
+      const day = String(time.getDate()).padStart(2, '0');
+      const hours = String(time.getHours()).padStart(2, '0');
+      const minutes = String(time.getMinutes()).padStart(2, '0');
+      const seconds = String(time.getSeconds()).padStart(2, '0');
+      return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
+    },
+    /** 澶勭悊鏃堕棿鏍煎紡 */
+    formatDateTime(dateTimeStr) {
+      if (!dateTimeStr) return '';
+      // 濡傛灉鏃堕棿瀛楃涓蹭笉鍖呭惈绉掞紝娣诲姞绉�
+      if (dateTimeStr.length === 16) { // yyyy-MM-dd HH:mm
+        return dateTimeStr + ':00';
+      }
+      return dateTimeStr;
     },
     /** 鏌ヨGPS鍒楄〃 */
     getList() {
-      this.loading = true;
-      listGps(this.addDateRange(this.queryParams, this.dateRange)).then(
-        (response) => {
-          this.gpsList = response.rows;
-          this.total = response.total;
-          this.loading = false;
+      this.loading = true;      
+      // 鏋勫缓鏌ヨ鍙傛暟
+      const params = {
+        ...this.queryParams
+      };
+
+      // 濡傛灉娌℃湁閫夋嫨鏃堕棿鑼冨洿锛屽垯浣跨敤URL涓殑鏃堕棿
+      // if (!this.dateRange || this.dateRange.length === 0) {
+      //   const query = this.$route.query;
+      //   if (query.beginTime && query.endTime) {
+      //     params.beginTime = query.beginTime;
+      //     params.endTime = query.endTime;
+      //   } else {
+      //     this.$message.error('璇烽�夋嫨鏃堕棿鑼冨洿');
+      //     this.loading = false;
+      //     return;
+      //   }
+      // } else {
+      //   params.beginTime = this.dateRange[0];
+      //   params.endTime = this.dateRange[1];
+      // }
+      
+      anonymousList(params).then(response => {
+        this.gpsList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+        window.loadGpsList=true;
+        if(window.initMapFlag){
           this.drawTrack();
         }
-      );
+      }).catch(error => {
+        this.loading = false;
+        // 鏄剧ず鍙嬪ソ鐨勯敊璇彁绀�
+        if (error.message && error.message.includes("鏈壘鍒拌杞﹁締瀵瑰簲鐨凣PS璁惧")) {
+          this.$message.warning("璇ヨ溅杈嗘殏鏃燝PS璁惧淇℃伅");
+        } else {
+          this.$message.error(error.message || "鏌ヨGPS杞ㄨ抗澶辫触");
+        }
+      });
     },
-    async translatePoints(points) {
-      // 灏哤GS84鍧愭爣杞崲涓虹櫨搴﹀潗鏍�
-      var translatePoints = [];
-      return new Promise((resolve, reject) => {
+    /** 鍧愭爣杞崲鏂规硶 */
+    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() {
+      if (!this.queryParams.vehicleNo) {
+        this.$message.error('璇疯緭鍏ヨ溅鐗屽彿');
+        return;
+      }
+      if (!this.dateRange || this.dateRange.length !== 2) {
+        this.$message.error('璇烽�夋嫨鏃堕棿鑼冨洿');
+        return;
+      }
+      // 鏇存柊鏌ヨ鍙傛暟
+      this.queryParams.beginTime = this.dateRange[0];
+      this.queryParams.endTime = this.dateRange[1];
       this.getList();
     },
     /** 閲嶇疆鎸夐挳鎿嶄綔 */
     resetQuery() {
-      this.dateRange = [];
+      // 閲嶇疆涓哄綋澶╂椂闂磋寖鍥�
+      const today = new Date();
+      const startTime = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0);
+      const endTime = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 23, 59, 59);
+      this.dateRange = [this.parseTime(startTime), this.parseTime(endTime)];
       this.resetForm("queryForm");
+      // 淇濈暀杞︾墝鍙�
+      this.queryParams.vehicleNo = this.$route.query.vehicleNo;
+      // 鏇存柊鏌ヨ鍙傛暟
+      this.queryParams.beginTime = this.dateRange[0];
+      this.queryParams.endTime = this.dateRange[1];
       this.handleQuery();
     },
     /** 鍒濆鍖栧湴鍥� */
-    initMap() {
-      // 鍒涘缓鍦板浘瀹炰緥
-      this.map = new BMap.Map("mapContainer");
-      // 璁剧疆鍦板浘涓績鐐瑰拰缂╂斁绾у埆
-      this.map.centerAndZoom(new BMap.Point(116.404, 39.915), 11);
-      // 鍚敤婊氳疆鏀惧ぇ缂╁皬
-      this.map.enableScrollWheelZoom();
+    async initMap() {
+      try {
+        await this.loadBMapScript();
+        // 鍒涘缓鍦板浘瀹炰緥
+        this.map = new BMap.Map("mapContainer");
+        // 璁剧疆鍦板浘涓績鐐瑰拰缂╂斁绾у埆
+        this.map.centerAndZoom(new BMap.Point(116.404, 39.915), 11);
+        // 鍚敤婊氳疆鏀惧ぇ缂╁皬
+        this.map.enableScrollWheelZoom();
+        console.log("鍦板浘鍒濆鍖栨垚鍔�");
+      } catch (error) {
+        console.error("鍦板浘鍒濆鍖栧け璐�", error);
+        this.$message.error("鍦板浘鍔犺浇澶辫触锛岃鍒锋柊椤甸潰閲嶈瘯");
+      }
     },
      /** 璁$畻涓ょ偣涔嬮棿鐨勮窛绂伙紙绫筹級 */
      getDistance(point1, point2) {
@@ -254,34 +395,7 @@
         return Math.atan2(dy, dx) * 180 / Math.PI;
       },
 
-     /** 鍦ㄤ袱鐐逛箣闂存彃鍏ュ钩婊戠偣 */
-     getSmoothPoints(point1, point2) {
-        const distance = this.getDistance(point1, point2);
-        if (distance < this.minDistance) {
-          return [point1, point2];
-        }
-        
-        const angle = this.getAngle(point1, point2);
-        const midPoint = new BMap.Point(
-          (point1.lng + point2.lng) / 2,
-          (point1.lat + point2.lat) / 2
-        );
-        
-        // 璁$畻鎺у埗鐐�
-        const controlPoint = new BMap.Point(
-          midPoint.lng + this.smoothFactor * distance * Math.cos((angle + 90) * Math.PI / 180),
-          midPoint.lat + this.smoothFactor * distance * Math.sin((angle + 90) * Math.PI / 180)
-        );
-        
-        // 浣跨敤浜屾璐濆灏旀洸绾跨敓鎴愬钩婊戠偣
-        const points = [];
-        for (let t = 0; t <= 1; t += 0.1) {
-          const x = Math.pow(1 - t, 2) * point1.lng + 2 * (1 - t) * t * controlPoint.lng + Math.pow(t, 2) * point2.lng;
-          const y = Math.pow(1 - t, 2) * point1.lat + 2 * (1 - t) * t * controlPoint.lat + Math.pow(t, 2) * point2.lat;
-          points.push(new BMap.Point(x, y));
-        }
-        return points;
-      },
+   
 
     /** 缁樺埗杞ㄨ抗 */
     async drawTrack() {
@@ -311,7 +425,7 @@
       );
       const currentSegment = this.gpsList.slice(startIndex, endIndex);
 
-      //鍏堣幏寰楁墍鏈夊潗鏍囨暟缁�
+      // 鑾峰彇鎵�鏈夊潗鏍囨暟缁�
       const originPoints = currentSegment.map(
         (item) => new BMap.Point(item.longitude, item.latitude)
       );
@@ -319,21 +433,29 @@
       this.gpsList.sort((a, b) => {
         return new Date(b.collectTime) - new Date(a.collectTime);
       }).forEach(item => {
-       item.speed=item.speed/1000;
+        item.speed = item.speed/1000;
       });
-      //鎵归噺杞崲鍧愭爣
-      var translatePoints = await this.translatePoints(originPoints);
+
+      // 鎵归噺杞崲鍧愭爣
+      const translatePoints = await this.translatePoints(originPoints);
 
       // 鍒涘缓杞ㄨ抗鐐规暟缁�
       const points = translatePoints;
       translatePoints.forEach((item, index) => {
         const bdPoint = item;
 
-        // 鍙湪璧风偣鍜岀粓鐐瑰垱寤烘爣璁�
-        if (index === 0 || index === translatePoints.length - 1) {
+        // 鍒ゆ柇璧风偣鍜岀粓鐐规槸鍚︾浉鍚�
+        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 (index === 0) {
+          if (isStartPoint && !isStartEndSame) {
             // 璧风偣鏄剧ず"璧�"瀛�
             const label = new BMap.Label("璧�", {
               offset: new BMap.Size(0, 0),
@@ -347,11 +469,11 @@
               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),
@@ -365,6 +487,20 @@
               rotation: direction,
             });
           }
+          //鍦ㄨ溅鍥炬爣涓婃樉绀鸿溅鐗�
+          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();
@@ -377,13 +513,14 @@
               addComp.street +
               addComp.streetNumber;
 
-            // 娣诲姞淇℃伅绐楀彛
-            const infoWindow = new BMap.InfoWindow(
-              `鏃堕棿锛�${item.collectTime}<br/>閫熷害锛�${
-                item.speed
-              }km/h<br/>鏂瑰悜锛�${item.direction}掳<br/>鍦板潃锛�${address}`
-            );
+            // 娣诲姞鐐瑰嚮浜嬩欢鐩戝惉鍣�
             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);
             });
           });
@@ -391,12 +528,6 @@
           this.map.addOverlay(marker);
           this.markers.push(marker);
         }
-        // const smoothPoints = [];
-        // for (let i = 0; i < points.length - 1; i++) {
-        //   const segmentPoints = this.getSmoothPoints(points[i], points[i + 1]);
-        //   smoothPoints.push(...segmentPoints);
-        // }
-        // smoothPoints.push(points[points.length - 1]);
 
         // 濡傛灉鏄渶鍚庝竴涓偣锛岀粯鍒惰建杩圭嚎
         if (index === currentSegment.length - 1) {
@@ -455,12 +586,25 @@
           });
           marker.setLabel(label);
           
-          // 娣诲姞淇℃伅绐楀彛
-          const infoWindow = new BMap.InfoWindow(
-            `鏃堕棿锛�${row.collectTime}<br/>閫熷害锛�${row.speed}km/h<br/>鏂瑰悜锛�${row.direction}掳<br/>鍦板潃锛�${row.address}`
-          );
-          marker.addEventListener("click", () => {
-            this.map.openInfoWindow(infoWindow, data.points[0]);
+          // 鑾峰彇鍦板潃淇℃伅
+          const geoc = new BMap.Geocoder();
+          geoc.getLocation(data.points[0], (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(
+                `杞︾墝鍙凤細${row.vehicleNo}<br/>鏃堕棿锛�${row.collectTime}<br/>閫熷害锛�${row.speed}km/h<br/>鏂瑰悜锛�${row.direction}掳<br/>鍦板潃锛�${address}`
+              );
+              this.map.openInfoWindow(infoWindow, data.points[0]);
+            });
           });
           
           // 淇濆瓨褰撳墠鏍囪鐐瑰紩鐢�
@@ -537,6 +681,30 @@
       }
       this.isPlaying = false;
     },
+    /** 澶勭悊鏃堕棿鑼冨洿鍙樺寲 */
+    handleDateRangeChange(val) {
+      if (val && val.length === 2) {
+        // 鏍煎紡鍖栨椂闂�
+        this.dateRange = [
+          this.formatDateTime(val[0]),
+          this.formatDateTime(val[1])
+        ];
+        
+        // 妫�鏌ョ粨鏉熸椂闂存槸鍚﹀寘鍚叿浣撴椂闂�
+        const endDate = new Date(this.dateRange[1]);
+        const hasSpecificTime = endDate.getHours() !== 0 || endDate.getMinutes() !== 0;
+        
+        if (!hasSpecificTime) {
+          // 濡傛灉娌℃湁鍏蜂綋鏃堕棿锛岃缃负23:59:59
+          endDate.setHours(23, 59, 59);
+          this.dateRange[1] = this.parseTime(endDate);
+        }
+        
+        // 鏇存柊鏌ヨ鍙傛暟
+        this.queryParams.beginTime = this.dateRange[0];
+        this.queryParams.endTime = this.dateRange[1];
+      }
+    },
   },
   beforeDestroy() {
     this.stopPlayback();

--
Gitblit v1.9.1