parent
f70b2905dd
commit
9ec6f41e6f
|
@ -13,6 +13,7 @@
|
|||
"dayjs": "^1.11.10",
|
||||
"echarts": "^5.5.0",
|
||||
"element-plus": "^2.6.2",
|
||||
"hls.js": "^1.6.5",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mitt": "^3.0.1",
|
||||
"mockjs": "^1.1.0",
|
||||
|
@ -2892,6 +2893,11 @@
|
|||
"he": "bin/he"
|
||||
}
|
||||
},
|
||||
"node_modules/hls.js": {
|
||||
"version": "1.6.5",
|
||||
"resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.6.5.tgz",
|
||||
"integrity": "sha512-KMn5n7JBK+olC342740hDPHnGWfE8FiHtGMOdJPfUjRdARTWj9OB+8c13fnsf9sk1VtpuU2fKSgUjHvg4rNbzQ=="
|
||||
},
|
||||
"node_modules/hosted-git-info": {
|
||||
"version": "2.8.9",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
"dayjs": "^1.11.10",
|
||||
"echarts": "^5.5.0",
|
||||
"element-plus": "^2.6.2",
|
||||
"hls.js": "^1.6.5",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mitt": "^3.0.1",
|
||||
"mockjs": "^1.1.0",
|
||||
|
|
|
@ -85,4 +85,24 @@ export const todayHourly=(param:any={})=>{
|
|||
/**获取当天每小时总车流量和平均车流量 */
|
||||
export const trafficTrend=(param:any={})=>{
|
||||
return GET('/device/trafficFlow/trafficTrend',param)
|
||||
}
|
||||
}
|
||||
|
||||
/**事件历史记录管理 历史数据 */
|
||||
export const meventListHistory=(param:any={})=>{
|
||||
return GET('/device/mevent/listHistory',param)
|
||||
}
|
||||
|
||||
/**数据字典-根据类型获取字典数据 */
|
||||
export const getDictData = (dictType: string) => {
|
||||
return GET(`/system/dict/data/type/${dictType}`);
|
||||
}
|
||||
|
||||
/**视频监控设备列表*/
|
||||
export const getVideoDeviceList = (param: any = {}) => {
|
||||
return POST('/video/device/list', param);
|
||||
}
|
||||
|
||||
/**视频流 */
|
||||
export const videoStream=(param:any={})=>{
|
||||
return GET('/video/stream',param)
|
||||
}
|
||||
|
|
|
@ -1,52 +1,79 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, computed } from "vue";
|
||||
import { ref, computed, onMounted } from "vue";
|
||||
import { meventListHistory } from "@/api/modules/index";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
interface EventItem {
|
||||
type: string;
|
||||
location: string;
|
||||
time: string;
|
||||
status: "处置中" | "待处置";
|
||||
}
|
||||
|
||||
// 模拟数据
|
||||
const wrongWayEvents = ref<EventItem[]>([
|
||||
{
|
||||
location: "邯郸方向 K34+230",
|
||||
time: "2025-4-15 12:34:56",
|
||||
status: "处置中",
|
||||
},
|
||||
const allEvents = ref<EventItem[]>([
|
||||
// {
|
||||
// type: "车辆逆行",
|
||||
// location: "邯郸方向 K34+230",
|
||||
// time: "2025-4-15 12:34:56",
|
||||
// status: "处置中",
|
||||
// },
|
||||
// {
|
||||
// type: "道路施工",
|
||||
// location: "邯郸方向 K34+230",
|
||||
// time: "2025-4-15 12:34:56",
|
||||
// status: "待处置",
|
||||
// },
|
||||
// {
|
||||
// type: "车辆逆行",
|
||||
// location: "邯郸方向 K34+230",
|
||||
// time: "2025-4-15 12:34:56",
|
||||
// status: "待处置",
|
||||
// },
|
||||
]);
|
||||
|
||||
const roadWorkEvents = ref<EventItem[]>([
|
||||
{
|
||||
location: "邯郸方向 K34+230",
|
||||
time: "2025-4-15 12:34:56",
|
||||
status: "待处置",
|
||||
},
|
||||
]);
|
||||
// const wrongWayEvents = computed(() =>
|
||||
// allEvents.value.filter((e) => e.type === "车辆逆行")
|
||||
// );
|
||||
// const roadWorkEvents = computed(() =>
|
||||
// allEvents.value.filter((e) => e.type === "道路施工")
|
||||
// );
|
||||
|
||||
const formatTime = (time: string) => {
|
||||
return dayjs(time).format("YYYY-MM-DD HH:mm:ss");
|
||||
};
|
||||
onMounted(()=>{
|
||||
const endTime = dayjs().endOf('day').format('YYYY-MM-DD HH:mm:ss');
|
||||
const startTime = dayjs().subtract(6, 'day').startOf('day').format('YYYY-MM-DD HH:mm:ss');
|
||||
meventListHistory({startTime, endTime}).then((res)=>{
|
||||
console.log(res, 'rrreeesss')
|
||||
allEvents.value = res.rows.map((item: any) => ({
|
||||
type: item.eventType,
|
||||
location: (item.direction === '1' ? '黄骅港方向 ' : item.direction === '2' ? '邯郸方向 ' : '') + item.pilenum,
|
||||
time: item.time,
|
||||
status: item.status == '0' ? '待处置' : '处置中',
|
||||
}));
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="event-task">
|
||||
<div class="event-section">
|
||||
<div v-for="(event, index) in allEvents"
|
||||
:key="index" class="event-section">
|
||||
<div class="section-header">
|
||||
<div style="color: #fbfbfc">车辆逆行</div>
|
||||
<div style="color: #fbfbfc">{{event.type}}</div>
|
||||
<div
|
||||
v-if="wrongWayEvents.length"
|
||||
class="event-status"
|
||||
:class="{ processing: wrongWayEvents[0].status === '处置中' }"
|
||||
:class="{
|
||||
processing: event.status === '处置中',
|
||||
pending: event.status === '待处置'
|
||||
}"
|
||||
>
|
||||
{{ wrongWayEvents[0].status }}
|
||||
{{ event.status }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="event-list" v-if="wrongWayEvents.length">
|
||||
<div class="event-list">
|
||||
<div
|
||||
v-for="(event, index) in wrongWayEvents"
|
||||
:key="index"
|
||||
class="event-item"
|
||||
>
|
||||
<div class="event-info">
|
||||
|
@ -55,10 +82,10 @@ const formatTime = (time: string) => {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="empty-state">暂无逆行事件</div>
|
||||
<!-- <div v-else class="empty-state">暂无逆行事件</div> -->
|
||||
</div>
|
||||
|
||||
<div class="event-section">
|
||||
<!-- <div class="event-section">
|
||||
<div class="section-header">
|
||||
<div style="color: #fbfbfc">道路施工</div>
|
||||
<div
|
||||
|
@ -82,7 +109,7 @@ const formatTime = (time: string) => {
|
|||
</div>
|
||||
</div>
|
||||
<div v-else class="empty-state">暂无施工事件</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -96,7 +123,22 @@ const formatTime = (time: string) => {
|
|||
background: transparent;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
overflow-y: scroll;
|
||||
z-index: 9999;
|
||||
&::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: linear-gradient(180deg, #00c6ff 0%, #085b9f 100%);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background: rgba(0, 198, 255, 0.08);
|
||||
border-radius: 4px;
|
||||
}
|
||||
.event-section {
|
||||
height: calc(50% - 10px);
|
||||
background: linear-gradient(
|
||||
|
@ -112,7 +154,7 @@ const formatTime = (time: string) => {
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
// overflow: hidden;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
|
@ -129,20 +171,20 @@ const formatTime = (time: string) => {
|
|||
);
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 1px;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
transparent,
|
||||
rgba(0, 198, 255, 0.3),
|
||||
transparent
|
||||
);
|
||||
}
|
||||
// &::after {
|
||||
// content: "";
|
||||
// position: absolute;
|
||||
// bottom: 0;
|
||||
// left: 0;
|
||||
// right: 0;
|
||||
// height: 1px;
|
||||
// background: linear-gradient(
|
||||
// 90deg,
|
||||
// transparent,
|
||||
// rgba(0, 198, 255, 0.3),
|
||||
// transparent
|
||||
// );
|
||||
// }
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
|
@ -151,22 +193,22 @@ const formatTime = (time: string) => {
|
|||
gap: 12px;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 1px solid rgba(0, 198, 255, 0.1);
|
||||
position: relative;
|
||||
border: 1px solid rgba(0, 198, 255, 0.1);
|
||||
// position: relative;
|
||||
background-color: #0e2d51;
|
||||
border-radius: 15px;
|
||||
padding: 14px;
|
||||
font-size: 22px;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: -1px;
|
||||
left: 0;
|
||||
width: 100px;
|
||||
height: 1px;
|
||||
background: linear-gradient(90deg, #00c6ff, transparent);
|
||||
}
|
||||
// &::after {
|
||||
// content: "";
|
||||
// position: absolute;
|
||||
// bottom: -1px;
|
||||
// left: 0;
|
||||
// width: 100px;
|
||||
// height: 1px;
|
||||
// background: linear-gradient(90deg, #00c6ff, transparent);
|
||||
// }
|
||||
|
||||
i {
|
||||
width: 32px;
|
||||
|
@ -229,7 +271,7 @@ const formatTime = (time: string) => {
|
|||
|
||||
.event-list {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
//overflow-y: auto;
|
||||
padding-right: 4px;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
|
@ -258,36 +300,36 @@ const formatTime = (time: string) => {
|
|||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 1px;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
transparent,
|
||||
rgba(0, 198, 255, 0.2),
|
||||
transparent
|
||||
);
|
||||
}
|
||||
// &::before {
|
||||
// content: "";
|
||||
// position: absolute;
|
||||
// top: 0;
|
||||
// left: 0;
|
||||
// right: 0;
|
||||
// height: 1px;
|
||||
// background: linear-gradient(
|
||||
// 90deg,
|
||||
// transparent,
|
||||
// rgba(0, 198, 255, 0.2),
|
||||
// transparent
|
||||
// );
|
||||
// }
|
||||
|
||||
&:hover {
|
||||
background: rgba(4, 49, 128, 0.3);
|
||||
border-color: rgba(0, 198, 255, 0.3);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 20px rgba(0, 198, 255, 0.15);
|
||||
// &:hover {
|
||||
// background: rgba(4, 49, 128, 0.3);
|
||||
// border-color: rgba(0, 198, 255, 0.3);
|
||||
// transform: translateY(-2px);
|
||||
// box-shadow: 0 4px 20px rgba(0, 198, 255, 0.15);
|
||||
|
||||
&::before {
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
transparent,
|
||||
rgba(0, 198, 255, 0.4),
|
||||
transparent
|
||||
);
|
||||
}
|
||||
}
|
||||
// &::before {
|
||||
// background: linear-gradient(
|
||||
// 90deg,
|
||||
// transparent,
|
||||
// rgba(0, 198, 255, 0.4),
|
||||
// transparent
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
.event-info {
|
||||
display: flex;
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { ref, onMounted, nextTick } from "vue";
|
||||
import demoImage from "@/assets/img/demo.png";
|
||||
import { getVideoDeviceList, videoStream } from "@/api/modules/index";
|
||||
import Hls from "hls.js";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
const videoUrl = ref(""); // 保存m3u8地址
|
||||
const videoRef = ref<HTMLVideoElement | null>(null);
|
||||
// 设备状态数据
|
||||
const deviceStatus = ref({
|
||||
normal: 248,
|
||||
|
@ -10,49 +15,50 @@ const deviceStatus = ref({
|
|||
|
||||
// 监控点分组数据
|
||||
const monitoringGroups = ref([
|
||||
{
|
||||
id: 1,
|
||||
name: "邯港方向",
|
||||
count: 5,
|
||||
expanded: true,
|
||||
points: [
|
||||
{ id: 1, name: "邯港方向监控001", status: "正常" },
|
||||
{ id: 2, name: "邯港方向监控002", status: "正常" },
|
||||
{ id: 3, name: "邯港方向监控003", status: "正常" },
|
||||
{ id: 4, name: "邯港方向监控004", status: "正常" },
|
||||
{ id: 5, name: "邯港方向监控005", status: "正常" },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "黄驿港方向",
|
||||
count: 12,
|
||||
expanded: false,
|
||||
points: [],
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "收费站",
|
||||
count: 5,
|
||||
expanded: true,
|
||||
points: [
|
||||
{ id: 6, name: "收费站监控001", status: "正常" },
|
||||
{ id: 7, name: "收费站监控002", status: "正常" },
|
||||
{ id: 8, name: "收费站监控003", status: "正常" },
|
||||
{ id: 9, name: "收费站监控004", status: "正常" },
|
||||
],
|
||||
},
|
||||
// {
|
||||
// id: 1,
|
||||
// name: "邯港方向",
|
||||
// count: 5,
|
||||
// expanded: true,
|
||||
// points: [
|
||||
// { id: 1, name: "邯港方向监控001", status: "正常" },
|
||||
// { id: 2, name: "邯港方向监控002", status: "正常" },
|
||||
// { id: 3, name: "邯港方向监控003", status: "正常" },
|
||||
// { id: 4, name: "邯港方向监控004", status: "正常" },
|
||||
// { id: 5, name: "邯港方向监控005", status: "正常" },
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// id: 2,
|
||||
// name: "黄驿港方向",
|
||||
// count: 12,
|
||||
// expanded: false,
|
||||
// points: [],
|
||||
// },
|
||||
// {
|
||||
// id: 3,
|
||||
// name: "收费站",
|
||||
// count: 5,
|
||||
// expanded: true,
|
||||
// points: [
|
||||
// { id: 6, name: "收费站监控001", status: "正常" },
|
||||
// { id: 7, name: "收费站监控002", status: "正常" },
|
||||
// { id: 8, name: "收费站监控003", status: "正常" },
|
||||
// { id: 9, name: "收费站监控004", status: "正常" },
|
||||
// ],
|
||||
// },
|
||||
]);
|
||||
|
||||
// 固定的六个道路监控数据
|
||||
const fixedRoadMonitors = ref([
|
||||
{ id: 101, name: "高速公路监控001", image: demoImage },
|
||||
{ id: 102, name: "高速公路监控002", image: demoImage },
|
||||
{ id: 103, name: "高速公路监控003", image: demoImage },
|
||||
{ id: 104, name: "高速公路监控004", image: demoImage },
|
||||
{ id: 105, name: "高速公路监控005", image: demoImage },
|
||||
{ id: 106, name: "高速公路监控006", image: demoImage },
|
||||
]);
|
||||
// // 固定的六个道路监控数据
|
||||
// const fixedRoadMonitors = ref([
|
||||
// { id: 101, name: "高速公路监控001", src:'' },
|
||||
// { id: 102, name: "高速公路监控002", src:'' },
|
||||
// { id: 103, name: "高速公路监控003", src:'' },
|
||||
// { id: 104, name: "高速公路监控004", src:'' },
|
||||
// { id: 105, name: "高速公路监控005", src:'' },
|
||||
// { id: 106, name: "高速公路监控006", src:'' },
|
||||
// ]);
|
||||
const fixedRoadMonitors = ref<any[]>([]);
|
||||
|
||||
// 切换分组展开状态
|
||||
const toggleGroup = (group: any) => {
|
||||
|
@ -62,15 +68,72 @@ const toggleGroup = (group: any) => {
|
|||
// 选中的监控点
|
||||
const selectedPoints = ref<any[]>([]);
|
||||
|
||||
// 选择监控点
|
||||
const togglePoint = (point: any) => {
|
||||
const index = selectedPoints.value.findIndex((p) => p.id === point.id);
|
||||
// // 选择监控点
|
||||
// const togglePoint = (point: any) => {
|
||||
// const index = selectedPoints.value.findIndex((p) => p.channelCode === point.channelCode);
|
||||
// if (index > -1) {
|
||||
// selectedPoints.value.splice(index, 1);
|
||||
// } else {
|
||||
// selectedPoints.value.push(point);
|
||||
// }
|
||||
// videoStream({deviceCode:'00000000001311027500',channelCode:'00000000001311028602',}).then((res)=>{
|
||||
// videoUrl.value = res;
|
||||
// nextTick();
|
||||
// if (videoRef.value) {
|
||||
// if (Hls.isSupported()) {
|
||||
// const hls = new Hls();
|
||||
// hls.loadSource(videoUrl.value);
|
||||
// hls.attachMedia(videoRef.value);
|
||||
// } else if (videoRef.value.canPlayType('application/vnd.apple.mpegurl')) {
|
||||
// videoRef.value.src = videoUrl.value;
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// };
|
||||
const togglePoint = async (point: any) => {
|
||||
const index = selectedPoints.value.findIndex((p) => p.channelCode === point.channelCode);
|
||||
if (index > -1) {
|
||||
// 已选中则取消选中,并移除对应视频
|
||||
selectedPoints.value.splice(index, 1);
|
||||
const monitorIdx = fixedRoadMonitors.value.findIndex(m => m.channelCode === point.channelCode);
|
||||
if (monitorIdx > -1) {
|
||||
fixedRoadMonitors.value.splice(monitorIdx, 1);
|
||||
}
|
||||
} else {
|
||||
// 超过6个,移除最早的
|
||||
if (selectedPoints.value.length >= 6) {
|
||||
const removed = selectedPoints.value.shift();
|
||||
// 同步移除fixedRoadMonitors中对应的
|
||||
const rmIdx = fixedRoadMonitors.value.findIndex(m => m.channelCode === removed.channelCode);
|
||||
if (rmIdx > -1) fixedRoadMonitors.value.splice(rmIdx, 1);
|
||||
}
|
||||
selectedPoints.value.push(point);
|
||||
|
||||
// 获取视频流并放入fixedRoadMonitors
|
||||
const res = await videoStream({ deviceCode: point.deviceCode, channelCode: point.channelCode });
|
||||
// 保证fixedRoadMonitors只有6个
|
||||
if (fixedRoadMonitors.value.length >= 6) {
|
||||
fixedRoadMonitors.value.shift();
|
||||
}
|
||||
fixedRoadMonitors.value.push({
|
||||
...point,
|
||||
src: res
|
||||
});
|
||||
}
|
||||
};
|
||||
onMounted(()=>{
|
||||
const endTime = dayjs().endOf('day').format('YYYY-MM-DD HH:mm:ss');
|
||||
getVideoDeviceList({endTime:endTime, currentPage: 1, pageSize: 2}).then((res)=>{ //暂时是公共的 先取两条
|
||||
console.log(res, 'rrrrrrrrrrrrrrrrrrrrrrrrrsssssssssssss')
|
||||
if(res.code == 200){
|
||||
res.data.data.forEach((item)=>{
|
||||
item.expanded = true
|
||||
})
|
||||
monitoringGroups.value = res.data.data
|
||||
}
|
||||
console.log(monitoringGroups.value, 'monitoringGroups.value')
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -107,36 +170,36 @@ const togglePoint = (point: any) => {
|
|||
</div>
|
||||
<div class="list-content">
|
||||
<div
|
||||
v-for="group in monitoringGroups"
|
||||
:key="group.id"
|
||||
v-for="(group, index) in monitoringGroups"
|
||||
:key="index"
|
||||
class="group-item"
|
||||
>
|
||||
<div class="group-header" @click="toggleGroup(group)">
|
||||
<div class="group-name">
|
||||
<i class="arrow" :class="{ expanded: group.expanded }"></i>
|
||||
<!-- <i class="arrow" :class="{ expanded: group.expanded }"></i> -->
|
||||
<span style="font-size: 22.5px"
|
||||
>{{ group.name }}({{ group.count }})</span
|
||||
>{{ group.deviceName }}({{ group.channels.length }})</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="group-content" v-show="group.expanded">
|
||||
<div class="group-content" v-show="group.channels">
|
||||
<div
|
||||
v-for="point in group.points"
|
||||
:key="point.id"
|
||||
v-for="(point, vic) in group.channels"
|
||||
:key="point.channelCode"
|
||||
class="point-item"
|
||||
:class="{ active: selectedPoints.some((p) => p.id === point.id) }"
|
||||
:class="{ active: selectedPoints.some((p) => p.channelCode === point.channelCode) }"
|
||||
@click="togglePoint(point)"
|
||||
>
|
||||
<div class="point-info">
|
||||
<span class="point-name">{{ point.name }}</span>
|
||||
<span class="point-name">{{ point.channelName }}</span>
|
||||
<div class="status-wrapper">
|
||||
<span
|
||||
class="status-indicator"
|
||||
:class="point.status === '正常' ? 'normal' : 'warning'"
|
||||
:class="point.status === 1 ? 'normal' : 'warning'"
|
||||
></span>
|
||||
<span
|
||||
class="point-status"
|
||||
:class="point.status === '正常' ? 'normal' : 'warning'"
|
||||
:class="point.status === 1 ? 'normal' : 'warning'"
|
||||
>
|
||||
{{ point.status }}
|
||||
</span>
|
||||
|
@ -150,7 +213,7 @@ const togglePoint = (point: any) => {
|
|||
|
||||
<!-- 右侧图像网格 - 改为固定显示六张图片 -->
|
||||
<div class="monitor-grid">
|
||||
<div class="fixed-grid-container">
|
||||
<!-- <div class="fixed-grid-container">
|
||||
<div
|
||||
v-for="monitor in fixedRoadMonitors"
|
||||
:key="monitor.id"
|
||||
|
@ -161,7 +224,34 @@ const togglePoint = (point: any) => {
|
|||
<div class="corner-decoration bottom-left"></div>
|
||||
<div class="corner-decoration bottom-right"></div>
|
||||
<div class="image-container">
|
||||
<img :src="monitor.image" :alt="monitor.name" />
|
||||
<video
|
||||
ref="videoRef"
|
||||
v-if="videoUrl"
|
||||
controls
|
||||
autoplay
|
||||
style="width:100%;height:300px;background:#000"
|
||||
></video>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="fixed-grid-container">
|
||||
<div
|
||||
v-for="(monitor, idx) in fixedRoadMonitors"
|
||||
:key="monitor.channelCode || monitor.id || idx"
|
||||
class="grid-item"
|
||||
>
|
||||
<div class="corner-decoration top-left"></div>
|
||||
<div class="corner-decoration top-right"></div>
|
||||
<div class="corner-decoration bottom-left"></div>
|
||||
<div class="corner-decoration bottom-right"></div>
|
||||
<div class="image-container">
|
||||
<video
|
||||
v-if="monitor.src"
|
||||
:src="monitor.src"
|
||||
controls
|
||||
autoplay
|
||||
style="width:100%;height:300px;background:#000"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -321,30 +321,38 @@ const handleTimeRangeChange = (event: Event) => {
|
|||
// 这里可以添加切换时间范围的逻辑
|
||||
};
|
||||
const items = ref([
|
||||
{
|
||||
{
|
||||
defaultImg: eqm1Default,
|
||||
activeImg: eqm1Active,
|
||||
isActive: false,
|
||||
isActive: true, // 默认选中
|
||||
type: '44', //
|
||||
},
|
||||
{
|
||||
defaultImg: eqm2Default,
|
||||
activeImg: eqm2Active,
|
||||
isActive: false,
|
||||
isActive: true,
|
||||
type: '22', // 视频监控
|
||||
},
|
||||
{
|
||||
defaultImg: eqm3Default,
|
||||
activeImg: eqm3Active,
|
||||
isActive: false,
|
||||
isActive: true,
|
||||
type: '53', // 广播
|
||||
},
|
||||
{
|
||||
defaultImg: eqm4Default,
|
||||
activeImg: eqm4Active,
|
||||
isActive: false,
|
||||
isActive: true,
|
||||
type: '15', // 情报板
|
||||
},
|
||||
]);
|
||||
|
||||
const toggleSelection = (index: number) => {
|
||||
items.value[index].isActive = !items.value[index].isActive;
|
||||
// 通知地图组件切换显示/隐藏
|
||||
window.dispatchEvent(new CustomEvent('toggle-map-device', {
|
||||
detail: { type: items.value[index].type, show: items.value[index].isActive }
|
||||
}));
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -50,14 +50,14 @@ const iconModules = import.meta.glob("@/assets/img/map/*.png", {
|
|||
function getIcon(type, active = false) {
|
||||
const iconName =
|
||||
{
|
||||
1: active ? "lianzhen.png" : "lianzhen.png",
|
||||
2: active ? "datun.png" : "datun.png",
|
||||
3: active ? "zhaowang.png" : "zhaowang.png",
|
||||
4: active ? "dongguang.png" : "dongguang.png",
|
||||
5: active ? "nanpi.png" : "nanpi.png",
|
||||
6: active ? "zhaizi.png" : "zhaizi.png",
|
||||
7: active ? "xiaozhuang.png" : "xiaozhuang.png",
|
||||
8: active ? "warning.png" : "warning.png",
|
||||
// 1: active ? "lianzhen.png" : "lianzhen.png",
|
||||
// 2: active ? "datun.png" : "datun.png",
|
||||
// 3: active ? "zhaowang.png" : "zhaowang.png",
|
||||
// 4: active ? "dongguang.png" : "dongguang.png",
|
||||
// 5: active ? "nanpi.png" : "nanpi.png",
|
||||
// 6: active ? "zhaizi.png" : "zhaizi.png",
|
||||
// 7: active ? "xiaozhuang.png" : "xiaozhuang.png",
|
||||
// 8: active ? "warning.png" : "warning.png",
|
||||
22: active ? "video-active.png" : "video.png",
|
||||
44: active ? "weather-active.png" : "weather.png",
|
||||
53: active ? "broadcast-active.png" : "broadcast.png",
|
||||
|
@ -101,6 +101,18 @@ const customDevices = [
|
|||
];
|
||||
|
||||
onMounted(async () => {
|
||||
// 监听设备的显示隐藏
|
||||
window.addEventListener('toggle-map-device', (e) => {
|
||||
const { type, show } = e.detail;
|
||||
showType.value[type] = show;
|
||||
markerMap.value[type]?.forEach((marker) => {
|
||||
if (show) {
|
||||
map.addOverlay(marker);
|
||||
} else {
|
||||
map.removeOverlay(marker);
|
||||
}
|
||||
});
|
||||
});
|
||||
await nextTick();
|
||||
map = new BMap.Map("baiduMap");
|
||||
const point = new BMap.Point(116.827009, 37.890385);
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, onMounted } from "vue";
|
||||
import { ref, onMounted, computed } from "vue";
|
||||
import EventStatus from "./EventStatus.vue";
|
||||
import EventTask from "./EventTask.vue";
|
||||
import RealTimeImage from "./RealTimeImage.vue";
|
||||
import { weatherForecast, weatherHourly, todayStatusCount, todayHourly } from "@/api/modules/index";
|
||||
import { weatherForecast, weatherHourly, todayStatusCount, todayHourly, getDictData } from "@/api/modules/index";
|
||||
import { useTodayTime, } from "@/utils/packge";
|
||||
|
||||
const { todayTime, getTodayTime } = useTodayTime();
|
||||
// 模拟数据,实际项目中可能需要从API获取
|
||||
const pendingCount = ref<string>('');
|
||||
const processingCount = ref<string>('');
|
||||
|
||||
const serviceArea = ref<any[]>([]);
|
||||
const Hub = ref<any[]>([]);
|
||||
const Intercommunication = ref<any[]>([]);
|
||||
// 服务区数据
|
||||
const selectedServiceArea = ref("全部");
|
||||
const serviceAreas = ref(["全部", "南皮服务区", "东光服务区"]);
|
||||
const serviceAreas = ref([]);
|
||||
// 服务区选择变更处理
|
||||
const handleServiceAreaChange = (area: string) => {
|
||||
selectedServiceArea.value = area;
|
||||
|
@ -28,25 +30,49 @@ const areaTypes = ref([
|
|||
|
||||
// 切换区域类型选中状态
|
||||
const toggleAreaType = (id: string) => {
|
||||
const areaType = areaTypes.value.find((type) => type.id === id);
|
||||
if (areaType) {
|
||||
areaType.selected = !areaType.selected;
|
||||
}
|
||||
areaTypes.value.forEach((type) => {
|
||||
type.selected = type.id === id;
|
||||
});
|
||||
};
|
||||
onMounted(()=>{
|
||||
todayStatusCount({todayTime: todayTime.value}).then((res: any) => {
|
||||
if(res.code === 200){
|
||||
res.data.forEach((item: any) => {
|
||||
if(item.status == '0'){ //待处理
|
||||
pendingCount.value = item.count
|
||||
pendingCount.value = item.count || 0
|
||||
} else if(item.status == '2'){ //处置中
|
||||
processingCount.value = item.count
|
||||
processingCount.value = item.count || 0
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
getDictData("hb_service_area").then((res: any) => { //服务区
|
||||
if (res.code === 200) {
|
||||
serviceArea.value = res.data || [];
|
||||
}
|
||||
});
|
||||
getDictData("hb_hub").then((res: any) => { //枢纽
|
||||
if (res.code === 200) {
|
||||
Hub.value = res.data || [];
|
||||
}
|
||||
});
|
||||
getDictData("hb_interchange").then((res: any) => { //互通
|
||||
if (res.code === 200) {
|
||||
Intercommunication.value = res.data || [];
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
const currentAreaList = computed(() => {
|
||||
const selectedType = areaTypes.value.find((type) => type.selected);
|
||||
if (selectedType?.id === "service") {
|
||||
return serviceArea.value;
|
||||
} else if (selectedType?.id === "interchange") {
|
||||
return Intercommunication.value;
|
||||
} else if (selectedType?.id === "hub") {
|
||||
return Hub.value;
|
||||
}
|
||||
return [];
|
||||
});
|
||||
const isDropdownOpen = ref(false);
|
||||
</script>
|
||||
|
||||
|
@ -91,16 +117,16 @@ const isDropdownOpen = ref(false);
|
|||
</div>
|
||||
<div class="dropdown-menu" v-show="isDropdownOpen">
|
||||
<div
|
||||
v-for="area in serviceAreas"
|
||||
:key="area"
|
||||
v-for="(item, index) in currentAreaList"
|
||||
:key="index"
|
||||
class="dropdown-item"
|
||||
:class="{ active: selectedServiceArea === area }"
|
||||
:class="{ active: selectedServiceArea === item.dictLabel }"
|
||||
@click="
|
||||
handleServiceAreaChange(area);
|
||||
handleServiceAreaChange(item.dictLabel);
|
||||
isDropdownOpen = false;
|
||||
"
|
||||
>
|
||||
{{ area }}
|
||||
{{ item.dictLabel }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -118,6 +144,7 @@ const isDropdownOpen = ref(false);
|
|||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-right: 20px;
|
||||
// justify-content: space-between;
|
||||
// align-items: flex-start;
|
||||
.top {
|
||||
|
|
Loading…
Reference in New Issue