瀏覽代碼

新增轨迹查询页面

zhuzhongjie 1 周之前
父節點
當前提交
445a73f8f9
共有 3 個文件被更改,包括 282 次插入1 次删除
  1. 4 0
      src/request/modules/apiTms.js
  2. 15 1
      src/router/modules/pages.js
  3. 263 0
      src/views/trajectoryQuery/index.vue

+ 4 - 0
src/request/modules/apiTms.js

@@ -13,6 +13,10 @@ export const queryWaybillExceptionByCondition = (params) => res('post', 'apiTms'
 //查询轨迹
 export const truckTrackQueryByWaybillNum = (params) => res('post', 'apiTms', '/transwiseway/truckTrackQueryByWaybillNum',params,{form:true})
 
+// ### 查询时间段的运输轨迹以及停留时长
+export const truckTrackQuery = (params) => res('post', 'apiTms', '/transwiseway/truckTrackQuery',params,{form:true})
+
+
 //供应商仓库列表
 export const warehouseList = (params) => res('post', 'apiTms', '/warehouse/review',params,{form:true})
 

+ 15 - 1
src/router/modules/pages.js

@@ -61,7 +61,7 @@ const route = [
   {
     path: '/configManager',
     component: Layout,
-    redirect: 'trackManager/configManager',
+    redirect: 'configManager/configManager',
     meta: { title: '收发货地范围管理', icon: 'icon-shezhi' },
     children: [
       {
@@ -70,6 +70,20 @@ const route = [
         meta: { title: '收发货地范围管理', cache: false,icon: 'icon-shezhi' },
       }
     ]
+  },
+  // 车辆运单轨迹查询
+  {
+    path: '/trajectoryQuery',
+    component: Layout,
+    redirect: 'trajectoryQuery/trajectoryQuery',
+    meta: { title: '车辆运单轨迹查询', icon: 'icon-fabu' },
+    children: [
+      {
+        path: 'trajectoryQuery',
+        component: createNameComponent(() => import('@/views/trajectoryQuery/index.vue')),
+        meta: { title: '车辆运单轨迹查询', cache: false,icon: 'icon-fabu' },
+      }
+    ]
   }
 ]
 

+ 263 - 0
src/views/trajectoryQuery/index.vue

@@ -0,0 +1,263 @@
+/** // author:jiana // time:2025-04-23 // desc:运单管理 */
+<template>
+  <div class="mapMark">
+    <div class="btnBox">
+      <el-form :model="form" :rules="rules" label-width="auto">
+        <el-row>
+          <el-col :span="4">
+            <!-- 车牌号 -->
+            <el-form-item label="车牌号" prop="licensePlateNo">
+              <el-autocomplete
+                v-model="form.licensePlateNo"
+                :fetch-suggestions="querySearch"
+                clearable
+                placeholder="请输入车牌号"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="4">
+            <!-- 车牌颜色 -->
+            <el-form-item label="车牌颜色" prop="licensePlateColor">
+              <el-select clearable v-model="form.licensePlateColor" placeholder="请选择车牌颜色">
+                <el-option
+                  v-for="item in licensePlateColorList"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                ></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <!-- 时间范围 -->
+            <!-- 限制结束时间在开始时间三天内 -->
+            <el-form-item label="时间范围" prop="timeRange">
+              <el-date-picker
+                clearable
+                v-model="form.startTime"
+                type="datetime"
+                placeholder="开始日期"
+                value-format="YYYY-MM-DD HH:mm:ss"
+              ></el-date-picker>
+              <el-date-picker
+                clearable
+                v-model="form.endTime"
+                :disabled-date="disabledDateFn"
+                type="datetime"
+                placeholder="结束日期"
+                value-format="YYYY-MM-DD HH:mm:ss"
+              ></el-date-picker>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <!-- 查询按钮 -->
+            <el-form-item>
+              <el-button type="primary" @click="queryWaybill">查询轨迹</el-button>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+    </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="container3"></div>
+  </div>
+</template>
+<script setup>
+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 { Message, Modal, Spin } from 'view-ui-plus'
+import { transformFromWGSToGCJArr } from '../trackManager/utils.js'
+
+// 限制选择的结束时间必须在选择的开始时间后的三天内
+const disabledDateFn = time => {
+  const startTime = new Date(form.value.startTime)
+  const endTime = new Date(time)
+  const diffTime = endTime - startTime
+  return diffTime > 3 * 24 * 60 * 60 * 1000
+}
+const route = useRoute()
+const trajectory = ref([])
+const tabPosition = ref('load')
+const map = ref(null)
+const form = ref({})
+const rules = {
+  licensePlateNo: [{ required: true, message: '请输入车牌号', trigger: 'blur' }],
+  licensePlateColor: [{ required: true, message: '请选择车牌颜色', trigger: 'change' }],
+}
+const licensePlateColorList = [
+  { label: '蓝色', value: '蓝色' },
+  { label: '黄色', value: '黄色' },
+  { label: '黄绿色', value: '黄绿色' },
+  { label: '白色', value: '白色' },
+  { label: '绿色', value: '绿色' },
+]
+
+const restaurants = ref([])
+const querySearch = (queryString, cb) => {
+  const results = queryString ? restaurants.value.filter(createFilter(queryString)) : restaurants.value
+  // call callback function to return suggestions
+  cb(results)
+}
+const createFilter = queryString => {
+  return restaurant => {
+    return restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0
+  }
+}
+const loadAll = () => {
+  return [{ value: '蒙L22887' }, { value: '蒙L83719' }]
+}
+
+const initMap = () => {
+  AMapLoader.load({
+    key: '81a1282308f1aae58082425a1ebb91b0',
+    version: '2.0',
+    plugins: ['AMap.MoveAnimation'],
+  })
+    .then(AMap => {
+      AMap.plugin('AMap.MoveAnimation', () => {
+        map.value = new AMap.Map('container3', {
+          center: [116.397428, 39.90923],
+        })
+      })
+    })
+    .catch(e => {
+      console.error(e)
+    })
+}
+const data = ref(null)
+const parkArray = ref([])
+const totalMin = ref(0)
+const showTable = ref(false)
+const queryWaybill = async () => {
+  if (!form.value.licensePlateNo) {
+    return Message.error('请输入车牌号')
+  }
+  if (!form.value.startTime || !form.value.endTime) {
+    return Message.error('请选择时间范围')
+  }
+  if (!form.value.licensePlateColor) {
+    return Message.error('请选择车牌颜色')
+  }
+  console.log(form.value, '查询参数')
+  const params = {
+    licensePlateNo: form.value.licensePlateNo,
+    licensePlateColor: form.value.licensePlateColor,
+    startTime: form.value.startTime,
+    endTime: form.value.endTime,
+  }
+  const res = await tms.truckTrackQuery(params)
+
+  if (res.code == 101) {
+    if (res.data.status !== 1001) {
+      Message.error(res.data.result)
+      return
+    }
+
+    data.value = res.data
+    if (data.value.result && data.value.result.trackArray) {
+      parkArray.value = data.value.result.parkArray
+      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(transformFromWGSToGCJArr(Number(item.lon) / 600000, Number(item.lat) / 600000))
+        }
+      })
+    }
+    // 清除之前的markers
+    map.value.clearMap()
+    var polyline = new AMap.Polyline({
+      map: map.value,
+      path: trajectory.value,
+      showDir: true,
+      strokeColor: '#28F', //线颜色
+      strokeWeight: 6, //线宽
+    })
+    map.value.setFitView()
+  }
+}
+
+// 添加marker
+const addMarker = data => {
+  data.forEach(item => {
+    const marker = new AMap.Marker({
+      position: item,
+      icon: require('@/assets/images/dian.png'), // 自定义图标
+      offset: new AMap.Pixel(-13, -26),
+    })
+    marker.setMap(map.value)
+    map.value.setFitView()
+  })
+}
+
+// 清除markers
+const clearMarkers = () => {
+  map.value.clearMap()
+}
+
+onMounted(async () => {
+  restaurants.value = loadAll()
+  await initMap()
+})
+</script>
+
+<style lang="scss" scoped>
+.mapMark {
+  position: relative;
+  // padding: 20px;
+  #container3 {
+    width: 100%;
+    height: 78vh;
+  }
+  .btnBox {
+    width: 100%;
+    position: absolute;
+    top: 10px;
+    left: 20px;
+    z-index: 100;
+    // width: 200px;
+    border-radius: 5px;
+  }
+}
+</style>
+<style lang="scss">
+.amap-icon {
+  width: 40px !important;
+  height: 40px !important;
+}
+.amap-icon img {
+  width: 40px !important;
+  height: 40px !important;
+}
+.abnormal {
+  text-align: right;
+  position: absolute;
+  width: 50%;
+  top: 45px;
+  right: 15px;
+  padding: 5px;
+  z-index: 10;
+  &-title {
+    padding: 5px;
+    background: #fff;
+  }
+}
+</style>