424 lines
12 KiB
Vue
424 lines
12 KiB
Vue
<template>
|
||
<div class="bottom-panel">
|
||
<div class="nav-menu">
|
||
<div
|
||
v-for="(item, index) in menuItems"
|
||
:key="index"
|
||
class="nav-item"
|
||
:class="{ active: activeIndex === index }"
|
||
@click="handleClick(item, index)"
|
||
>
|
||
<div class="nav-icon-box" :ref="(el) => setNavIconRef(el, index)">
|
||
<!-- <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" :getdateRange="getdateRange" @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>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, computed, nextTick, inject } 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'
|
||
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'
|
||
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 getdateRange = inject('getdateRange', ref([]))
|
||
const emit = defineEmits(['changeActiveIndex', 'clearMapMarkers', 'hazardItemClick', 'roadItemClick', 'showHazardPopupfn'])
|
||
|
||
const activeIndex = ref(-1)
|
||
|
||
const menuItems = [
|
||
{
|
||
label: '涉灾隐患点',
|
||
icon: 'icon-hazard',
|
||
iconClass: 'hazard',
|
||
icon: hazardIconIconIcon,
|
||
icon1: hazardIconIcon,
|
||
},
|
||
{
|
||
label: '路段',
|
||
icon: 'icon-road',
|
||
iconClass: 'road',
|
||
icon: roadIconIcon,
|
||
icon1: roadIconIcon1,
|
||
},
|
||
{
|
||
label: '驻地',
|
||
icon: 'icon-warning',
|
||
iconClass: 'warning',
|
||
icon: warningIconIcon,
|
||
icon1: warningIconIcon1,
|
||
},
|
||
{
|
||
label: '隧道',
|
||
icon: 'icon-tunnel',
|
||
iconClass: 'tunnel',
|
||
icon: tunnelIconIcon,
|
||
icon1: tunnelIconIcon1,
|
||
},
|
||
{
|
||
label: '边坡',
|
||
icon: 'icon-slope',
|
||
iconClass: 'slope',
|
||
icon: slopeIconIcon,
|
||
icon1: slopeIconIcon1,
|
||
},
|
||
{
|
||
label: '桥梁',
|
||
icon: 'icon-bridge',
|
||
iconClass: 'bridge',
|
||
icon: bridgeIconIcon,
|
||
icon1: bridgeIconIcon1,
|
||
},
|
||
{
|
||
label: '队伍',
|
||
icon: 'icon-team',
|
||
iconClass: 'team',
|
||
icon: teamIconIcon,
|
||
icon1: teamIconIcon1,
|
||
},
|
||
{
|
||
label: '危大工程',
|
||
icon: 'icon-hazard',
|
||
iconClass: 'hazard',
|
||
icon: engineeringIconIconIcon,
|
||
icon1: engineeringIconIcon,
|
||
},
|
||
]
|
||
|
||
// 涉灾隐患点弹窗相关
|
||
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)
|
||
// 点击非路段,隐藏路段统计
|
||
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('清除筛选条件')
|
||
// 重置活动索引
|
||
activeIndex.value = -1
|
||
// 关闭弹窗
|
||
showHazardPopup.value = false
|
||
showRoadPopup.value = false
|
||
// 触发清除地图标记事件
|
||
emit('clearMapMarkers')
|
||
emit('showHazardPopupfn', false)
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
// 视频屏幕自适应 - 基于视口宽度动态调整
|
||
// 基准宽度 1920px,使用 vw 单位实现自适应
|
||
@function vw($px) {
|
||
@return calc($px / 1920 * 100vw);
|
||
}
|
||
|
||
.bottom-panel {
|
||
position: relative;
|
||
width: 100%;
|
||
height: 100%;
|
||
box-sizing: border-box;
|
||
display: flex;
|
||
|
||
@media (max-width: 1366px) {
|
||
padding: vw(8);
|
||
}
|
||
|
||
@media (max-width: 1024px) {
|
||
padding: vw(6);
|
||
}
|
||
}
|
||
|
||
// 涉灾隐患点弹窗样式
|
||
.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;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.nav-menu {
|
||
width: vw(80);
|
||
min-width: vw(80);
|
||
height: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: end;
|
||
align-items: center;
|
||
gap: vw(5);
|
||
z-index: 2;
|
||
position: absolute;
|
||
bottom: 0;
|
||
left: 0;
|
||
|
||
.nav-item {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
|
||
&:hover,
|
||
&.active {
|
||
.nav-icon-box {
|
||
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);
|
||
min-width: vw(36);
|
||
min-height: vw(36);
|
||
margin-bottom: vw(5);
|
||
background: rgba(64, 169, 255, 0.1);
|
||
// border: 1px solid rgba(64, 169, 255, 0.3);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
transition: all 0.3s ease;
|
||
img {
|
||
width: vw(50);
|
||
height: vw(50);
|
||
min-width: vw(32);
|
||
min-height: vw(32);
|
||
}
|
||
|
||
i {
|
||
font-size: vw(24);
|
||
color: #40a9ff;
|
||
}
|
||
|
||
// 使用 emoji 作为图标占位
|
||
&.warning::before {
|
||
content: '📍';
|
||
font-size: vw(24);
|
||
}
|
||
|
||
&.tunnel::before {
|
||
content: '🚇';
|
||
font-size: vw(24);
|
||
}
|
||
|
||
&.slope::before {
|
||
content: '⛰️';
|
||
font-size: vw(24);
|
||
}
|
||
|
||
&.bridge::before {
|
||
content: '🌉';
|
||
font-size: vw(24);
|
||
}
|
||
|
||
&.road::before {
|
||
content: '🛣️';
|
||
font-size: vw(24);
|
||
}
|
||
}
|
||
|
||
.nav-label {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: vw(14);
|
||
color: #fff;
|
||
transition: all 0.3s ease;
|
||
}
|
||
}
|
||
}
|
||
</style>
|