Browse Source

轨迹回显转换完成

zhuzhongjie 2 weeks ago
parent
commit
5060d91bc2

+ 1 - 0
package.json

@@ -9,6 +9,7 @@
     "lint": "vue-cli-service lint"
   },
   "dependencies": {
+    "@amap/amap-jsapi-loader": "^1.0.1",
     "@vueuse/core": "^9.1.1",
     "@wangeditor/editor": "^5.1.15",
     "@wangeditor/editor-for-vue": "next",

+ 1 - 1
src/utils/system/filters.js

@@ -37,7 +37,7 @@
     }
   }
 
-  //车颜色
+  //车颜色
   function plateColorFilter(val){
     switch (val) {
       case "1":

+ 5 - 6
src/views/trackManager/abnormalWaybill.vue

@@ -37,10 +37,7 @@
         <el-table-column label="司机姓名" prop="waybill.driverName" width="120"  align="center"></el-table-column>
         <el-table-column label="司机手机号" prop="waybill.driverPhone" width="120" align="center"></el-table-column>
         <el-table-column label="车牌" prop="waybill.plateNumber" width="120" align="center"></el-table-column>
-        <el-table-column label="车辆颜色" align="center" width="100">
-          <template #default="scope">
-            <span>{{ plateColorFilter(scope.row.waybill.plateColor)}}</span>
-          </template>
+        <el-table-column label="车牌颜色" align="center" prop="waybill.plateColor" width="100">
         </el-table-column>
         <el-table-column label="状态" align="center" width="100">
           <template #default="scope">
@@ -76,7 +73,7 @@
     </Card>
     <!-- 查看轨迹 -->
     <Modal v-model="showModal" width="75%" title="查看轨迹">
-      <mapTrack :waybillNum="waybillNum" v-if="showModal"></mapTrack>
+      <mapTrack :waybillNum="waybillNum" :waybill="waybill" v-if="showModal"></mapTrack>
     </Modal>
     <!-- 查看异常 -->
     <Modal v-model="showInfo" width="60%" title="查看异常">
@@ -180,8 +177,10 @@ export default defineComponent({
 
     const showModal = ref(false)
     let waybillNum = ref('')
+    let waybill = ref({}) // 运单数据
     // 查看详情
     function lookTrack(data){
+      waybill.value = data.waybill
       waybillNum.value = data.waybillNum
       showModal.value = true
     }
@@ -198,7 +197,7 @@ export default defineComponent({
 
     return {
       handleSelectionChange,getData,changePage,moment,deleteInfo,TabData,filtInfoData,
-      loading,batchOperation,resetData,exceptionInfo,showInfo,lookInfo,lookTrack,showModal,plateColorFilter,waybillNum
+      loading,batchOperation,resetData,exceptionInfo,showInfo,lookInfo,lookTrack,showModal,plateColorFilter,waybillNum,waybill
     }
   },
 })

+ 7 - 6
src/views/trackManager/deviceAbnormality.vue

@@ -37,10 +37,7 @@
         <el-table-column label="司机姓名" prop="waybill.driverName" width="120"  align="center"></el-table-column>
         <el-table-column label="司机手机号" prop="waybill.driverPhone" width="120" align="center"></el-table-column>
         <el-table-column label="车牌" prop="waybill.plateNumber" width="120" align="center"></el-table-column>
-        <el-table-column label="车辆颜色" align="center" width="100">
-          <template #default="scope">
-            <span>{{ plateColorFilter(scope.row.waybill.plateColor)}}</span>
-          </template>
+        <el-table-column label="车牌颜色" align="center" prop="waybill.plateColor" width="100">
         </el-table-column>
         <el-table-column label="状态" align="center" width="100">
           <template #default="scope">
@@ -76,7 +73,7 @@
     </Card>
     <!-- 查看轨迹 -->
     <Modal v-model="showModal" width="75%" title="查看轨迹">
-      <mapTrack :waybillNum="waybillNum" v-if="showModal"></mapTrack>
+      <mapTrack :waybillNum="waybillNum" :waybill="waybill" v-if="showModal"></mapTrack>
     </Modal>
     <!-- 查看异常 -->
     <Modal v-model="showInfo" width="60%" title="查看异常">
@@ -180,8 +177,12 @@ export default defineComponent({
 
     const showModal = ref(false)
     let waybillNum = ref('')
+    const waybill = ref({}) // 运单数据
     // 查看详情
     function lookTrack(data){
+      console.log(data);
+      
+      waybill.value = data.waybill
       waybillNum.value = data.waybillNum
       showModal.value = true
     }
@@ -198,7 +199,7 @@ export default defineComponent({
 
     return {
       handleSelectionChange,getData,changePage,moment,deleteInfo,TabData,filtInfoData,
-      loading,batchOperation,resetData,exceptionInfo,showInfo,lookInfo,lookTrack,showModal,plateColorFilter,waybillNum
+      loading,batchOperation,resetData,exceptionInfo,showInfo,lookInfo,lookTrack,showModal,plateColorFilter,waybillNum,waybill
     }
   },
 })

+ 5 - 6
src/views/trackManager/loadDeviation.vue

@@ -37,10 +37,7 @@
         <el-table-column label="司机姓名" prop="waybill.driverName" width="120"  align="center"></el-table-column>
         <el-table-column label="司机手机号" prop="waybill.driverPhone" width="120" align="center"></el-table-column>
         <el-table-column label="车牌" prop="waybill.plateNumber" width="120" align="center"></el-table-column>
-        <el-table-column label="车辆颜色" align="center" width="100">
-          <template #default="scope">
-            <span>{{ plateColorFilter(scope.row.waybill.plateColor)}}</span>
-          </template>
+        <el-table-column label="车牌颜色" align="center" prop="waybill.plateColor" width="100">
         </el-table-column>
         <el-table-column label="状态" align="center" width="100">
           <template #default="scope">
@@ -76,7 +73,7 @@
     </Card>
     <!-- 查看轨迹 -->
     <Modal v-model="showModal" width="75%" title="查看轨迹">
-      <mapTrack :waybillNum="waybillNum" v-if="showModal"></mapTrack>
+      <mapTrack :waybillNum="waybillNum" :waybill="waybill" v-if="showModal"></mapTrack>
     </Modal>
     <!-- 查看异常 -->
     <Modal v-model="showInfo" width="60%" title="查看异常">
@@ -180,8 +177,10 @@ export default defineComponent({
 
     const showModal = ref(false)
     let waybillNum = ref('')
+    const waybill = ref({}) // 运单数据
     // 查看详情
     function lookTrack(data){
+      waybill.value = data.waybill
       waybillNum.value = data.waybillNum
       showModal.value = true
     }
@@ -199,7 +198,7 @@ export default defineComponent({
 
     return {
       handleSelectionChange,getData,changePage,moment,deleteInfo,TabData,filtInfoData,
-      loading,batchOperation,resetData,exceptionInfo,showInfo,lookInfo,lookTrack,showModal,plateColorFilter,waybillNum
+      loading,batchOperation,resetData,exceptionInfo,showInfo,lookInfo,lookTrack,showModal,plateColorFilter,waybillNum,waybill
     }
   },
 })

+ 111 - 68
src/views/trackManager/mapTrack.vue

@@ -1,8 +1,4 @@
-/**
-  // author:jiana
-  // time:2025-04-23
-  // desc:运单管理
-*/
+/** // author:jiana // time:2025-04-23 // desc:运单管理 */
 <template>
   <div class="mapTrack">
     <!-- <div class="btnBox">
@@ -16,100 +12,134 @@
           <Button size="small" type="primary" @click="stopAnimation" ghost>停止动画</Button>
         </div>
       </div> -->
+    <!-- 异常停留 -->
+    <div class="abnormal">
+      <div>
+        <span class="abnormal-title">共停留{{ parkArray.length }}次,共停留{{ totalMin }}分钟</span>
+        <el-button size="small" type="primary" @click="showTable = !showTable">查看停留明细</el-button>
+      </div>
+      <el-table :data="parkArray" style="width: 100%" border stripe size="small" v-if="showTable">
+        <el-table-column prop="parkBte" label="停留开始" width="180">
+          <template #default="scope">
+            {{ moment(Number(scope.row.parkBte)).format('yyyy-MM-DD hh:mm:ss') }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="parkMins" label="停留时长(分钟)" width="180"></el-table-column>
+        <el-table-column prop="parkAdr" label="停留地址"></el-table-column>
+      </el-table>
+    </div>
     <div id="container"></div>
   </div>
 </template>
 <script>
-import { defineComponent, ref ,reactive, onMounted} from 'vue'
-import {useRoute} from 'vue-router'
-import AMapLoader from "@amap/amap-jsapi-loader";
-import axios from 'axios';
+import { defineComponent, ref, reactive, onMounted } from 'vue'
+import { useRoute } from 'vue-router'
+import AMapLoader from '@amap/amap-jsapi-loader'
 import { tms } from '@/request/api'
+import { transformFromWGSToGCJArr } from './utils'
+import moment from 'moment'
 export default defineComponent({
-  components:{
-    
-  },
-  props:{
-    waybillNum: { type: String, default: "" }
+  components: {},
+  props: {
+    waybillNum: { type: String, default: '' },
+    waybill: { type: Object, default: () => {} },
   },
   setup(props) {
     const route = useRoute()
-    const data = ref(null);
-    const trajectory = ref([]);
-    const loadData = async () =>{
+    const data = ref(null)
+    const trajectory = ref([])
+    const parkArray = ref([])
+    const totalMin = ref(0)
+    const showTable = ref(false)
+    const loadData = async () => {
       trajectory.value = []
-      await tms.truckTrackQueryByWaybillNum({waybillNum:props.waybillNum}).then(res =>{
+      await tms.truckTrackQueryByWaybillNum({ waybillNum: props.waybillNum }).then(res => {
         if (res.code == 101) {
+          console.log(res.data)
           data.value = res.data
-          if(data.value.obj && data.value.obj.runRoute){
-            data.value.obj.runRoute.forEach(item => {
+          if (data.value.result && data.value.result.trackArray) {
+            parkArray.value = data.value.result.parkArray
+            parkArray.value = [
+              {
+                parkMins: '25',
+                parkBte: '1698679428000',
+                parkEte: '1698680928000',
+                parkLon: '69776406',
+                parkLat: '24056355',
+                parkAdr: '北京市昌平区朱辛庄西口正东方向 170 米北京博亚金源科贸有限责任公司,西北方向,68.0 米',
+              },
+            ]
+            parkArray.value.forEach(item => {
+              totalMin.value += Number(item.parkMins)
+            })
+            data.value.result.trackArray.forEach(item => {
               if (!isNaN(item.lon) && !isNaN(item.lat)) {
-                trajectory.value.push([Number(item.lon),Number(item.lat)])
+                trajectory.value.push(transformFromWGSToGCJArr(Number(item.lon) / 600000, Number(item.lat) / 600000))
               }
-            });
+            })
           }
         }
       })
     }
 
-    const getMap = () =>{
+    const getMap = () => {
       AMapLoader.load({
         key: '81a1282308f1aae58082425a1ebb91b0',
         version: '2.0',
-        plugins: ['AMap.MoveAnimation']
-      }).then(AMap => {
-        AMap.plugin('AMap.MoveAnimation', () => {
-          var map = new AMap.Map('container', {
-            center: trajectory.value[0],
-          });
-          // 起点
-          var marker = new AMap.Marker({
-            map: map,
-            position: trajectory.value[0],
-            icon: require('@/assets/images/qidian.png'), // 自定义图标
-            offset: new AMap.Pixel(-13, -26),
-          });
-          // 终点
-          var markerEnd = new AMap.Marker({
-            map: map,
-            position: trajectory.value.slice(-1).pop(),
-            icon: require('@/assets/images/zhongdian.png'), // 自定义图标
-            offset: new AMap.Pixel(-13, -26),
-          });
-          // 绘制轨迹
-          var polyline = new AMap.Polyline({
-            map: map,
-            path: trajectory.value,
-            showDir:true,
-            strokeColor: "#28F",  //线颜色
-            strokeWeight: 6,      //线宽
-          });
-          map.setFitView();
-          map.setZoom(7);
-        });
-      }).catch(e => {
-        console.error(e);
-      });
+        plugins: ['AMap.MoveAnimation'],
+      })
+        .then(AMap => {
+          AMap.plugin('AMap.MoveAnimation', () => {
+            var map = new AMap.Map('container', {
+              center: trajectory.value[0],
+            })
+            // 起点
+            var marker = new AMap.Marker({
+              map: map,
+              position: [props.waybill.originLng, props.waybill.originLat],
+              icon: require('@/assets/images/qidian.png'), // 自定义图标
+              offset: new AMap.Pixel(-13, -26),
+            })
+            // 终点
+            var markerEnd = new AMap.Marker({
+              map: map,
+              position: [props.waybill.destinationLng, props.waybill.destinationLat],
+              icon: require('@/assets/images/zhongdian.png'), // 自定义图标
+              offset: new AMap.Pixel(-13, -26),
+            })
+            // 绘制轨迹
+            var polyline = new AMap.Polyline({
+              map: map,
+              path: trajectory.value,
+              showDir: true,
+              strokeColor: '#28F', //线颜色
+              strokeWeight: 6, //线宽
+            })
+            map.setFitView()
+            // map.setZoom(7)
+          })
+        })
+        .catch(e => {
+          console.error(e)
+        })
     }
-    onMounted(async ()=>{
+    onMounted(async () => {
       await loadData()
       await getMap()
     })
-    return {
-      
-    }
+    return { parkArray, totalMin, showTable, trajectory, data, moment }
   },
 })
 </script>
 
 <style lang="scss" scoped>
-.mapTrack{
+.mapTrack {
   // padding: 20px;
-  #container{
-    width: 100%; 
+  #container {
+    width: 100%;
     height: 460px;
   }
-  .btnBox{
+  .btnBox {
     position: absolute;
     top: 70px;
     left: 20px;
@@ -120,15 +150,28 @@ export default defineComponent({
     padding: 10px;
     border-radius: 5px;
   }
+  .abnormal {
+    text-align: right;
+    position: absolute;
+    width: 50%;
+    top: 70px;
+    right: 15px;
+    padding: 5px;
+    z-index: 10;
+    &-title {
+      padding: 5px;
+      background: #fff;
+    }
+  }
 }
 </style>
 <style lang="scss">
-.amap-icon{
+.amap-icon {
   width: 40px !important;
   height: 40px !important;
 }
-.amap-icon img{
+.amap-icon img {
   width: 40px !important;
   height: 40px !important;
 }
-</style>
+</style>

+ 174 - 0
src/views/trackManager/utils.js

@@ -0,0 +1,174 @@
+/**
+ *  判断经纬度是否超出中国境内
+ */
+function isLocationOutOfChina(longitude, latitude) {
+  if (longitude < 72.004 || longitude > 137.8347 || latitude < 0.8293 || latitude > 55.8271)
+    return true;
+  return false;
+}
+
+
+/**
+ *  将WGS-84(国际标准)转为GCJ-02(火星坐标):
+ */
+function transformFromWGSToGCJ(longitude, latitude) {
+  var lat = "";
+  var lon = "";
+  var ee = 0.00669342162296594323;
+  var a = 6378245.0;
+  var pi = 3.14159265358979324;
+
+  if (isLocationOutOfChina(longitude, latitude)) {
+    lat = latitude;
+    lon = longitude;
+  }
+  else {
+    var adjustLat = transformLatWithXY(longitude - 105.0, latitude - 35.0);
+    var adjustLon = transformLonWithXY(longitude - 105.0, latitude - 35.0);
+    var radLat = latitude / 180.0 * pi;
+    var magic = Math.sin(radLat);
+    magic = 1 - ee * magic * magic;
+    var sqrtMagic = Math.sqrt(magic);
+    adjustLat = (adjustLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
+    adjustLon = (adjustLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
+    latitude = latitude + adjustLat;
+    longitude = longitude + adjustLon;
+  }
+  return { latitude: latitude, longitude: longitude };
+
+}
+
+function transformFromWGSToGCJArr(longitude, latitude) {
+  var lat = "";
+  var lon = "";
+  var ee = 0.00669342162296594323;
+  var a = 6378245.0;
+  var pi = 3.14159265358979324;
+
+  if (isLocationOutOfChina(longitude, latitude)) {
+    lat = latitude;
+    lon = longitude;
+  }
+  else {
+    var adjustLat = transformLatWithXY(longitude - 105.0, latitude - 35.0);
+    var adjustLon = transformLonWithXY(longitude - 105.0, latitude - 35.0);
+    var radLat = latitude / 180.0 * pi;
+    var magic = Math.sin(radLat);
+    magic = 1 - ee * magic * magic;
+    var sqrtMagic = Math.sqrt(magic);
+    adjustLat = (adjustLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
+    adjustLon = (adjustLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
+    latitude = latitude + adjustLat;
+    longitude = longitude + adjustLon;
+  }
+  return [longitude, latitude]
+}
+
+/**
+ *  将GCJ-02(火星坐标)转为百度坐标(DB-09):
+ */
+function transformFromGCJToBaidu(longitude, latitude) {
+  var pi = 3.14159265358979324 * 3000.0 / 180.0;
+
+  var z = Math.sqrt(longitude * longitude + latitude * latitude) + 0.00002 * Math.sin(latitude * pi);
+  var theta = Math.atan2(latitude, longitude) + 0.000003 * Math.cos(longitude * pi);
+  var a_latitude = (z * Math.sin(theta) + 0.006);
+  var a_longitude = (z * Math.cos(theta) + 0.0065);
+
+  return { latitude: a_latitude, longitude: a_longitude };
+}
+
+/**
+ *  将百度坐标(DB-09)转为GCJ-02(火星坐标):
+ */
+function transformFromBaiduToGCJ(longitude, latitude) {
+  var xPi = 3.14159265358979323846264338327950288 * 3000.0 / 180.0;
+
+  var x = longitude - 0.0065;
+  var y = latitude - 0.006;
+  var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * xPi);
+  var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * xPi);
+  var a_latitude = z * Math.sin(theta);
+  var a_longitude = z * Math.cos(theta);
+
+  return { latitude: a_latitude, longitude: a_longitude };
+}
+
+/**
+ *  将GCJ-02(火星坐标)转为WGS-84(国际标准):
+ */
+function transformFromGCJToWGS(longitude, latitude) {
+  var threshold = 0.00001;
+
+  // The boundary
+  var minLat = latitude - 0.5;
+  var maxLat = latitude + 0.5;
+  var minLng = longitude - 0.5;
+  var maxLng = longitude + 0.5;
+
+  var delta = 1;
+  var maxIteration = 30;
+
+  while (true) {
+    var leftBottom = transformFromWGSToGCJ(minLat, minLng);
+    var rightBottom = transformFromWGSToGCJ(minLat, maxLng);
+    var leftUp = transformFromWGSToGCJ(maxLat, minLng);
+    var midPoint = transformFromWGSToGCJ((minLat + maxLat) / 2, (minLng + maxLng) / 2);
+    delta = Math.abs(midPoint.latitude - latitude) + Math.abs(midPoint.longitude - longitude);
+
+    if (maxIteration-- <= 0 || delta <= threshold) {
+      return { latitude: (minLat + maxLat) / 2, longitude: (minLng + maxLng) / 2 };
+    }
+
+    if (isContains({ latitude: latitude, longitude: longitude }, leftBottom, midPoint)) {
+      maxLat = (minLat + maxLat) / 2;
+      maxLng = (minLng + maxLng) / 2;
+    }
+    else if (isContains({ latitude: latitude, longitude: longitude }, rightBottom, midPoint)) {
+      maxLat = (minLat + maxLat) / 2;
+      minLng = (minLng + maxLng) / 2;
+    }
+    else if (isContains({ latitude: latitude, longitude: longitude }, leftUp, midPoint)) {
+      minLat = (minLat + maxLat) / 2;
+      maxLng = (minLng + maxLng) / 2;
+    }
+    else {
+      minLat = (minLat + maxLat) / 2;
+      minLng = (minLng + maxLng) / 2;
+    }
+  }
+
+}
+
+function isContains(point, p1, p2) {
+  return (point.latitude >= Math.min(p1.latitude, p2.latitude) && point.latitude <= Math.max(p1.latitude, p2.latitude)) && (point.longitude >= Math.min(p1.longitude, p2.longitude) && point.longitude <= Math.max(p1.longitude, p2.longitude));
+}
+
+function transformLatWithXY(x, y) {
+  var pi = 3.14159265358979324;
+  var lat = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
+  lat += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
+  lat += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
+  lat += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
+  return lat;
+}
+
+function transformLonWithXY(x, y) {
+  var pi = 3.14159265358979324;
+  var lon = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
+  lon += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
+  lon += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
+  lon += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0 * pi)) * 2.0 / 3.0;
+  return lon;
+}
+
+
+
+module.exports = {
+  isLocationOutOfChina: isLocationOutOfChina,
+  transformFromWGSToGCJ: transformFromWGSToGCJ,
+  transformFromGCJToBaidu: transformFromGCJToBaidu,
+  transformFromBaiduToGCJ: transformFromBaiduToGCJ,
+  transformFromGCJToWGS: transformFromGCJToWGS,
+  transformFromWGSToGCJArr: transformFromWGSToGCJArr,
+}

+ 5 - 6
src/views/trackManager/waybillManager.vue

@@ -37,10 +37,7 @@
         <el-table-column label="司机姓名" prop="driverName" width="120"  align="center"></el-table-column>
         <el-table-column label="司机手机号" prop="driverPhone" width="120" align="center"></el-table-column>
         <el-table-column label="车牌" prop="plateNumber" width="120" align="center"></el-table-column>
-        <el-table-column label="车辆颜色" align="center" width="100">
-          <template #default="scope">
-            <span>{{ plateColorFilter(scope.row.plateColor)}}</span>
-          </template>
+        <el-table-column label="车牌颜色" align="center" prop="plateColor" width="100">
         </el-table-column>
         <el-table-column label="状态" align="center" width="100">
           <template #default="scope">
@@ -74,7 +71,7 @@
       </div>
     </Card>
     <Modal v-model="showModal" width="75%" title="查看轨迹">
-      <mapTrack :waybillNum="waybillNum" v-if="showModal"></mapTrack>
+      <mapTrack :waybillNum="waybillNum" :waybill="waybill" v-if="showModal"></mapTrack>
     </Modal>
   </div>
 </template>
@@ -158,8 +155,10 @@ export default defineComponent({
     }
     const showModal = ref(false)
     let waybillNum = ref('')
+    let waybill = ref({}) // 运单数据
     // 查看详情
     function lookTrack(data){
+      waybill.value = data
       waybillNum.value = data.waybillNum
       showModal.value = true
     }
@@ -174,7 +173,7 @@ export default defineComponent({
     })
     return {
       handleSelectionChange,getData,changePage,moment,deleteInfo,TabData,filtInfoData,
-      loading,batchOperation,resetData,lookTrack,showModal,wayBillStatus,plateColorFilter,waybillNum
+      loading,batchOperation,resetData,lookTrack,showModal,wayBillStatus,plateColorFilter,waybillNum,waybill
     }
   },
 })