You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
446 lines
13 KiB
446 lines
13 KiB
<template>
|
|
<Bg1 class='RoadAndEvents'>
|
|
<div class="tabs">
|
|
<div class="tabs-item" :class="layer.title === active ? 'tabs-active' : ''" v-for="layer in layerData"
|
|
:key="layer.title" @click="handleClick(layer)">
|
|
{{ layer.title }}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- group -->
|
|
<div name="fade-group" tag="div" class="tabs-content">
|
|
<div class="device-item keep-ratio" v-for="(item, index) in tabContentData" :key="item.id"
|
|
@click="handleDevice(item)" :style="getStart(index)">
|
|
<div class="device-icon"
|
|
:style="{ backgroundImage: `url(${require(`@screen/images/layer/${active}/${item.title}${item.status}.svg`)})`, '--bgColor': `rgba(0, 209, 255, ${item.status ? 0.3 : 0})` }" />
|
|
<span>{{ item.title }}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="bottom">
|
|
<div class="cleared-btn" @click="handleCleared">
|
|
<img src="@screen/images/clearLayer.svg" />
|
|
<span>清空图层</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 摄像机设备 控制 弹窗 球机 可打开-->
|
|
<!-- 摄像机 G35 K094+079 下行(可控) 枪机 可打开-->
|
|
<!-- <Camera :data="dialogConfig.data" :visible="dialogConfig.visibleType === 1" /> -->
|
|
<component :dialogData="dialogConfig.data" visible :selectedDevice="dialogConfig.data" :is="dialogConfig.component"
|
|
@change="handleCameraChange" @update:visible="handleCameraChange" />
|
|
</Bg1>
|
|
</template>
|
|
|
|
<script>
|
|
import { getLayerData } from "./utils/layerImages";
|
|
import { debounce } from "lodash";
|
|
import { eventMap, cacheRemoveFunc, getHandleDeviceType } from "./utils/buttonEvent";
|
|
|
|
import Bg1 from "@screen/components/Decorations/bg-1.vue"
|
|
import InfoBoard from "./../InfoBoard/index.vue"
|
|
|
|
import DrivingGuidance from "./../Dialogs/DrivingGuidance/index.vue"
|
|
import Camera from "./../Dialogs/Camera/index.vue";
|
|
import Broadcast from "./../Dialogs/Broadcast/index.vue";
|
|
import TrafficIncidents from "./../Dialogs/TrafficIncidents/index.vue";
|
|
import PerceiveEvent from "./../Dialogs/PerceiveEvent/index.vue";
|
|
import SmartDevice from "./../Dialogs/SmartDevice/index.vue";
|
|
import SolarEnergy from "./../Dialogs/SolarEnergy/index.vue";
|
|
import Intermodulation from "./../Dialogs/Intermodulation/index.vue";
|
|
import GuardrailCollision from "./../Dialogs/GuardrailCollision/index.vue";
|
|
|
|
import FatigueWakesUp from "./../Dialogs/FatigueWakesUp/index.vue";
|
|
import { addInGraphHandle } from "./utils/map"
|
|
import { lngLatMap } from "./utils/buttonEvent";
|
|
|
|
export default {
|
|
name: 'RoadAndEvents',//首页弹窗 渲染基类
|
|
components: {
|
|
// ControlCamera,
|
|
Camera,
|
|
DrivingGuidance,
|
|
Bg1,
|
|
InfoBoard,
|
|
Broadcast,
|
|
TrafficIncidents,
|
|
PerceiveEvent,
|
|
SmartDevice,
|
|
SolarEnergy,
|
|
Intermodulation,
|
|
GuardrailCollision,
|
|
FatigueWakesUp
|
|
},
|
|
data() {
|
|
return {
|
|
// testData:{
|
|
// visible:true,
|
|
// device: {
|
|
// "id": 904,
|
|
// "iotDeviceId": "81221-65535",
|
|
// "groupId": null,
|
|
// "productId": 0,
|
|
// "stakeMark": "k59+289",
|
|
// "direction": "1",
|
|
// "deviceName": "大学城入口站前板",
|
|
// "deviceType": 2,
|
|
// "installationDate": null,
|
|
// "productionDate": null,
|
|
// "durableYears": null,
|
|
// "installationSite": null,
|
|
// "useState": null,
|
|
// "otherConfig": "{\"screenSize\":\"160*80\"}",
|
|
// "remark": null,
|
|
// "createTime": "2024-01-10T15:48:59.000+08:00",
|
|
// "updateTime": null
|
|
// }
|
|
// },
|
|
layerData: [],
|
|
active: "事件专题",
|
|
tabContentData: [],
|
|
nowSelected: null, //当前点击选中的事件 title
|
|
nowSelectedCompleted: true, //选中事件的处理是否完成
|
|
// 路测设备-摄像机
|
|
dialogConfig: {
|
|
// 0 有 可控(球机) ControlCamera | 1 ⽆ 不可控(枪机) Camera
|
|
component: void 0,
|
|
data: void 0,
|
|
// component: "SmartDevice",
|
|
data: {
|
|
"searchValue": null,
|
|
"createBy": null,
|
|
"createTime": "2024-07-23 14:18:58",
|
|
"updateBy": null,
|
|
"updateTime": null,
|
|
"remark": null,
|
|
"params": {},
|
|
"id": 11,
|
|
"stakeMark": "k103+900",
|
|
"direction": "1",
|
|
"deptId": null,
|
|
"warningState": 1,
|
|
"warningTime": null,
|
|
"userId": null,
|
|
"warningSource": 1,
|
|
"warningLevel": null,
|
|
"warningType": 1,
|
|
"warningSubclass": null,
|
|
"warningTitle": null,
|
|
"otherConfig": null,
|
|
"sectionName": null,
|
|
"number": 0,
|
|
"type": null,
|
|
"sectionId": null,
|
|
"longitude": "116.493888",
|
|
"latitude": "36.291145"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
props: {
|
|
isGisCompleted: {
|
|
type: Boolean,
|
|
default: () => false
|
|
}
|
|
},
|
|
watch: {
|
|
isGisCompleted: {
|
|
async handler(bool) {
|
|
if (!bool) return;
|
|
await Promise.allSettled((this.tabContentData || []).map(item => this.handleDeviceImmediate(item, true)))
|
|
Object.keys(lngLatMap).forEach(key => {
|
|
addInGraphHandle(lngLatMap[key]);
|
|
});
|
|
}
|
|
}
|
|
},
|
|
inject: ['getMap', 'activeDeviceTypes'],
|
|
created() {
|
|
const defaultActive = 0;
|
|
|
|
const layerData = getLayerData();
|
|
this.layerData = layerData;
|
|
this.tabContentData = layerData[defaultActive].children || [];
|
|
this.active = layerData[defaultActive].title;
|
|
|
|
this.minLayers = 3;
|
|
this.emitter.on("selectedCompleted", this.selectedCompletedHandle);
|
|
},
|
|
mounted() {
|
|
// 获取原始 Layer
|
|
const getMinMapLayers = (time = 0) => {
|
|
setTimeout(() => {
|
|
const { mapIns } = this.getMap();
|
|
|
|
if (!mapIns) return getMinMapLayers(150);
|
|
|
|
this.minLayers = mapIns.getLayers().length - 1;
|
|
}, time);
|
|
}
|
|
|
|
getMinMapLayers();
|
|
},
|
|
beforeDestroy() {
|
|
this.emitter.off("selectedCompleted", this.selectedCompletedHandle);
|
|
},
|
|
methods: {
|
|
selectedCompletedHandle(item) {
|
|
if (this.nowSelected === item.title) this.nowSelectedCompleted = true;
|
|
},
|
|
setFilterDataNoAction(data) { //纯更新data
|
|
this.filterData = data;
|
|
},
|
|
async setFilterData(data) {//更新并调用接口
|
|
this.filterData = data;
|
|
const tabContentData = [];
|
|
this.layerData.forEach((layerDataItem => {
|
|
layerDataItem.children.forEach(item => {
|
|
if (!item.status) return;
|
|
tabContentData.push(item);
|
|
// this.handleDeviceImmediate(item);
|
|
// this.handleDeviceImmediate(item);
|
|
})
|
|
}));
|
|
const eventMapCall = async (item, isDefault) => {
|
|
const key = getHandleDeviceType(item) || `${this.active}/${item.title}`;
|
|
const status = item.status;
|
|
// if (!eventMap[`${key}${status ? "_close" : ""}`]) return this.$emit("onClickItem", item);
|
|
// console.log(`${key}${status ? "" : "_close"}`, this.filterData, 'xxx');
|
|
await eventMap[`${key}${status ? "" : "_close"}`]?.call(this, item, this.filterData, isDefault, this.cb);
|
|
}
|
|
await Promise.allSettled(tabContentData.map(item => eventMapCall(item, true)))
|
|
Object.keys(lngLatMap).forEach(key => {
|
|
addInGraphHandle(lngLatMap[key]);
|
|
});
|
|
},
|
|
handleClick(item) {
|
|
this.active = item.title;
|
|
this.tabContentData = item.children;
|
|
},
|
|
cb(item, config) {
|
|
const deviceType = config.deviceType;
|
|
const activeDeviceTypes = this.activeDeviceTypes;
|
|
const findIndex = activeDeviceTypes.indexOf(deviceType);
|
|
if (item.status) findIndex === -1 && activeDeviceTypes.push(deviceType);
|
|
else findIndex !== -1 && activeDeviceTypes.splice(findIndex, 1);
|
|
},
|
|
async handleDeviceImmediate(item, isDefault) {
|
|
const key = getHandleDeviceType(item) || `${this.active}/${item.title}`;
|
|
|
|
const status = item.status;
|
|
|
|
if (!status) { //开启
|
|
this.nowSelected = item.title;
|
|
this.nowSelectedCompleted = false;
|
|
}
|
|
else if (this.nowSelected === item.title && this.nowSelectedCompleted === false) return;
|
|
|
|
item.status = item.status ? "" : "_active";
|
|
|
|
console.log("%c [ key ]-102-「index.vue」", "font-size:15px; background:#9d63e9; color:#e1a7ff;", key);
|
|
|
|
if (!eventMap[`${key}${status ? "_close" : ""}`]) {
|
|
this.emitter.emit("selectedCompleted", item);
|
|
return this.$emit("onClickItem", item);
|
|
}
|
|
console.log(`${key}${status ? "_close" : ""}`, this.filterData, isDefault)
|
|
|
|
await eventMap[`${key}${status ? "_close" : ""}`]?.call(this, item, this.filterData, isDefault, this.cb);
|
|
},
|
|
handleDevice: debounce(async function (item) {
|
|
await this.handleDeviceImmediate(item);
|
|
}, 360),
|
|
handleCleared() {
|
|
const { mapIns } = this.getMap();
|
|
|
|
this.layerData.forEach(({ children }) => {
|
|
children.forEach(item => item.status = "")
|
|
});
|
|
|
|
if (!mapIns) return;
|
|
|
|
for (const key in cacheRemoveFunc) {
|
|
cacheRemoveFunc[key]?.();
|
|
}
|
|
|
|
// mapIns.clearMap();
|
|
mapIns.getLayers().forEach((layer, index) => index > this.minLayers && mapIns.remove(layer))
|
|
window.infoWindow.close();
|
|
},
|
|
|
|
// 摄像机 可控 不可控 弹窗 回调
|
|
handleCameraChange() {
|
|
this.dialogConfig = {
|
|
// 0 有 可控(球机)ControlCamera | 1 ⽆ 不可控(枪机)Camera
|
|
component: null,
|
|
data: null
|
|
}
|
|
},
|
|
getStart(index) {
|
|
const columns = 5;
|
|
|
|
return {
|
|
gridRowStart: Math.floor(index / columns) + 1,
|
|
gridColumnStart: (index % columns) + 1,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang='scss' scoped>
|
|
.fade-enter-active,
|
|
.fade-leave-active {
|
|
transition: opacity .24s;
|
|
}
|
|
|
|
.fade-enter,
|
|
.fade-leave-to {
|
|
opacity: 0;
|
|
}
|
|
|
|
.fade-group-enter-active,
|
|
.fade-group-leave-active {
|
|
transition: all 0.24s ease;
|
|
}
|
|
|
|
.fade-group-enter-from,
|
|
.fade-group-leave-to {
|
|
opacity: 0;
|
|
}
|
|
|
|
.RoadAndEvents {
|
|
width: 100%;
|
|
// background: url("~@screen/images/bg/box_bg_002.png") no-repeat;
|
|
// clip-path: polygon(13% 0, 87% 0, 100% 14%, 100% 85%, 85% 100%, 11% 100%, 0 87%, 0 15%);
|
|
// background-size: 100% 100%;
|
|
position: relative;
|
|
display: flex;
|
|
flex-direction: column;
|
|
padding: 24px 18px;
|
|
padding-bottom: 15px;
|
|
overflow: hidden;
|
|
max-height: min-content;
|
|
|
|
.tabs-content {
|
|
margin-top: 15px;
|
|
margin-bottom: 6px;
|
|
display: grid;
|
|
grid-template-columns: repeat(5, 1fr);
|
|
grid-auto-rows: 60px;
|
|
flex: 1;
|
|
max-height: 100%;
|
|
// overflow: auto;
|
|
position: relative;
|
|
gap: 6px;
|
|
transition: all .24s linear;
|
|
|
|
.device-item {
|
|
// position: absolute;
|
|
position: relative;
|
|
width: 70px;
|
|
cursor: pointer;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
--height-svg: 24px;
|
|
--gap: 12px;
|
|
transition: all .15s linear;
|
|
padding-top: calc(var(--height-svg) + var(--gap));
|
|
|
|
.device-icon {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
position: absolute;
|
|
transition: all .15s linear;
|
|
top: 0;
|
|
height: 33px;
|
|
width: 100%;
|
|
background-repeat: no-repeat;
|
|
background-size: auto;
|
|
background-position: center;
|
|
transition: all .18s linear;
|
|
|
|
&::before {
|
|
content: "";
|
|
position: absolute;
|
|
width: 33px;
|
|
height: 33px;
|
|
border: 1px solid rgba(0, 209, 255, .5);
|
|
background-color: var(--bgColor);
|
|
border-radius: 50%;
|
|
z-index: -1;
|
|
}
|
|
}
|
|
|
|
span {
|
|
display: block;
|
|
text-align: center;
|
|
font-size: 13px;
|
|
font-family: PingFang SC, PingFang SC;
|
|
font-weight: 500;
|
|
color: #ffffff;
|
|
line-height: 15px;
|
|
min-height: 27px;
|
|
}
|
|
}
|
|
}
|
|
|
|
.tabs {
|
|
display: flex;
|
|
overflow: hidden;
|
|
gap: 24px;
|
|
|
|
.tabs-item {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
cursor: pointer;
|
|
// width: 128px;
|
|
flex: 1;
|
|
height: 36px;
|
|
background: url("~@screen/images/bg/box_bg_005.png") no-repeat;
|
|
background-size: 100% 100%;
|
|
font-size: 15px;
|
|
font-family: PingFang SC, PingFang SC;
|
|
font-weight: 500;
|
|
color: #ffffff;
|
|
transition: all .3s linear;
|
|
}
|
|
|
|
.tabs-active {
|
|
color: #00d1ff;
|
|
background: url("~@screen/images/bg/box_bg_005_active.png") no-repeat;
|
|
background-size: 100% 100%;
|
|
}
|
|
}
|
|
|
|
.bottom {
|
|
display: flex;
|
|
justify-content: end;
|
|
|
|
.cleared-btn {
|
|
// position: absolute;
|
|
cursor: pointer;
|
|
width: 98px;
|
|
height: 31px;
|
|
border-radius: 20px;
|
|
border: 1px solid #25d8ff;
|
|
font-size: 12px;
|
|
font-family: PingFang SC, PingFang SC;
|
|
font-weight: 500;
|
|
color: #ffffff;
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
img {
|
|
width: 16px;
|
|
height: 16px;
|
|
display: inline-block;
|
|
margin: 0 10px;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|
|
|