Commit 2dc3308f authored by ninglx's avatar ninglx

首页 超限车辆检测 历史播放

parent 2a75496c
syntax = "proto3"; syntax = "proto3";
package com.wanji.holo.proto; package com.wanji.holo.proto;
option optimize_for = SPEED; option optimize_for = SPEED;
option java_package = "com.wanji.holo.proto"; option java_package = "com.wanji.holo.proto";
option java_multiple_files = true; option java_multiple_files = true;
...@@ -23,7 +21,9 @@ message RealtimeCarInfo { ...@@ -23,7 +21,9 @@ message RealtimeCarInfo {
bool isAggregate = 13; //是否聚合 bool isAggregate = 13; //是否聚合
string aggregatePointNum = 14; //聚合点数量 string aggregatePointNum = 14; //聚合点数量
string dateTime = 15; //车辆时间 string dateTime = 15; //车辆时间
map<string, string> extendAttribute = 17; RoadNet roadNet = 16; //路网数据
map<string, string> extendAttribute = 17; //扩展属性
OverRun overRun = 18;//超限数据
} }
//数据类型对象 //数据类型对象
...@@ -34,20 +34,44 @@ message DataType { ...@@ -34,20 +34,44 @@ message DataType {
double level= 4;//缩放级别 double level= 4;//缩放级别
} }
//数据类型对象
message OverRun {
string overType = 1;//超限类型 1超高 2超宽
string timeStamp = 2;//超限预警时间
double vehicleHeight = 3;//车高
double vehicleWidth= 4;//车宽
}
//数据类型对象
message RoadNet {
string crossId = 1;//路口ID
string rid = 2;//路段ID
string laneId = 3;//车道ID
string segmentId= 4;//渠化段ID
}
//数据类型对象
message DetectorState {
string laneId = 1;//车道ID
int32 state = 2;//状态
}
//轨迹信息 //轨迹信息
message RealtimeCarTrack { message RealtimeCarTrack {
//轨迹 //轨迹
repeated RealtimeCarInfo carInfo = 1; repeated RealtimeCarInfo carInfo = 1;
//数据帧时间 //数据帧时间
string frameTime = 2; string frameTime = 2;
map<string, int32> detectorState = 3; //检测器状态 map<string, int32> detectorState = 3; //检测器状态
} }
//分页信息 //分页信息
message Page { message Page {
int32 pageNum = 1;//页号 int32 pageNum = 1;//页号
int32 pageSize = 2;//每页大小 int32 pageSize = 2;//每页大小
int32 totalPageNum = 3;//总页数 int32 totalPageNum = 3;//总页数
} }
message FrameList { message FrameList {
......
<template> <template>
<div <div class="loopVideo" v-loading="videoLoading" element-loading-text="加载中..."
class="loopVideo" element-loading-spinner="el-icon-loading" element-loading-background="rgba(0, 0, 0, 0.8)">
v-loading="videoLoading" <video :id="`historyVideoComponent${channel}`" style="object-fit: fill;" @canplay="videoCanPlay" :autoplay="autoplay" muted controls loop
element-loading-text="加载中..." class="videoControl" ref="loopVideoPlayer">
v-show="videoUrl"
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.8)"
>
<video
:id="`historyVideoComponent${channel}`"
@canplay="videoCanPlay"
:autoplay="autoplay"
muted
controls
loop
class="videoControl"
ref="loopVideoPlayer"
>
<source :src="videoUrl" type="video/mp4" /> <source :src="videoUrl" type="video/mp4" />
您的浏览器不支持 video 属性。 您的浏览器不支持 video 属性。
</video> </video>
...@@ -65,7 +51,7 @@ export default { ...@@ -65,7 +51,7 @@ export default {
.replaceAll(" ", "_") .replaceAll(" ", "_")
.replaceAll(":", "_"); .replaceAll(":", "_");
}, },
destroy() {}, destroy() { },
async getVideoStreamUrl() { async getVideoStreamUrl() {
if (this.timeModel.startTime && this.timeModel.endTime) { if (this.timeModel.startTime && this.timeModel.endTime) {
try { try {
...@@ -75,11 +61,15 @@ export default { ...@@ -75,11 +61,15 @@ export default {
starttime: this.replaceTimeGap(this.timeModel.startTime), starttime: this.replaceTimeGap(this.timeModel.startTime),
endtime: this.replaceTimeGap(this.timeModel.endTime), endtime: this.replaceTimeGap(this.timeModel.endTime),
}); });
console.log("response", response); console.log("video response", response);
this.videoUrl = response.content; this.videoUrl = response.content;
setTimeout(() => { setTimeout(() => {
this.$refs.loopVideoPlayer.load(); this.$refs.loopVideoPlayer.load();
}, 200); }, 200);
// this.videoUrl = 'video/111.mp4';
// setTimeout(() => {
// this.$refs.loopVideoPlayer.load();
// }, 200);
} catch (error) { } catch (error) {
console.error(`Failed to get video stream url: ${error}`); console.error(`Failed to get video stream url: ${error}`);
} }
...@@ -124,5 +114,4 @@ export default { ...@@ -124,5 +114,4 @@ export default {
// left: 30%; // left: 30%;
// top: -14px; // top: -14px;
// transform: translateX(-50%); // transform: translateX(-50%);
// } // }</style>
</style>
...@@ -18,6 +18,7 @@ export default { ...@@ -18,6 +18,7 @@ export default {
}, },
carTypeGlbMap:{ carTypeGlbMap:{
1:'0', 1:'0',
2:'170',
9:'0', 9:'0',
13:'0', 13:'0',
15:'0', 15:'0',
......
...@@ -31,11 +31,11 @@ export function initWs(data) { ...@@ -31,11 +31,11 @@ export function initWs(data) {
// 接收消息 // 接收消息
currentSocket.onmessage = (res) => { currentSocket.onmessage = (res) => {
// protobuf 解压数据 // protobuf 解压数据
if (data.name === "callCar") { if (data.name.includes("callCar")) {
let reader = new FileReader(); let reader = new FileReader();
reader.onload = (e) => { reader.onload = (e) => {
let buf = new Uint8Array(e.target.result); let data1 = new Uint8Array(e.target.result);
let responseCarTrack = ResponseCarTrack.decode(buf); let responseCarTrack = ResponseCarTrack.decode(data1);
data.callback(responseCarTrack.carInfo); data.callback(responseCarTrack.carInfo);
}; };
reader.readAsArrayBuffer(res.data); reader.readAsArrayBuffer(res.data);
......
...@@ -20,7 +20,7 @@ import 'element-ui/lib/theme-chalk/index.css'; ...@@ -20,7 +20,7 @@ import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI, { Vue.use(ElementUI, {
size: 'small', size: 'small',
}) })
window.wsHost = (process.env.NODE_ENV==='development'?'10.102.1.181:9000':location.host) window.wsHost = (process.env.NODE_ENV==='development'?'10.102.1.182:9000':location.host)
// 暂时挂载到window 以支持项目之前的ELEMENT.Message写法 // 暂时挂载到window 以支持项目之前的ELEMENT.Message写法
window.ELEMENT = ElementUI window.ELEMENT = ElementUI
// 事件总线 // 事件总线
......
...@@ -30,27 +30,30 @@ export default { ...@@ -30,27 +30,30 @@ export default {
}); });
}, },
mxRefreshLightWs() { mxRefreshLightWs() {
let targetPoint = turf.point([window.map.getCenter().lng, window.map.getCenter().lat]); if (this.shouldShowLight) {
// 取最近点的crossId 判断哪个路口离当前视野中心点最近 请求对应的灯态websocket let targetPoint = turf.point([window.map.getCenter().lng, window.map.getCenter().lat]);
let nearest = turf.nearestPoint(targetPoint, this.crossGeo); // 取最近点的crossId 判断哪个路口离当前视野中心点最近 请求对应的灯态websocket
let nearestCrossId = nearest.properties.id; let nearest = turf.nearestPoint(targetPoint, this.crossGeo);
// 如果求得最近路口不是上次的最近路口,则关闭上个ws,请求最新路口ws let nearestCrossId = nearest.properties.id;
if (nearestCrossId !== this.currentNearestCrossId) { // 如果求得最近路口不是上次的最近路口,则关闭上个ws,请求最新路口ws
this.currentNearestCrossId = nearestCrossId; if (nearestCrossId !== this.currentNearestCrossId) {
this.closeWs("callLight").then(() => { this.currentNearestCrossId = nearestCrossId;
let socket = initWs({ this.closeWs("callLight").then(() => {
// url: `${ws_config.CROSS_CONTROL}${nearestCrossId},holo-web`, let socket = initWs({
url: `ws://${window.wsHost}/utc/signalStatus/${nearestCrossId},holo-web`, // url: `${ws_config.CROSS_CONTROL}${nearestCrossId},holo-web`,
callback: this.callLight, url: `ws://${window.wsHost}/utc/signalStatus/${nearestCrossId},holo-web`,
name: "callLight", callback: this.callLight,
name: "callLight",
});
socket.ws.onopen = () => {
if (socket.ws.readyState === 1) {
this.sockets.push(socket);
}
};
}); });
socket.ws.onopen = () => { }
if (socket.ws.readyState === 1) {
this.sockets.push(socket);
}
};
});
} }
}, },
// 处理灯态 // 处理灯态
callLight(msg) { callLight(msg) {
......
...@@ -174,11 +174,13 @@ export default { ...@@ -174,11 +174,13 @@ export default {
radarTimers.push(timer); radarTimers.push(timer);
}, },
loadUpdateRadars() { loadUpdateRadars() {
if (!this.radarShow) { if (this.shouldShowRadar) {
this.radarShow = true; if (!this.radarShow) {
this.loadRadars(); this.radarShow = true;
} else { this.loadRadars();
this.updateRadars() } else {
this.updateRadars()
}
} }
}, },
updateRadars() { updateRadars() {
......
...@@ -112,7 +112,7 @@ ...@@ -112,7 +112,7 @@
</template> </template>
<script> <script>
import { download, getBlob } from "../../../utils/request"; import { getBlob } from "../../../utils/request";
// import fetch from "@/utils/fetch"; // import fetch from "@/utils/fetch";
import { getReports, getReportsByPage } from "../../../dao/analysis"; import { getReports, getReportsByPage } from "../../../dao/analysis";
import JSZip from "jszip"; import JSZip from "jszip";
...@@ -292,7 +292,7 @@ export default { ...@@ -292,7 +292,7 @@ export default {
link.href = window.URL.createObjectURL(blob); link.href = window.URL.createObjectURL(blob);
link.download = report.name; link.download = report.name;
link.click(); link.click();
download(url, {}, report.name); // download(url, {}, report.name);
}, },
screenReports() { screenReports() {
let filter = this.reportSearchValue; let filter = this.reportSearchValue;
......
...@@ -107,7 +107,8 @@ ...@@ -107,7 +107,8 @@
<div class="traffics"> <div class="traffics">
<vue-seamless-scroll ref='22' class="warningMsg" :data="overData" :class-option="optionSetting1" <vue-seamless-scroll ref='22' class="warningMsg" :data="overData" :class-option="optionSetting1"
v-show="overData.length"> v-show="overData.length">
<li v-for="(item, index) of overData" class="overItem" :key="index"> <li @click="playOverHistoryTrace(item)" v-for="(item, index) of overData" class="overItem"
:key="index">
<div class='topLicense'> <span>预警时间:</span>{{ item.timeStamp }}</div> <div class='topLicense'> <span>预警时间:</span>{{ item.timeStamp }}</div>
<div class='detailMsg'> <div class='detailMsg'>
<div><span>车牌:</span>{{ item.plateNo }}</div> <div><span>车牌:</span>{{ item.plateNo }}</div>
...@@ -157,7 +158,7 @@ export default { ...@@ -157,7 +158,7 @@ export default {
dict, dict,
activeName: '11', activeName: '11',
overData: [ overData: [
// { "plateNo": "京A895413", "inDirName": "东向西", "type": "201", "timeStamp": "2024-08-27 15:39:18" }, { "plateNo": "京A895413", "inDirName": "东向西", "type": "201", "timeStamp": "2024-08-27 15:39:18" },
// { "plateNo": "京A895413", "inDirName": "东向西", "type": "504", "timeStamp": "2024-08-27 15:39:18" }, // { "plateNo": "京A895413", "inDirName": "东向西", "type": "504", "timeStamp": "2024-08-27 15:39:18" },
// { "plateNo": "京A895413", "inDirName": "东向西", "type": "504", "timeStamp": "2024-08-27 15:39:18" }, // { "plateNo": "京A895413", "inDirName": "东向西", "type": "504", "timeStamp": "2024-08-27 15:39:18" },
// { "plateNo": "京A895413", "inDirName": "东向西", "type": "504", "timeStamp": "2024-08-27 15:39:18" }, // { "plateNo": "京A895413", "inDirName": "东向西", "type": "504", "timeStamp": "2024-08-27 15:39:18" },
...@@ -229,13 +230,46 @@ export default { ...@@ -229,13 +230,46 @@ export default {
this.timers.push(timer4); this.timers.push(timer4);
}, },
methods: { methods: {
timeFormat(date) {
let time = new Date(date);
let year, month, day, hour, min, sec;
year = time.getFullYear();
month =
time.getMonth() + 1 < 10
? "0" + (time.getMonth() + 1)
: time.getMonth() + 1;
day = time.getDate() < 10 ? "0" + time.getDate() : time.getDate();
hour = time.getHours() < 10 ? "0" + time.getHours() : time.getHours();
min =
time.getMinutes() < 10 ? "0" + time.getMinutes() : time.getMinutes();
sec =
time.getSeconds() < 10 ? "0" + time.getSeconds() : time.getSeconds();
let dateTime = `${year}-${month}-${day} ${hour}:${min}:${sec}`; //+year + month + day + hour + min + sec;
return dateTime;
},
playOverHistoryTrace(row) {
let wsSend = {
"dataType": "OVER_RUN", //数据类型【固定值】
"timeStamp": row.timeStamp, //时间
'endTime': this.timeFormat(new Date(new Date(row.timeStamp).getTime() + 1000 * 10)),
"globalId": row.globalId, //车辆ID
"overType": row.type //超限类型
}
console.log('close real time', row, wsSend);
this.$emit("playOverHistoryTrace", wsSend)
},
// 获取超限列表 // 获取超限列表
getOverData() { getOverData() {
getAlarmOverDatas().then(res => { getAlarmOverDatas().then(res => {
this.overLoading = false this.overLoading = false
console.log("超限列表", res.content); console.log("超限列表", res.content);
// todo // todo
this.overData = res.content; if (res.content) {
this.overData = res.content.map(item => {
item.timeStamp = item.timeStamp.replace('T', ' ')
return item
}) || [];
}
}) })
}, },
tabClick(e) { tabClick(e) {
...@@ -642,15 +676,18 @@ export default { ...@@ -642,15 +676,18 @@ export default {
text-overflow: ellipsis; text-overflow: ellipsis;
margin-right: 5px; margin-right: 5px;
} }
div:nth-child(1) { div:nth-child(1) {
width: 25%; width: 25%;
} }
div:nth-child(2) { div:nth-child(2) {
width: calc(50% - 10px); width: calc(50% - 10px);
} }
div:nth-child(3) { div:nth-child(3) {
width: 25%; width: 25%;
margin-right:0 margin-right: 0
} }
} }
} }
......
...@@ -6,7 +6,8 @@ ...@@ -6,7 +6,8 @@
<situation-time v-show="currentCheck === 'first' && timeState" class="situationTime" :time="situationTimeVal" /> <situation-time v-show="currentCheck === 'first' && timeState" class="situationTime" :time="situationTimeVal" />
<wMap :mapId="'situation-map'" ref="wMap" /> <wMap :mapId="'situation-map'" ref="wMap" />
<!--左右图表组件--> <!--左右图表组件-->
<message-boxes @delWarningPopup="delWarningPopup" @addWarningPopup="addWarningPopup" :show="boxesShow" /> <message-boxes @playOverHistoryTrace="playOverHistoryTrace" @delWarningPopup="delWarningPopup"
@addWarningPopup="addWarningPopup" :show="boxesShow" />
<!--图层切换按钮--> <!--图层切换按钮-->
<layers-switch ref="switch" :show="boxesShow" @changeCheck="changeCheck" @visibleChange="visibleChange" <layers-switch ref="switch" :show="boxesShow" @changeCheck="changeCheck" @visibleChange="visibleChange"
:class="boxesShow ? 'generalSwitch' : 'rightSwitch'" /> :class="boxesShow ? 'generalSwitch' : 'rightSwitch'" />
...@@ -20,6 +21,8 @@ ...@@ -20,6 +21,8 @@
<traffic-events-tend @updateHeatMap="refreshEventLayer" v-if="currentCheck === 'third'" /> <traffic-events-tend @updateHeatMap="refreshEventLayer" v-if="currentCheck === 'third'" />
<!--设备图例控制--> <!--设备图例控制-->
<equipment-switch @equipmentChange="equipmentChange" v-if="currentCheck === 'fourth'" /> <equipment-switch @equipmentChange="equipmentChange" v-if="currentCheck === 'fourth'" />
<!--单车超限历史轨迹视频-->
<sigalTraceVideos :key="sigalKey" v-if="showHisVid" :timeDuration="timeDuration"></sigalTraceVideos>
</div> </div>
</template> </template>
...@@ -46,6 +49,7 @@ import draw from "./mixins/draw"; ...@@ -46,6 +49,7 @@ import draw from "./mixins/draw";
import mixinLightModel from "./mixins/light3d"; import mixinLightModel from "./mixins/light3d";
import lightMixin from "../../mixins/lightMixin"; import lightMixin from "../../mixins/lightMixin";
import radarMixin from "../../mixins/radarMixin"; import radarMixin from "../../mixins/radarMixin";
import sigalTraceVideos from './sigalTraceVideos/index.vue'
import detetorMixin from "../../mixins/detetorMixin"; import detetorMixin from "../../mixins/detetorMixin";
import { import {
eventInfo, eventInfo,
...@@ -123,7 +127,7 @@ export default { ...@@ -123,7 +127,7 @@ export default {
mixinLightModel, mixinLightModel,
lightMixin, // 实时灯态mixin lightMixin, // 实时灯态mixin
radarMixin, // 雷达模型状态mixin radarMixin, // 雷达模型状态mixin
detetorMixin // 实时检测器mixin detetorMixin, // 实时检测器mixin
], ],
components: { components: {
TrackSwitcher, TrackSwitcher,
...@@ -135,10 +139,25 @@ export default { ...@@ -135,10 +139,25 @@ export default {
VideoList, VideoList,
TrafficEventsTend, TrafficEventsTend,
EquipmentSwitch, EquipmentSwitch,
sigalTraceVideos
}, },
props: {}, props: {},
computed: {
shouldShowRadar() {
return this.currentCheck === 'first' && !this.showHisVid
},
shouldShowLight() {
return this.currentCheck === 'first' && !this.showHisVid
}
},
data() { data() {
return { return {
sigalKey: '',
showHisVid: false,
timeDuration: {
startTime: "",
endTime: "",
},
// Mixin 公用数据 // Mixin 公用数据
crossGeo: null, //所有路口lnglat geojson集合 crossGeo: null, //所有路口lnglat geojson集合
sockets: [], sockets: [],
...@@ -179,7 +198,6 @@ export default { ...@@ -179,7 +198,6 @@ export default {
third: ["eventHeat", "eventPoint"], third: ["eventHeat", "eventPoint"],
fourth: ["weather", "camera", "radar", "signal", "milli"], fourth: ["weather", "camera", "radar", "signal", "milli"],
}, },
layerShowRenders: true,
rulerStatus: false, rulerStatus: false,
selectVehicleTrackData: null, selectVehicleTrackData: null,
highLightCarTracks: {}, // 储存弹窗车辆轨迹数据 highLightCarTracks: {}, // 储存弹窗车辆轨迹数据
...@@ -187,6 +205,7 @@ export default { ...@@ -187,6 +205,7 @@ export default {
cBearing: "", cBearing: "",
cLocation: "", cLocation: "",
overCarsPoints: {}, // 储存超限车辆动态经纬度 overCarsPoints: {}, // 储存超限车辆动态经纬度
backToRealTimer: null, // 存储回到实时车流倒计时器
}; };
}, },
watch: { watch: {
...@@ -306,6 +325,62 @@ export default { ...@@ -306,6 +325,62 @@ export default {
this.lastLocation = []; this.lastLocation = [];
}); });
}, },
playOverHistoryTrace(sendMsg) {
if (this.backToRealTimer) {
clearTimeout(this.backToRealTimer)
this.backToRealTimer = null
}
Promise.all([this.closeWs('callCar'), this.closeWs('callCar1')]).then(() => {
console.log('closed all...');
this.removeAllRadars()
this.radarShow = false
this.clearTrackTimer();
window.tb?.clear(null, true);
window.tb?.update();
this.lastLocation = [];
this.timeDuration = {
startTime: sendMsg.timeStamp,
endTime: sendMsg.endTime,
};
this.$nextTick(() => {
// 播放单车历史ws
let socket = initWs({
name: "callCar1",
url: `ws://${window.wsHost}/holows/subscribe`,
callback: this.callCar,
});
socket.ws.onopen = () => {
if (this.backToRealTimer) {
clearTimeout(this.backToRealTimer)
this.backToRealTimer = null
}
this.backToRealTimer = setTimeout(() => {
this.closeWs('callCar1').then(() => {
this.openRealTime()
this.showHisVid = false
})
this.backToRealTimer = null
}, 1000 * 10)
if (socket.ws.readyState === 1) {
this.sockets.push(socket);
this.showHisVid = true
this.sigalKey = sendMsg.globalId
// socket.ws.send('{ dataType: "1"}');
// socket.ws.send('{"dataType":"OVER_RUN","timeStamp":"2024-09-06 15:01:17.000","endTime":"2024-09-06 15:01:27.000","globalId":"10547041","vehicleHeight":6,"vehicleWidth":2.55,"overType":1}')
socket.ws.send(JSON.stringify(sendMsg));
}
};
// socket.ws.onclose = () => {
// // this.closeRealTime()
// if(this.showHisVid){
// this.showHisVid = false
// this.openRealTime()
// }
// };
})
})
},
openRealTime() { openRealTime() {
this.registerListener(); this.registerListener();
this.switchfirst(); this.switchfirst();
...@@ -587,7 +662,7 @@ export default { ...@@ -587,7 +662,7 @@ export default {
if (this.currentCheck === "first") { if (this.currentCheck === "first") {
if (map.getZoom() > 18) { if (map.getZoom() > 18) {
this.mxRefreshLightWs(); this.mxRefreshLightWs();
this.showCameras = []; // this.showCameras = [];
} }
} }
}, },
...@@ -633,7 +708,6 @@ export default { ...@@ -633,7 +708,6 @@ export default {
} }
} }
}, 100); }, 100);
this.layerShowRenders = true;
let arr = this.$store.state.dicts.CrossInfo.map(item => { let arr = this.$store.state.dicts.CrossInfo.map(item => {
[item.longitude, item.latitude] = item.location.split(",") [item.longitude, item.latitude] = item.location.split(",")
return item return item
...@@ -891,6 +965,8 @@ export default { ...@@ -891,6 +965,8 @@ export default {
}, },
// 车辆详情弹窗内容 // 车辆详情弹窗内容
addCheckDetail(data) { addCheckDetail(data) {
console.log('添加弹窗...');
if (vehiclePopups[`popup${data.id}`]) { if (vehiclePopups[`popup${data.id}`]) {
if (popupVises[`popup${data.id}`]) { if (popupVises[`popup${data.id}`]) {
vehiclePopups[`popup${data.id}`].setLngLat([ vehiclePopups[`popup${data.id}`].setLngLat([
...@@ -927,7 +1003,7 @@ export default { ...@@ -927,7 +1003,7 @@ export default {
vehiclePopups[`popup${data.id}`] = null; vehiclePopups[`popup${data.id}`] = null;
delete vehiclePopups[`popup${data.id}`]; delete vehiclePopups[`popup${data.id}`];
delete this.highLightCarTracks[data.id] delete this.highLightCarTracks[data.id]
delete delete this.overCarsPoints[data.id] delete this.overCarsPoints[data.id]
popupVises[`popup${data.id}`] = false; popupVises[`popup${data.id}`] = false;
}); });
popupVises[`popup${data.id}`] = true; popupVises[`popup${data.id}`] = true;
...@@ -959,176 +1035,182 @@ export default { ...@@ -959,176 +1035,182 @@ export default {
} }
licenseLabel = {}; licenseLabel = {};
} }
if (this.layerShowRenders) { // 筛选可见区域
// 筛选可见区域 for (let i = 0; i < msg.length; i++) {
for (let i = 0; i < msg.length; i++) { // 缺失车牌号字段和非机动车类型 把车牌号字段置空
// 缺失车牌号字段和非机动车类型 把车牌号字段置空 if (!msg[i].picLicense || dict.noVehicleTypes.includes(msg[i].originalType)) {
if (!msg[i].picLicense || dict.noVehicleTypes.includes(msg[i].originalType)) { msg[i].picLicense = "";
msg[i].picLicense = ""; }
} // if (msg[i].id.toString().includes('120') && new Date().getMinutes() % 2 === 0) {
// if (msg[i].id.toString().includes('120327')) { // msg[i].overRun = {
// msg[i].overType = '201,202' // overType: '1,2',
// msg[i].timeStamp = '2021' // }
// } // }
let pt = turf.point([msg[i].longitude, msg[i].latitude]); let pt = turf.point([msg[i].longitude, msg[i].latitude]);
let poly = turf.polygon(this.bounds); let poly = turf.polygon(this.bounds);
if (!turf.booleanPointInPolygon(pt, poly)) { if (!turf.booleanPointInPolygon(pt, poly)) {
msg.splice(i, 1); msg.splice(i, 1);
i = i - 1; i = i - 1;
}
}
if (msg.length > 0) {
// console.log("车辆总数", msg.length);
// 第一帧 || 时间戳不相同 => 放行
if (msg.length === 1) {
console.log('msg', msg);
}
// if (this.lastLocation.length === 0) {
this.situationTimeVal = msg[0].dateTime;
// zoom 大于 18 : 移除圆点和图片图层
if (zoom >= 18) {
this.removeLayers("vehiclePic,vehicle");
}
// zoom 小于 18:隐藏 three场景 ;大于17且小于18的部分使用图片图层 其余部分使用圆点
if (zoom < 18) {
this.hideTb();
if (zoom > 17) {
this.removeLayers("vehicle");
mapTools.addOrUpdateVehiclePic(map, msg);
map.on("click", "vehiclePic", this.vehiclePicClick);
} else {
this.clearLicense();
this.removeLayers(
"lightLayer,lightLayerText,vehicleSelectWave,vehiclePic,waitingLayer"
);
mapTools.addOrUpdateVehicle(map, msg);
map.on("click", "vehicle", this.vehicleCircleClick);
} }
} }
if (msg.length > 0) { let allData = this.diff(this.lastLocation, msg);
// console.log("车辆总数", msg.length); for (let item of allData) {
// 第一帧 || 时间戳不相同 => 放行 // 如果选中车辆存在 则弹窗更新 否则删除弹窗
if ( if (this.selectVehicles[item.id]) {
this.lastLocation.length === 0 || if (["add", "com"].includes(item.dill)) {
this.lastLocation[0].dateTime !== msg[0].dateTime if (popupVises[`popup${item.id}`]) {
) { this.addCheckDetail(item);
this.situationTimeVal = msg[0].dateTime;
// zoom 大于 18 : 移除圆点和图片图层
if (zoom >= 18) {
this.removeLayers("vehiclePic,vehicle");
}
// zoom 小于 18:隐藏 three场景 ;大于17且小于18的部分使用图片图层 其余部分使用圆点
if (zoom < 18) {
this.hideTb();
if (zoom > 17) {
this.removeLayers("vehicle");
mapTools.addOrUpdateVehiclePic(map, msg);
map.on("click", "vehiclePic", this.vehiclePicClick);
} else {
this.clearLicense();
this.removeLayers(
"lightLayer,lightLayerText,vehicleSelectWave,vehiclePic,waitingLayer"
);
mapTools.addOrUpdateVehicle(map, msg);
map.on("click", "vehicle", this.vehicleCircleClick);
} }
} else {
vehiclePopups[`popup${item.id}`]?.remove();
delete this.selectVehicles[item.id]
} }
let allData = this.diff(this.lastLocation, msg); }
for (let item of allData) { // 超限车辆弹窗判断 todo
// 如果选中车辆存在 则弹窗更新 否则删除弹窗 if (item.overRun?.overType) {
if (this.selectVehicles[item.id]) { console.log('检测到超限...', item.overRun)
if (["add", "com"].includes(item.dill)) { // 如果超限车辆第一次添加 则设置 popupVises[`popup${item.id}`] 为 true
if (popupVises[`popup${item.id}`]) { if (!this.overCarsPoints[item.id]) {
this.addCheckDetail(item); popupVises[`popup${item.id}`] = true
} // 右下角弹出超限警告
} else { let overArr = item.overRun.overType.split(',')
vehiclePopups[`popup${item.id}`]?.remove(); let overStr = ''
delete this.selectVehicles[item.id] for (let t of overArr) {
} overStr += dict.overCarType[t]
} }
// 超限车辆弹窗判断 todo this.$notify({
if (item.overType) { title: '超限车辆',
// 如果超限车辆第一次添加 则设置 popupVises[`popup${item.id}`] 为 true dangerouslyUseHTMLString: true,
if (item.dill === 'add') { customClass: 'manageWebNotify',
popupVises[`popup${item.id}`] = true message: `
// 右下角弹出超限警告
let overArr = item.overType.split(',')
let overStr = ''
for (let t of overArr) {
overStr += dict.overCarType[t]
}
this.$notify({
title: '超限车辆',
dangerouslyUseHTMLString: true,
customClass: 'manageWebNotify',
message: `
<div>车牌号:${item.picLicense || '--'}</div> <div>车牌号:${item.picLicense || '--'}</div>
<div>超限类型:${overStr}</div> <div>超限类型:${overStr}</div>
<div>预警时间:${item.timeStamp}</div> <div>预警时间:${item.overRun.timeStamp}</div>
`, `,
type: 'warning', type: 'warning',
position: 'bottom-right', position: 'bottom-right',
duration: 5000 duration: 5000
}); });
} }
if (['add', 'com'].includes(item.dill)) { if (['add', 'com'].includes(item.dill)) {
if (popupVises[`popup${item.id}`]) { if (popupVises[`popup${item.id}`]) {
this.overCarsPoints[item.id] = [item.longitude, item.latitude] this.overCarsPoints[item.id] = [item.longitude, item.latitude]
this.addCheckDetail(item) this.addCheckDetail(item)
}
} else {
delete this.overCarsPoints[item.id]
vehiclePopups[`popup${item.id}`]?.remove();
}
} }
if (zoom > 18) { } else {
// 新增 delete this.overCarsPoints[item.id]
if ( vehiclePopups[`popup${item.id}`]?.remove();
item.dill === "add" || }
(item.dill === "com" && !vehicleModels[item.id]) } else {
) { if (this.overCarsPoints[item.id]) {
this.addVehicleModels(item); delete this.overCarsPoints[item.id]
if (this.licenseState) this.addVehicleLicenses(item); vehiclePopups[`popup${item.id}`]?.remove();
} else { }
// console.log("模型总数", Object.keys(vehicleModels).length); }
for (let key in vehicleModels) { // 超限车辆 end
if (vehicleModels[key].userData.data?.id === item.id) { if (zoom > 18) {
if (item.dill === "del") { // 新增
if (licenseLabel[`license${item.id}`]) { if (
window.tb.clear(`license${item.id}`, true); item.dill === "add" ||
delete licenseLabel[`license${item.id}`]; (item.dill === "com" && !vehicleModels[item.id])
} ) {
if (vehicleModels[key]) { this.addVehicleModels(item);
window.tb.clear(item.id, true); if (this.licenseState) this.addVehicleLicenses(item);
delete vehicleModels[key]; } else {
} // console.log("模型总数", Object.keys(vehicleModels).length);
for (let key in vehicleModels) {
if (vehicleModels[key].userData.data?.id === item.id) {
if (item.dill === "del") {
if (licenseLabel[`license${item.id}`]) {
window.tb.clear(`license${item.id}`, true);
delete licenseLabel[`license${item.id}`];
}
if (vehicleModels[key]) {
window.tb.clear(item.id, true);
delete vehicleModels[key];
}
}
if (item.dill === "com") {
// 车型中途变化 清除并重新创建
if (
vehicleModels[key].userData.data.originalType !==
item.originalType
) {
if (vehicleModels[key]) {
window.tb.clear(item.id, true);
delete vehicleModels[key];
} }
if (item.dill === "com") { if (licenseLabel[`license${item.id}`]) {
// 车型中途变化 清除并重新创建 window.tb.clear(`license${item.id}`, true);
delete licenseLabel[`license${item.id}`];
}
this.addVehicleModels(item);
if (this.licenseState) this.addVehicleLicenses(item);
} else {
if (licenseLabel[`license${item.id}`]) {
// 如果车牌model存在且未改变 则setCoords
if ( if (
vehicleModels[key].userData.data.originalType !== licenseLabel[`license${item.id}`].userData.data
item.originalType .picLicense == item.picLicense
) { ) {
if (vehicleModels[key]) { licenseLabel[`license${item.id}`].setCoords([
window.tb.clear(item.id, true); item.longitude,
delete vehicleModels[key]; item.latitude,
} 4,
if (licenseLabel[`license${item.id}`]) { ]);
window.tb.clear(`license${item.id}`, true);
delete licenseLabel[`license${item.id}`];
}
this.addVehicleModels(item);
if (this.licenseState) this.addVehicleLicenses(item);
} else {
if (licenseLabel[`license${item.id}`]) {
// 如果车牌model存在且未改变 则setCoords
if (
licenseLabel[`license${item.id}`].userData.data
.picLicense == item.picLicense
) {
licenseLabel[`license${item.id}`].setCoords([
item.longitude,
item.latitude,
4,
]);
}
// 否则先删除当前车牌 再创建更新后的车牌
else {
window.tb.clear(`license${item.id}`, true);
delete licenseLabel[`license${item.id}`];
this.addVehicleLicenses(item);
}
} else {
if (this.licenseState)
this.addVehicleLicenses(item);
}
this.setModel(vehicleModels[key], item, true);
} }
// 否则先删除当前车牌 再创建更新后的车牌
else {
window.tb.clear(`license${item.id}`, true);
delete licenseLabel[`license${item.id}`];
this.addVehicleLicenses(item);
}
} else {
if (this.licenseState)
this.addVehicleLicenses(item);
} }
this.setModel(vehicleModels[key], item, true);
} }
} }
} }
} }
} }
this.updateSelectVehicleTrack()
this.updateOverCarLnglat()
this.lastLocation = msg;
} }
} }
this.updateSelectVehicleTrack()
this.updateOverCarLnglat()
this.lastLocation = msg;
// }
} }
}, },
vehicleCircleClick(e) { vehicleCircleClick(e) {
const features = map.queryRenderedFeatures(e.point, { const features = map.queryRenderedFeatures(e.point, {
...@@ -1235,7 +1317,6 @@ export default { ...@@ -1235,7 +1317,6 @@ export default {
}); });
}, },
closeAllWs() { closeAllWs() {
this.layerShowRenders = false;
// console.log("sockets...", this.sockets); // console.log("sockets...", this.sockets);
const closePromises = this.sockets.map((socket) => { const closePromises = this.sockets.map((socket) => {
return new Promise((resolve) => { return new Promise((resolve) => {
......
...@@ -30,6 +30,12 @@ ...@@ -30,6 +30,12 @@
<div class="detailItem" v-show="!notExceed"> <div class="detailItem" v-show="!notExceed">
<span class="left">超限类型:</span>{{ overTypeStr }} <span class="left">超限类型:</span>{{ overTypeStr }}
</div> </div>
<div class="detailItem" v-show="!notExceed">
<span class="left">宽度:</span>{{ overWidth }}
</div>
<div class="detailItem" v-show="!notExceed">
<span class="left">高度:</span>{{ overHeight }}
</div>
<div class="detailItem"> <div class="detailItem">
<span class="left">ID :</span>{{ model.id }} <span class="left">ID :</span>{{ model.id }}
</div> </div>
...@@ -78,12 +84,21 @@ export default { ...@@ -78,12 +84,21 @@ export default {
}, },
}, },
computed: { computed: {
overWidth() {
return this.model.overRun?.vehicleWidth || '--'
},
overHeight() {
return this.model.overRun?.vehicleHeight || '--'
},
notExceed() { notExceed() {
return !this.model.overType if (!this.model.overRun || !this.model.overRun.overType) {
return true
}
return false
}, },
overTypeStr() { overTypeStr() {
if (this.model.overType) { if (this.model.overRun?.overType) {
let overArr = this.model.overType.split(',') let overArr = this.model.overRun.overType.split(',')
let overStr = '' let overStr = ''
for (let t of overArr) { for (let t of overArr) {
overStr += dict.overCarType[t] overStr += dict.overCarType[t]
...@@ -92,7 +107,7 @@ export default { ...@@ -92,7 +107,7 @@ export default {
} }
}, },
overTime() { overTime() {
return this.model.timeStamp || '--' return this.model.overRun?.timeStamp || '--'
} }
}, },
beforeDestroy() { }, beforeDestroy() { },
......
<template>
<div id="holo_historyCameraContainer" class="eventCameraContainer" v-show="true">
<div id="historyCameraContainer" class="historyCameraContainer">
<div class="cameraVideoShow" :key="index" v-for="(item, index) of channels" v-show="true"
:id="`videoVisibles${item}`">
<loop-video class="holo_his" ref="hisVideo" :autoplay="true" :timeModel="timeDuration" :channel="item"></loop-video>
</div>
</div>
</div>
</template>
<script>
import LoopVideo from "../../../components/Standard/loopVideo.vue";
export default {
name: "historyVideos",
components: {
LoopVideo,
},
props: {
channels: {
type: Array,
default() {
return ['2', '9']
}
},
timeDuration: {
type: Object,
default() {
return {
startTime: '',
endTime: ''
}
}
},
},
data() {
return {
}
},
computed: {},
methods: {
// playHisVideos() {
// if (this.$refs.hisVideo) {
// for (let container of this.$refs.hisVideo) {
// container?.startPlay();
// }
// }
// }
},
};
</script>
<style lang="less" scoped>
.eventCameraContainer {
position: absolute;
width: 600px;
height: 200px;
max-width: 600px;
bottom: 40px;
left: 50%;
transform: translateX(-50%);
display: flex;
margin: 0 auto;
border: 1px solid rgba(83, 146, 189, 1);
background: rgba(10, 26, 41, 0.9);
border-radius: 6px;
.holo_his{
border: 1px solid rgba(255,255,255,0.3);
}
.historyCameraContainer {
display: flex;
flex-direction: row;
align-items: center;
width: 100%;
height: 100%;
.cameraVideoShow {
width: 50%;
height: 100%;
padding: 4px;
}
.lessWidthVideo {
width: calc(100% - 6px);
}
.normalWidthVideo {
width: 100%;
}
}
.noVideo {
pointer-events: none;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
font-size: 32px;
color: #04396f;
}
}
</style>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment