439 lines
12 KiB
Vue
Raw Normal View History

2026-03-27 17:47:09 +08:00
<template>
<div class="bottom-panel">
2026-03-27 17:47:09 +08:00
<div class="nav-menu">
<div
v-for="(item, index) in menuItems"
:key="index"
class="nav-item"
:class="{ active: activeIndex === index }"
@click="handleClick(item, index)"
2026-03-27 17:47:09 +08:00
>
<div class="nav-icon-box" :ref="el => setNavIconRef(el, index)">
2026-03-27 17:47:09 +08:00
<!-- <i :class="item.icon"></i> -->
<img :src="activeIndex === index ? item.icon1 : item.icon" alt="" />
</div>
<div class="nav-label">{{ item.label }}</div>
</div>
</div>
<!-- 气象预警监测表格组件 -->
<WeatherWarningTable ref="weatherWarningTableRef" @clearFilters="handleClearFilters" />
<!-- 涉灾隐患点图片弹窗 -->
<div v-if="showHazardPopup" class="hazard-popup" :style="popupStyle">
<div class="hazard-popup-content">
<div
v-for="(item, index) in hazardItems"
:key="index"
class="hazard-item"
@click="handleHazardItemClick(item)"
>
<img :src="item.icon" :alt="item.label" />
<span>{{ item.label }}</span>
</div>
</div>
</div>
<!-- 路段图片弹窗 -->
<div v-if="showRoadPopup" class="hazard-popup road-popup" :style="roadPopupStyle">
<div class="hazard-popup-content">
<div
v-for="(item, index) in roadItems"
:key="index"
class="hazard-item"
@click="handleRoadItemClick(item)"
>
<img :src="item.icon" :alt="item.label" />
<span>{{ item.label }}</span>
</div>
</div>
</div>
2026-03-27 17:47:09 +08:00
</div>
</template>
<script setup>
import { ref, computed, nextTick } from 'vue';
import WeatherWarningTable from './component/WeatherWarningTable.vue';
import warningIconIcon from '../../assets/RiskWarning_img/风险预警icon@2x.png';
import tunnelIconIcon from '../../assets/RiskWarning_img/隧道icon@2x.png';
import slopeIconIcon from '../../assets/RiskWarning_img/边坡icon@2x.png';
import bridgeIconIcon from '../../assets/RiskWarning_img/桥梁icon@2x.png';
import roadIconIcon from '../../assets/RiskWarning_img/线路路段icon@2x.png';
import teamIconIcon from '../../assets/RiskWarning_img/队伍icon@2x.png';
import hazardIconIconIcon from '../../assets/RiskWarning_img/隐患点icon@2x.png';
2026-04-28 09:20:54 +08:00
import engineeringIconIconIcon from '../../assets/RiskWarning_img/危大工程icon@2x.png';
import warningIconIcon1 from '../../assets/RiskWarning_img/风险预警icon1@2x.png';
import tunnelIconIcon1 from '../../assets/RiskWarning_img/隧道icon1@2x.png';
import slopeIconIcon1 from '../../assets/RiskWarning_img/边坡icon1@2x.png';
import bridgeIconIcon1 from '../../assets/RiskWarning_img/桥梁icon1@2x.png';
import roadIconIcon1 from '../../assets/RiskWarning_img/线路路段icon1@2x.png';
import teamIconIcon1 from '../../assets/RiskWarning_img/队伍icon1@2x.png';
import hazardIconIcon from '../../assets/RiskWarning_img/隐患点icon1@2x.png';
2026-04-28 09:20:54 +08:00
import engineeringIconIcon from '../../assets/RiskWarning_img/危大工程icon1@2x.png';
import hazardIconIcon1 from '../../assets/MaMap_img/一般路内隐患点@2x.png';
import hazardIconIcon2 from '../../assets/MaMap_img/一般路外隐患点@2x.png';
import hazardIconIcon3 from '../../assets/MaMap_img/较大路内隐患点@2x.png';
import hazardIconIcon4 from '../../assets/MaMap_img/较大路外隐患点@2x.png';
import hazardIconIcon5 from '../../assets/MaMap_img/重大路内隐患点@2x.png';
import hazardIconIcon6 from '../../assets/MaMap_img/重大路外隐患点@2x.png';
import tunnelLineIcon3 from '../../assets/MaMap_img/高风险路段@2x.png';
import tunnelLineIcon2 from '../../assets/MaMap_img/较高风险路段@2x.png';
import tunnelLineIcon1 from '../../assets/MaMap_img/中风险路段@2x.png';
import tunnelLineIcon from '../../assets/MaMap_img/线路icon定位@2x.png';
const emit = defineEmits([
'changeActiveIndex',
'clearMapMarkers',
'hazardItemClick',
'roadItemClick',
'showHazardPopupfn',
]);
2026-03-27 17:47:09 +08:00
const activeIndex = ref(-1);
2026-03-27 17:47:09 +08:00
const menuItems = [
{
label: '涉灾隐患点',
icon: 'icon-hazard',
iconClass: 'hazard',
icon: hazardIconIconIcon,
icon1: hazardIconIcon,
},
{
label: '路段',
icon: 'icon-road',
iconClass: 'road',
icon: roadIconIcon,
icon1: roadIconIcon1,
},
2026-03-27 17:47:09 +08:00
{
label: '项目',
icon: 'icon-warning',
iconClass: 'warning',
2026-03-27 17:47:09 +08:00
icon: warningIconIcon,
icon1: warningIconIcon1,
},
{
label: '隧道',
icon: 'icon-tunnel',
iconClass: 'tunnel',
2026-03-27 17:47:09 +08:00
icon: tunnelIconIcon,
icon1: tunnelIconIcon1,
},
{
label: '边坡',
icon: 'icon-slope',
iconClass: 'slope',
2026-03-27 17:47:09 +08:00
icon: slopeIconIcon,
icon1: slopeIconIcon1,
},
{
label: '桥梁',
icon: 'icon-bridge',
iconClass: 'bridge',
2026-03-27 17:47:09 +08:00
icon: bridgeIconIcon,
icon1: bridgeIconIcon1,
},
2026-04-02 16:35:45 +08:00
{
label: '队伍',
icon: 'icon-team',
iconClass: 'team',
2026-04-02 16:35:45 +08:00
icon: teamIconIcon,
icon1: teamIconIcon1,
},
2026-04-28 09:20:54 +08:00
{
label: '危大工程',
icon: 'icon-hazard',
iconClass: 'hazard',
icon: engineeringIconIconIcon,
icon1: engineeringIconIcon,
},
2026-03-27 17:47:09 +08:00
];
// 涉灾隐患点弹窗相关
const showHazardPopup = ref(false);
const popupStyle = ref({});
const navIconRefs = ref([]);
// 隐患点数据
const hazardItems = ref([
{ icon: hazardIconIcon5, label: '重大路内隐患点', isWithinRedLine: '是' },
{ icon: hazardIconIcon6, label: '重大路外隐患点', isWithinRedLine: '否' },
{ icon: hazardIconIcon3, label: '较大路内隐患点', isWithinRedLine: '是' },
{ icon: hazardIconIcon4, label: '较大路外隐患点', isWithinRedLine: '否' },
{ icon: hazardIconIcon1, label: '一般路内隐患点', isWithinRedLine: '是' },
{ icon: hazardIconIcon2, label: '一般路外隐患点', isWithinRedLine: '否' },
]);
// 路段弹窗相关
const showRoadPopup = ref(false);
const roadPopupStyle = ref({});
// 路段数据
const roadItems = ref([
{ icon: tunnelLineIcon3, label: '高风险路段' },
{ icon: tunnelLineIcon2, label: '较高风险路段' },
{ icon: tunnelLineIcon1, label: '中风险路段' },
{ icon: tunnelLineIcon, label: '低风险路段' },
]);
// 设置nav-icon-box的ref
const setNavIconRef = (el, index) => {
if (el) {
navIconRefs.value[index] = el;
}
};
const weatherWarningTableRef = ref(null);
// 点击切换导航项
const handleClick = (item, index) => {
// 如果点击的是涉灾隐患点
if (item.label === '涉灾隐患点') {
// 切换弹窗显示状态
showHazardPopup.value = !showHazardPopup.value;
if (showHazardPopup.value) {
showRoadPopup.value = false;
}
if (showHazardPopup.value) {
// 计算弹窗位置
const navIconBox = navIconRefs.value[index];
if (navIconBox) {
const rect = navIconBox.getBoundingClientRect();
popupStyle.value = {
position: 'fixed',
left: rect.right + 10 + 'px',
top: rect.top + 'px',
zIndex: 2,
};
}
}
} else if (item.label === '路段') {
// 如果点击的是路段
// 切换弹窗显示状态
showRoadPopup.value = !showRoadPopup.value;
if (showRoadPopup.value) {
showHazardPopup.value = false;
}
if (showRoadPopup.value) {
// 计算弹窗位置
const navIconBox = navIconRefs.value[index];
if (navIconBox) {
const rect = navIconBox.getBoundingClientRect();
roadPopupStyle.value = {
position: 'fixed',
left: rect.right + 10 + 'px',
top: rect.top + 'px',
zIndex: 2,
};
}
}
emit('showHazardPopupfn', false);
} else {
showHazardPopup.value = false;
showRoadPopup.value = false;
emit('showHazardPopupfn', false);
2026-04-17 17:23:51 +08:00
// 点击非路段,隐藏路段统计
emit('hideRoadStats');
}
activeIndex.value = index;
if (item.label !== '路段') {
emit('changeActiveIndex', {
...item,
});
}
};
// 点击隐患点项
const handleHazardItemClick = item => {
console.log('点击隐患点:', item);
emit('hazardItemClick', item);
// 可以在这里添加其他逻辑,比如关闭弹窗
// showHazardPopup.value = false;
emit('showHazardPopupfn', true);
};
const roadItem = ref({});
// 点击路段项
const handleRoadItemClick = item => {
console.log('点击路段:', item);
roadItem.value = item;
emit('roadItemClick', item);
// 可以在这里添加其他逻辑,比如关闭弹窗
// showRoadPopup.value = false;
};
// 处理清除筛选事件
const handleClearFilters = () => {
console.log('清除筛选条件');
// 重置活动索引
2026-04-09 14:53:44 +08:00
activeIndex.value = -1;
// 关闭弹窗
showHazardPopup.value = false;
showRoadPopup.value = false;
// 触发清除地图标记事件
emit('clearMapMarkers');
emit('showHazardPopupfn', false);
};
2026-03-27 17:47:09 +08:00
</script>
<style lang="scss" scoped>
// 视频屏幕自适应 - 基于视口宽度动态调整
// 基准宽度 1920px使用 vw 单位实现自适应
@function vw($px) {
@return calc($px / 1920 * 100vw);
}
.bottom-panel {
2026-03-27 17:47:09 +08:00
position: relative;
width: 100%;
height: 100%;
box-sizing: border-box;
display: flex;
@media (max-width: 1366px) {
2026-04-02 16:35:45 +08:00
padding: vw(8);
}
@media (max-width: 1024px) {
2026-04-02 16:35:45 +08:00
padding: vw(6);
}
2026-03-27 17:47:09 +08:00
}
// 涉灾隐患点弹窗样式
.hazard-popup {
background: rgba(20, 46, 73, 0.95);
border: 1px solid rgba(64, 169, 255, 0.4);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
.hazard-popup-content {
display: flex;
flex-direction: column;
gap: vw(8);
.hazard-item {
display: flex;
align-items: center;
gap: vw(8);
padding: vw(5) vw(10);
// border-radius: 4px;
transition: background 0.3s;
cursor: pointer;
&:hover {
background: rgba(64, 169, 255, 0.2);
}
img {
width: vw(40);
height: vw(40);
object-fit: contain;
}
span {
color: rgba(255, 255, 255, 0.9);
font-size: vw(16);
white-space: nowrap;
}
}
}
}
2026-03-27 17:47:09 +08:00
.nav-menu {
width: vw(80);
min-width: vw(80);
2026-04-02 16:35:45 +08:00
height: 100%;
2026-03-27 17:47:09 +08:00
display: flex;
flex-direction: column;
justify-content: end;
align-items: center;
gap: vw(5);
2026-04-02 16:35:45 +08:00
z-index: 2;
position: absolute;
bottom: 0;
left: 0;
2026-03-27 17:47:09 +08:00
.nav-item {
display: flex;
flex-direction: column;
align-items: center;
cursor: pointer;
transition: all 0.3s ease;
&:hover,
&.active {
.nav-icon-box {
2026-03-27 17:47:09 +08:00
background: rgba(64, 169, 255, 0.3);
border-color: rgba(64, 169, 255, 0.6);
}
.nav-label {
color: #40a9ff;
}
}
.nav-icon-box {
width: vw(50);
height: vw(50);
2026-04-02 16:35:45 +08:00
min-width: vw(36);
min-height: vw(36);
margin-bottom: vw(5);
2026-03-27 17:47:09 +08:00
background: rgba(64, 169, 255, 0.1);
// border: 1px solid rgba(64, 169, 255, 0.3);
2026-03-27 17:47:09 +08:00
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
img {
width: vw(50);
height: vw(50);
2026-04-02 16:35:45 +08:00
min-width: vw(32);
min-height: vw(32);
2026-03-27 17:47:09 +08:00
}
i {
font-size: vw(24);
2026-03-27 17:47:09 +08:00
color: #40a9ff;
}
// 使用 emoji 作为图标占位
&.warning::before {
content: '📍';
font-size: vw(24);
2026-03-27 17:47:09 +08:00
}
&.tunnel::before {
content: '🚇';
font-size: vw(24);
2026-03-27 17:47:09 +08:00
}
&.slope::before {
content: '⛰️';
font-size: vw(24);
2026-03-27 17:47:09 +08:00
}
&.bridge::before {
content: '🌉';
font-size: vw(24);
2026-03-27 17:47:09 +08:00
}
&.road::before {
content: '🛣️';
font-size: vw(24);
2026-03-27 17:47:09 +08:00
}
}
.nav-label {
display: flex;
align-items: center;
justify-content: center;
2026-04-03 18:08:42 +08:00
font-size: vw(14);
2026-03-27 17:47:09 +08:00
color: #fff;
transition: all 0.3s ease;
}
}
}
</style>