FenXiNspBigScreen/src/components/zhnjCov.vue

564 lines
14 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="yqgkcCon nynj">
<!-- 轨迹地图弹窗 -->
<el-dialog
custom-class="table_dialog"
top="85px"
:show-close="false"
width="100%"
destroy-on-close
append-to-body
:visible.sync="mapDialogVisible"
v-if="mapDialogVisible"
>
<div class="inner_width" style="background: #0B2536;height:106%;">
<img class="inner-img-w" src="@/assets/image/big_background.png" alt="">
<div class="content-box" style="padding: 0;">
<div class="mapparent" id="trajectory"></div>
<div class="topdetail">
<div class="map_detail_tit">
轨迹详情
<div style="height: 40px;float:right;cursor: pointer;" @click.stop="closeMapDialog">
<div class="banrutimg">
<span>关闭</span>
</div>
</div>
</div>
<div class="map-ul">
<div class="map-li">车辆:{{trajectoryVehicleName || '--'}}</div>
<div class="map-li">车牌:{{trajectoryPlate || '--'}}</div>
<div class="map-li">司机:{{formatName(trajectoryDriver)}}</div>
<div class="map-li">GPS设备{{trajectoryGpsId || '--'}}</div>
<div class="map-li">轨迹点数:{{trajectoryPoints.length || 0}}</div>
<div class="map-li"></div>
<div class="map-li"></div>
<div class="map-li"></div>
</div>
</div>
</div>
<div class="bottom-box">
<div class="play" @click="jog">
<img style="width: 24px;height: 24px;margin-bottom:3px" src="@/assets/image/reduce.png" alt="">
<div>减速</div>
</div>
<div class="play" v-if="playsttus == 0 || playsttus == 2" @click="silderInput">
<img src="@/assets/image/play.png" alt="">
<div>播放</div>
</div>
<div class="play" v-if="playsttus == 1" @click="pauseAnimation">
<img style="width: 24px;height: 24px;margin-bottom:3px" src="@/assets/image/puse.png" alt="">
<div>暂停</div>
</div>
<div class="play" @click="fastforward">
<img style="width: 24px;height: 24px;margin-bottom:3px" src="@/assets/image/add.png" alt="">
<div>加速</div>
</div>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
import { gpsRecordPage } from '@/api';
export default {
name: "zhnjCov",
props: {
// 从父组件接收车辆数据(点击地图标记时传入)
vehicleData: {
type: Object,
default: null
},
// 控制弹窗显示
visible: {
type: Boolean,
default: false
}
},
watch: {
vehicleData: {
handler(newVal) {
if (newVal && newVal.gpsId) {
// 接收到车辆数据,打开轨迹弹窗
this.openTrajectoryDialog(newVal);
}
},
deep: true,
immediate: true
},
visible: {
handler(newVal) {
if (!newVal) {
this.mapDialogVisible = false;
this.clearMap();
}
},
immediate: true
}
},
data() {
return {
mapDialogVisible: false,
// 轨迹相关
trajectoryPoints: [],
trajectoryVehicleName: '',
trajectoryPlate: '',
trajectoryDriver: '',
trajectoryGpsId: '',
allTrajectoryData: [],
// 地图相关
myMap: null,
polyline: null,
passedPolyline: null,
marker: null,
playsttus: 0,
valueTime: ''
};
},
methods: {
// 打开轨迹弹窗
openTrajectoryDialog(vehicleInfo) {
if (!vehicleInfo.gpsId) {
this.$message.warning('该车辆没有GPS设备ID');
return;
}
this.trajectoryVehicleName = vehicleInfo.veNotes || vehicleInfo.vehicleName || '车辆';
this.trajectoryPlate = vehicleInfo.vePlate || vehicleInfo.plateNumber || '--';
this.trajectoryDriver = vehicleInfo.veDriver || vehicleInfo.driverName || '--';
this.trajectoryGpsId = vehicleInfo.gpsId;
// 打开轨迹弹窗
this.mapDialogVisible = true;
// 获取轨迹数据
this.fetchAllTrajectoryData();
},
// 关闭轨迹弹窗
closeMapDialog() {
this.mapDialogVisible = false;
this.clearMap();
this.$emit('close');
},
// 清除地图
clearMap() {
if (this.marker) {
try {
this.marker.stopMove();
} catch(e) {}
this.marker = null;
}
if (this.polyline) {
this.polyline = null;
}
if (this.passedPolyline) {
this.passedPolyline = null;
}
if (this.myMap) {
try {
this.myMap.destroy();
} catch(e) {}
this.myMap = null;
}
this.playsttus = 0;
},
// 获取全部轨迹数据(不分页)
fetchAllTrajectoryData() {
const params = {
pageNo: 1,
pageSize: 1000,
gpsId: this.trajectoryGpsId
};
this.$message({
message: '正在加载轨迹数据...',
type: 'info',
duration: 1500
});
gpsRecordPage(params).then(res => {
if (res.success && res.result) {
const records = res.result.records || [];
this.allTrajectoryData = records;
// 提取经纬度点
this.trajectoryPoints = records
.filter(item => item.jingdu && item.weidu)
.map(item => [parseFloat(item.jingdu), parseFloat(item.weidu)]);
console.log('轨迹点数量:', this.trajectoryPoints.length);
if (this.trajectoryPoints.length > 0) {
this.$nextTick(() => {
this.initTrajectoryMap();
});
} else {
this.$message.warning('该车辆暂无轨迹数据');
}
} else {
this.$message.error('获取轨迹数据失败');
}
}).catch(err => {
console.error('获取轨迹数据失败:', err);
this.$message.error('获取轨迹数据失败');
});
},
// 初始化轨迹地图
initTrajectoryMap() {
if (this.trajectoryPoints.length === 0) return;
this.clearMap();
const mapContainer = document.getElementById('trajectory');
if (!mapContainer) {
console.error('地图容器不存在');
return;
}
// 初始化地图
this.myMap = new AMap.Map('trajectory', {
resizeEnable: true,
viewMode: '3D',
zoomEnable: true,
dragEnable: true,
doubleClickZoom: true,
zoom: 15,
center: this.trajectoryPoints[0]
});
// 添加地图图层
let googleLayer = new AMap.TileLayer({
tileSize: 256,
errorUrl: '',
getTileUrl: function (x, y, z) {
return 'https://map.snkoudai.com/maps/vt/lyrs=y&hl=zh-CN&gl=cn&scale=1&x=' + x + '&y=' + y + '&z=' + z + '';
},
zIndex: 2,
zooms: [16, 22],
opacity: 1,
});
googleLayer.setMap(this.myMap);
// 绘制轨迹线
this.polyline = new AMap.Polyline({
map: this.myMap,
path: this.trajectoryPoints,
showDir: true,
strokeColor: "#28F",
strokeWeight: 6,
});
this.myMap.add(this.polyline);
// 添加起点标记
this.marker = new AMap.Marker({
map: this.myMap,
position: this.trajectoryPoints[0],
icon: "https://manage.ilhzn.cn/zh-api/sys/common/static/temp/20241228154040_824e4981dff456b1bb8889.png",
offset: new AMap.Pixel(-23, -30)
});
// 已走过的路径
this.passedPolyline = new AMap.Polyline({
strokeColor: "#AF5",
strokeWeight: 6,
});
this.myMap.add(this.passedPolyline);
// 自适应视图
this.myMap.setFitView();
},
// 播放控制
silderInput() {
if (this.trajectoryPoints.length === 0) {
this.$message.warning('暂无轨迹数据');
return;
}
if (this.playsttus === 1) {
this.pauseAnimation();
return;
} else if (this.playsttus === 2) {
this.resumeAnimation();
return;
}
this.playsttus = 1;
const that = this;
AMap.plugin("AMap.MoveAnimation", () => {
that.marker.moveAlong(that.trajectoryPoints, {
duration: 5000,
autoRotation: true,
});
that.marker.on("moving", (e) => {
that.passedPolyline.setPath(e.passedPath);
that.myMap.setCenter(e.target.getPosition(), true);
if (e.passedPath.length === that.trajectoryPoints.length) {
that.playsttus = 0;
}
});
});
},
pauseAnimation() {
if (this.marker) {
this.marker.pauseMove();
this.playsttus = 2;
}
},
resumeAnimation() {
if (this.marker) {
this.marker.resumeMove();
this.playsttus = 1;
}
},
jog() {
this.$message.info('减速');
},
fastforward() {
this.$message.info('加速');
},
formatName(name) {
if (!name) return '--';
if (name.length <= 1) return name + '*';
if (name.length === 2) return name.charAt(0) + '*';
return name.charAt(0) + '*'.repeat(name.length - 1);
}
}
};
</script>
<style scoped lang="less">
:deep.el-pagination.is-background .el-pager li:not(.disabled).active {
background: #409EFF !important;
}
</style>
<style lang="less">
.table_dialog {
width: 100%;
height: calc(100vh - 122px);
margin-bottom: 0;
background: none;
padding: 20px;
box-sizing: border-box;
}
.table_dialog .inner_width {
width: 100%;
height: 100%;
position: relative;
}
.table_dialog .inner_width .inner-img-w {
width: 100%;
height: 100%;
}
.table_dialog .inner_width .content-box {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
padding: 15px 20px;
box-sizing: border-box;
}
.table_dialog .inner_width .bottom-box {
position: absolute;
bottom: 10px;
left: 0;
right: 0;
margin: auto;
background: rgba(0, 0, 0, 0.6);
display: flex;
justify-content: center;
flex-wrap: wrap;
width: 98%;
}
.table_dialog .inner_width .bottom-box .play {
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
padding: 10px 0;
box-sizing: border-box;
cursor: pointer;
}
.table_dialog .inner_width .bottom-box .play img {
width: 28px;
height: 28px;
}
.table_dialog .inner_width .bottom-box .play div {
width: 100%;
font-weight: 400;
font-size: 16px;
color: #FFFFFF;
text-align: center;
}
.table_dialog .inner_width .topdetail {
position: absolute;
top: 10px;
right: 0;
left: 1%;
height: 140px;
background: rgba(0, 0, 0, 0.61);
padding: 14px 30px;
box-sizing: border-box;
width: 98%;
}
.table_dialog .inner_width .topdetail .map_detail_tit {
font-weight: 500;
font-size: 18px;
color: #01fffa;
position: relative;
padding-left: 20px;
box-sizing: border-box;
line-height: 1.5;
}
.table_dialog .inner_width .topdetail .map_detail_tit:before {
content: ' ';
width: 4px;
height: 24px;
background: #01fffa;
position: absolute;
left: 0;
top: 0;
bottom: 0;
margin: auto;
}
.table_dialog .inner_width .topdetail .map-ul {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
margin-top: 10px;
}
.table_dialog .inner_width .topdetail .map-ul .map-li {
width: 25%;
font-weight: 400;
font-size: 14px;
color: #FFFFFF;
line-height: 2.5;
overflow: hidden;
display: block;
}
.table_dialog .el-dialog__header {
padding: 0;
}
.table_dialog .el-dialog__body {
height: 100%;
padding: 0;
}
.table_dialog .el-table tr {
background: none;
}
.table_dialog .el-table td.el-table__cell,
.table_dialog .el-table th.el-table__cell.is-leaf {
border-color: rgba(16, 128, 255, 0.4);
color: #fff;
}
.table_dialog .el-input__inner {
background: none;
border: none;
color: #01fffa;
height: 36px;
line-height: 36px;
}
.table_dialog .el-table th.el-table__cell {
background: none;
}
.table_dialog .el-table--border::after,
.table_dialog .el-table--group::after,
.table_dialog .el-table::before {
background-color: rgba(16, 128, 255, 0.4);
}
.table_dialog .el-table--enable-row-hover .el-table__body tr:hover > td.el-table__cell {
background: #06111B !important;
}
.table_dialog .pagination {
margin-top: 20px;
color: #fff;
text-align: center;
}
.table_dialog .pagination .el-pager li {
background: none;
color: #fff;
}
.table_dialog .pagination .el-pagination .btn-next,
.table_dialog .pagination .el-pagination .btn-prev {
background: none;
color: #fff;
}
.table_dialog .pagination .el-pagination__jump {
color: #fff;
}
.el-select-dropdown,
.el-picker-panel {
background-color: #0b202f;
border-color: rgba(16, 128, 255, 0.4);
}
.el-table td {
padding: 4px 0px;
}
.el-date-table__row .available {
color: #fff;
}
.el-date-picker__header .el-picker-panel__icon-btn {
color: #fff;
}
.el-date-picker__header .el-date-picker__header-label {
color: #fff;
}
.el-select-dropdown__item.hover,
.el-select-dropdown__item:hover {
background-color: #0b202f;
color: #fff;
}
.popper__arrow {
border-color: #0b202f;
}
.el-button--text {
color: #01fffa;
}
.mapparent {
width: 98%;
height: 800px;
margin: 0 auto;
margin-top: 1%;
background: #0a2a3a;
border-radius: 8px;
}
.banrutimg {
width: 88px;
height: 36px;
line-height: 36px;
background: url(@/assets/image/zhnj/backreturn.png) no-repeat;
background-size: 100% 100%;
}
.banrutimg span {
float: right;
color: #fff;
font-size: 16px;
margin-right: 20px;
}
.banrutimg:hover {
width: 88px;
height: 36px;
line-height: 36px;
float: right;
color: #fff;
font-size: 16px;
background: url(@/assets/image/zhnj/backreturnhover.png) no-repeat;
background-size: 100% 100%;
}
</style>