作者 小范

新增GPS定位功能

@@ -4,6 +4,14 @@ import http from "../http"; @@ -4,6 +4,14 @@ import http from "../http";
4 let baseServiceURL = 'wms-server-warehouse' 4 let baseServiceURL = 'wms-server-warehouse'
5 const serviceName = '/cloud-user-center' 5 const serviceName = '/cloud-user-center'
6 6
  7 +//GPS车辆绑定/解绑
  8 +//export const equipmentVehicleBind = params => { return axios.get(`${baseServiceURL}/gps/location/equipmentVehicleBind`, { params: params }); };
  9 +//GPS车辆历史轨迹
  10 +export const gpshistoryTrack = params => { return axios.get(`${baseServiceURL}/gps/location/gpshistoryTrack`, { params: params }); };
  11 +//GPS车辆当前定位
  12 +export const gpslastlocation = params => { return axios.get(`${baseServiceURL}/gps/location/gpslastlocation`, { params: params }); };
  13 +//GPS多车当前定位
  14 +export const gpsqueryMulVel = params => { return axios.get(`${baseServiceURL}/gps/location/gpsqueryMulVel`, { params: params }); };
7 15
8 //车辆定位 16 //车辆定位
9 export const selectVehicle = params => { return axios.get(`${baseServiceURL}/map/location/lastlocation`, { params: params }); }; 17 export const selectVehicle = params => { return axios.get(`${baseServiceURL}/map/location/lastlocation`, { params: params }); };
@@ -187,6 +187,7 @@ import VehicleInfo from "./views/dispatch/VehicleInfo"; @@ -187,6 +187,7 @@ import VehicleInfo from "./views/dispatch/VehicleInfo";
187 import DispatchNode from "./views/dispatch/DispatchNode"; 187 import DispatchNode from "./views/dispatch/DispatchNode";
188 import Dispatch from "./views/dispatch/Dispatch"; 188 import Dispatch from "./views/dispatch/Dispatch";
189 import multiple from "./views/deploy/multiple"; 189 import multiple from "./views/deploy/multiple";
  190 +import satellite from "./views/deploy/satellite";
190 191
191 192
192 193
@@ -574,6 +575,7 @@ let routes = [ @@ -574,6 +575,7 @@ let routes = [
574 {path:'/attendance',component:attendance,name:'出勤历史'}, 575 {path:'/attendance',component:attendance,name:'出勤历史'},
575 {path:'/conveyance',component:conveyance,name:'出勤车辆'}, 576 {path:'/conveyance',component:conveyance,name:'出勤车辆'},
576 {path:'/multiple',component:multiple,name:'多车定位'}, 577 {path:'/multiple',component:multiple,name:'多车定位'},
  578 + {path:'/satellite',component:satellite,name:'GPS多车定位'},
577 {path:'/station',component:station,name:'场站管理'}, 579 {path:'/station',component:station,name:'场站管理'},
578 {path:'/house',component:house,name:'仓库管理'}, 580 {path:'/house',component:house,name:'仓库管理'},
579 {path:'/inventroyrecord',component:inventroyrecord,name:'库存变更记录'}, 581 {path:'/inventroyrecord',component:inventroyrecord,name:'库存变更记录'},
  1 +<template>
  2 + <div id="mapContainer"></div>
  3 +</template>
  4 +
  5 +<script>
  6 + import AMapLoader from '@amap/amap-jsapi-loader';
  7 + import {queryMulVel, gpsqueryMulVel} from '../../api/consigner/vehicle';
  8 +
  9 + export default {
  10 + data() {
  11 + return {
  12 + mapInstance: null,
  13 + markers:[]
  14 + };
  15 + },
  16 + methods: {
  17 + fetchDataAndUpdateMap() {
  18 + // 请求后端数据
  19 + gpsqueryMulVel().then((response) => {
  20 + const res = response.data;
  21 + //const firstVcl = res.data.data.firstVcl; // 获取首个车辆信息
  22 + const others = res.data.data; // 获取其他车辆信息
  23 +
  24 + // 清除之前的标记
  25 + this.markers.forEach(marker => {
  26 + marker.setMap(null);
  27 + });
  28 + this.markers = [];
  29 +
  30 + /*// 添加首个车辆标记
  31 + if (firstVcl && firstVcl.lon && firstVcl.lat) {
  32 + const marker = new AMap.Marker({
  33 + position: [firstVcl.lon / 600000.0, firstVcl.lat / 600000.0],
  34 + map: this.mapInstance,
  35 + title: firstVcl.vno,
  36 + label: {
  37 + content: firstVcl.vno,
  38 + offset: new AMap.Pixel(0, -20) // 偏移量,使标题显示在标记的上方
  39 + }
  40 + });
  41 + this.markers.push(marker);
  42 + }*/
  43 + if (others) {
  44 + others.forEach(vehicle => {
  45 + if (vehicle.lon && vehicle.lat) {
  46 + const marker = new AMap.Marker({
  47 + position: [vehicle.lon, vehicle.lat],
  48 + map: this.mapInstance,
  49 + title: vehicle.vehicle,
  50 + label: {
  51 + content: vehicle.vehicle,
  52 + offset: new AMap.Pixel(0, -20) // 偏移量,使标题显示在标记的上方
  53 + }
  54 + });
  55 + this.markers.push(marker);
  56 + }
  57 + });
  58 + }
  59 + // 自动调整地图视野,确保所有标记都可见
  60 + /*if (this.markers.length > 0) {
  61 + const bounds = new AMap.Bounds();
  62 + this.markers.forEach(marker => {
  63 + bounds.extend(marker.getPosition());
  64 + });
  65 + this.mapInstance.setBounds(bounds);
  66 + }*/
  67 + if(others && others[0].lon && others[0].lat){
  68 + this.mapInstance.setCenter([others[0].lon,others[0].lat])
  69 + }
  70 + }).catch(error => {
  71 + console.error('Failed to fetch data:', error);
  72 + });
  73 + }
  74 + },
  75 + mounted() {
  76 + AMapLoader.load({
  77 + key: 'fdb27c13681d084e85ff8457b5cbe540',
  78 + version: '2.0',
  79 + plugins: [],
  80 + }).then((AMap) => {
  81 + this.mapInstance = new AMap.Map('mapContainer', {
  82 + zoom: 5,
  83 + center: [116.397428, 39.90923], // 默认中心点位置
  84 + //viewMode: '3D', // 使用3D视图
  85 + //showIndoorMap: false,
  86 + //showLabel: false,
  87 + // mapStyle: 'amap://styles/dark',
  88 + //mapStyle: 'amap://styles/fresh',
  89 + });
  90 +
  91 + // 首次加载数据并更新地图
  92 + this.fetchDataAndUpdateMap();
  93 +
  94 + // 启动定时器,每10分钟刷新一次数据并更新地图
  95 + setInterval(() => {
  96 + this.fetchDataAndUpdateMap();
  97 + }, 10 * 60 * 1000);
  98 + }).catch((err) => {
  99 + console.error('Failed to load AMap:', err);
  100 + });
  101 + },
  102 + };
  103 +</script>
  104 +<style>
  105 + #mapContainer {
  106 + width: 100%;
  107 + height: 100vh;
  108 + }
  109 +</style>
@@ -4,7 +4,8 @@ @@ -4,7 +4,8 @@
4 <el-card style="background-color: #F5F7FA"> 4 <el-card style="background-color: #F5F7FA">
5 <el-row> 5 <el-row>
6 <el-form :model="queryInfo" :rules="rules" ref="ruleForm"> 6 <el-form :model="queryInfo" :rules="rules" ref="ruleForm">
7 - <el-col :span="4.5"> 7 + <el-row>
  8 + <el-col :span="7">
8 <el-form-item label="" prop="vclN"> 9 <el-form-item label="" prop="vclN">
9 <el-input v-model="queryInfo.vclN" size="small" style="width: 170px" 10 <el-input v-model="queryInfo.vclN" size="small" style="width: 170px"
10 placeholder="车牌号" clearable required> 11 placeholder="车牌号" clearable required>
@@ -12,11 +13,11 @@ @@ -12,11 +13,11 @@
12 </el-input> 13 </el-input>
13 </el-form-item> 14 </el-form-item>
14 </el-col> 15 </el-col>
15 - <el-col :span="4.5"> 16 + <el-col :span="7">
16 <el-form-item label="" prop="vco"> 17 <el-form-item label="" prop="vco">
17 <div class="my-text-area"> 18 <div class="my-text-area">
18 <div class="el-input-group__prepend prepand">车牌类型</div> 19 <div class="el-input-group__prepend prepand">车牌类型</div>
19 - <el-select v-model="queryInfo.vco" placeholder="车牌类型" style="width: 70px"> 20 + <el-select v-model="queryInfo.vco" placeholder="车牌类型" style="width: 100px">
20 <el-option label="蓝牌" value="1"></el-option> 21 <el-option label="蓝牌" value="1"></el-option>
21 <el-option label="黄牌" value="2"></el-option> 22 <el-option label="黄牌" value="2"></el-option>
22 <el-option label="绿牌" value="3"></el-option> 23 <el-option label="绿牌" value="3"></el-option>
@@ -24,7 +25,20 @@ @@ -24,7 +25,20 @@
24 </div> 25 </div>
25 </el-form-item> 26 </el-form-item>
26 </el-col> 27 </el-col>
27 - <el-col :span="6.5"> 28 + <el-col :span="7">
  29 + <el-form-item label="" prop="satellite">
  30 + <div class="my-text-area">
  31 + <div class="el-input-group__prepend prepand">卫星</div>
  32 + <el-select required v-model="satellite" placeholder="卫星" style="width: 100px">
  33 + <el-option label="北斗" value="1"></el-option>
  34 + <el-option label="GPS" value="2"></el-option>
  35 + </el-select>
  36 + </div>
  37 + </el-form-item>
  38 + </el-col>
  39 + </el-row>
  40 + <el-row>
  41 + <el-col :span="7">
28 <el-form-item label="" prop="qryEtm"> 42 <el-form-item label="" prop="qryEtm">
29 <div class="my-text-area"> 43 <div class="my-text-area">
30 <div class="el-input-group__prepend prepand">开始时间</div> 44 <div class="el-input-group__prepend prepand">开始时间</div>
@@ -41,7 +55,7 @@ @@ -41,7 +55,7 @@
41 </div> 55 </div>
42 </el-form-item> 56 </el-form-item>
43 </el-col> 57 </el-col>
44 - <el-col :span="6.5"> 58 + <el-col :span="7">
45 <el-form-item label="" prop="qryBtm"> 59 <el-form-item label="" prop="qryBtm">
46 <div class="my-text-area"> 60 <div class="my-text-area">
47 <div class="el-input-group__prepend prepand">结束时间</div> 61 <div class="el-input-group__prepend prepand">结束时间</div>
@@ -58,13 +72,14 @@ @@ -58,13 +72,14 @@
58 </div> 72 </div>
59 </el-form-item> 73 </el-form-item>
60 </el-col> 74 </el-col>
61 - </el-form>  
62 <el-col :span="1"> 75 <el-col :span="1">
63 <el-button type="primary" size="mini" @click="getList()"> 76 <el-button type="primary" size="mini" @click="getList()">
64 查询 77 查询
65 </el-button> 78 </el-button>
66 </el-col> 79 </el-col>
67 </el-row> 80 </el-row>
  81 + </el-form>
  82 + </el-row>
68 </el-card> 83 </el-card>
69 </el-row> 84 </el-row>
70 <div id="mapContainer" ref="mapContainer" style="width: 100%; height: 500px;"></div> 85 <div id="mapContainer" ref="mapContainer" style="width: 100%; height: 500px;"></div>
@@ -72,7 +87,7 @@ @@ -72,7 +87,7 @@
72 </template> 87 </template>
73 <script> 88 <script>
74 import AMapLoader from '@amap/amap-jsapi-loader'; 89 import AMapLoader from '@amap/amap-jsapi-loader';
75 - import { historyTrack } from '../../api/consigner/vehicle'; 90 + import { historyTrack,gpshistoryTrack } from '../../api/consigner/vehicle';
76 91
77 92
78 export default { 93 export default {
@@ -87,6 +102,7 @@ @@ -87,6 +102,7 @@
87 //结束时间 102 //结束时间
88 qryBtm: '', 103 qryBtm: '',
89 }, 104 },
  105 + satellite:'1',
90 pickerOptions: { 106 pickerOptions: {
91 shortcuts: [{ 107 shortcuts: [{
92 text: '最近一周', 108 text: '最近一周',
@@ -155,6 +171,7 @@ @@ -155,6 +171,7 @@
155 }, 171 },
156 methods: { 172 methods: {
157 getList() { 173 getList() {
  174 + if(this.satellite=='1'){
158 this.$refs.ruleForm.validate(valid => { 175 this.$refs.ruleForm.validate(valid => {
159 if (!valid) return; 176 if (!valid) return;
160 const _this = this; 177 const _this = this;
@@ -170,6 +187,24 @@ @@ -170,6 +187,24 @@
170 _this.$message.error('获取车辆轨迹失败:' + error.toString()); 187 _this.$message.error('获取车辆轨迹失败:' + error.toString());
171 }); 188 });
172 }) 189 })
  190 + }else{
  191 + this.$refs.ruleForm.validate(valid => {
  192 + if (!valid) return;
  193 + const _this = this;
  194 + gpshistoryTrack(this.queryInfo).then((response) => {
  195 + const res = response.data;
  196 + if (res.code !== '200') {
  197 + return _this.$message.error('获取车辆轨迹失败!');
  198 + }
  199 + // 调用initMap方法,并将轨迹数据传递过去
  200 + _this.initMapGPS(res.data.data);
  201 + _this.$message.success('获取车辆轨迹成功!');
  202 + }).catch(error => {
  203 + _this.$message.error('获取车辆轨迹失败:' + error.toString());
  204 + });
  205 + })
  206 + }
  207 +
173 }, 208 },
174 initMap(trackArray) { 209 initMap(trackArray) {
175 const _this = this; 210 const _this = this;
@@ -201,6 +236,36 @@ @@ -201,6 +236,36 @@
201 console.error('初始化地图失败:', err); 236 console.error('初始化地图失败:', err);
202 }); 237 });
203 }, 238 },
  239 + initMapGPS(DATA) {
  240 + const _this = this;
  241 + AMapLoader.load({
  242 + key: 'fdb27c13681d084e85ff8457b5cbe540',
  243 + version: '2.0',
  244 + plugins: [], // 可以加载地图插件,比如定位、地图工具等
  245 + }).then((AMap) => {
  246 + // 创建地图对象并存储在 _this.mapInstance 中
  247 + _this.map = new AMap.Map('mapContainer', {
  248 + zoom: 10, // 设置地图缩放级别
  249 + center: [116.397428, 39.90923], // 设置地图中心点坐标
  250 + });
  251 + // 将轨迹数据添加到地图上
  252 + //var lineArr = trackArray.map((item) => [item.longitude / 600000.0, item.latitude / 600000.0]);
  253 + this.convertedCoords = this.convertBDToAMapGPS(DATA);
  254 + console.log(this.convertedCoords)
  255 + _this.poly = new AMap.Polyline({
  256 + path: this.convertedCoords, // 设置折线路径
  257 + strokeColor: "#3366ff", // 线颜色
  258 + strokeOpacity: 1, // 线透明度
  259 + strokeWeight: 3, // 线宽
  260 + strokeStyle: "solid", // 线样式
  261 + });
  262 + _this.poly.setMap(_this.map);
  263 + _this.map.setCenter(this.convertedCoords[0])
  264 + //_this.map.setFitView();
  265 + }).catch((err) => {
  266 + console.error('初始化地图失败:', err);
  267 + });
  268 + },
204 convertBDToAMap(bdCoordData) { 269 convertBDToAMap(bdCoordData) {
205 const aMapCoordData = []; 270 const aMapCoordData = [];
206 bdCoordData.forEach(coord => { 271 bdCoordData.forEach(coord => {
@@ -210,7 +275,15 @@ @@ -210,7 +275,15 @@
210 }); 275 });
211 return aMapCoordData; 276 return aMapCoordData;
212 }, 277 },
213 - 278 + convertBDToAMapGPS(bdCoordData) {
  279 + const aMapCoordData = [];
  280 + bdCoordData.forEach(coord => {
  281 + const lon = parseFloat(coord.lon); // 将经度从北斗格式转换为高德地图格式
  282 + const lat = parseFloat(coord.lat); // 将纬度从北斗格式转换为高德地图格式
  283 + aMapCoordData.push([lon, lat]); // 添加到结果数组
  284 + });
  285 + return aMapCoordData;
  286 + },
214 287
215 }, 288 },
216 289
@@ -41,6 +41,17 @@ @@ -41,6 +41,17 @@
41 </div> 41 </div>
42 </el-form-item> 42 </el-form-item>
43 </el-col> 43 </el-col>
  44 + <el-col :span="6">
  45 + <el-form-item label="" prop="satellite">
  46 + <div class="my-text-area">
  47 + <div class="el-input-group__prepend prepand">卫星</div>
  48 + <el-select required v-model="satellite" placeholder="卫星" style="width: 100px">
  49 + <el-option label="北斗" value="1"></el-option>
  50 + <el-option label="GPS" value="2"></el-option>
  51 + </el-select>
  52 + </div>
  53 + </el-form-item>
  54 + </el-col>
44 <el-col :span="2"> 55 <el-col :span="2">
45 <el-button type="primary" icon="el-icon-search" size="mini" @click="getList()"> 56 <el-button type="primary" icon="el-icon-search" size="mini" @click="getList()">
46 查询 57 查询
@@ -74,7 +85,7 @@ @@ -74,7 +85,7 @@
74 </template> 85 </template>
75 <script> 86 <script>
76 import AMapLoader from '@amap/amap-jsapi-loader'; 87 import AMapLoader from '@amap/amap-jsapi-loader';
77 - import {selectVehicle, selectNameList, selectByliscenNo, selectList} from '../../api/consigner/vehicle'; 88 + import {selectVehicle, selectNameList, selectByliscenNo, selectList, gpslastlocation} from '../../api/consigner/vehicle';
78 import {loginedUserInfo} from "../../api/user"; 89 import {loginedUserInfo} from "../../api/user";
79 90
80 export default { 91 export default {
@@ -87,6 +98,7 @@ @@ -87,6 +98,7 @@
87 vno: '', 98 vno: '',
88 vnocolor: '2' 99 vnocolor: '2'
89 }, 100 },
  101 + satellite:'1',
90 vnos:[], 102 vnos:[],
91 loading:false, 103 loading:false,
92 imageUrls: [], // 存储图片地址的数组 104 imageUrls: [], // 存储图片地址的数组
@@ -151,6 +163,7 @@ @@ -151,6 +163,7 @@
151 }); 163 });
152 }, 164 },
153 getList() { 165 getList() {
  166 + if(this.satellite=='1'){
154 this.$refs.ruleForm.validate(valid => { 167 this.$refs.ruleForm.validate(valid => {
155 if (!valid) return; 168 if (!valid) return;
156 const _this = this; 169 const _this = this;
@@ -199,6 +212,53 @@ @@ -199,6 +212,53 @@
199 _this.$message.error('获取车辆位置失败:' + error.toString()); 212 _this.$message.error('获取车辆位置失败:' + error.toString());
200 }); 213 });
201 }) 214 })
  215 + }else{
  216 + this.$refs.ruleForm.validate(valid => {
  217 + if (!valid) return;
  218 + const _this = this;
  219 + gpslastlocation({vno:this.queryInfo.vno}).then((response) => {
  220 + const res = response.data;
  221 + if (res.code !== '200') {
  222 + return _this.$message.error('获取车辆位置失败!');
  223 + }
  224 + if(res.data.data!=='' && res.data.data!=null){
  225 + // 获取车辆位置信息
  226 + const vehicle = res.data.data;
  227 + // 在获取车辆位置成功的部分,创建信息窗口或者自定义标记
  228 + if (vehicle[0].lon && vehicle[0].lat) {
  229 +
  230 + const markerContent = document.createElement('div');
  231 + markerContent.innerHTML = `
  232 + <div class="rounded-corner" STYLE="width: 250px;background-color: rgba(255,255,255,0.7);text-align: left">
  233 + <p>车牌号:${vehicle[0].vehicle}</p >
  234 + <p>速度:${vehicle[0].speed}</p >
  235 + <p>车辆位置:${vehicle[0].placeName}</p >
  236 + </div>
  237 + `;
  238 + // 添加车辆位置标记
  239 + const marker = new AMap.Marker({
  240 + position: [vehicle[0].lon, vehicle[0].lat],
  241 + map: _this.mapInstance,
  242 + content: markerContent
  243 + });
  244 + const defaultMarker = new AMap.Marker({
  245 + position: [vehicle[0].lon, vehicle[0].lat],
  246 + map: _this.mapInstance,
  247 + });
  248 + // 移动地图中心到车辆位置
  249 + _this.mapInstance.setCenter([vehicle[0].lon, vehicle[0].lat]);
  250 + _this.$message.success('获取车辆位置成功!');
  251 + } else {
  252 + _this.$message.warning('车辆位置信息不完整!');
  253 + }
  254 + }else{
  255 + return _this.$message.error('无相关车辆信息返回');
  256 + }
  257 + }).catch(error => {
  258 + _this.$message.error('获取车辆位置失败:' + error.toString());
  259 + });
  260 + })
  261 + }
202 }, 262 },
203 initMap() { 263 initMap() {
204 AMapLoader.load({ 264 AMapLoader.load({