|
|
@@ -260,6 +260,66 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
+ <!-- 右侧面板 - 圩区详情 -->
|
|
|
+ <div class="right-panel" v-else-if="selectedPolderDetail === 'konggang' && !showHydrologyDetail">
|
|
|
+ <div class="right-panel-3d">
|
|
|
+ <!-- 降雨预报和降雨量 -->
|
|
|
+ <m-card title="降雨预报" class="water-station-card water-station-card-top" :width="398" :height="320">
|
|
|
+ <div class="rainfall-forecast-panel">
|
|
|
+ <!-- 降雨预报卡片 -->
|
|
|
+ <div class="forecast-cards">
|
|
|
+ <div class="forecast-card" v-for="(forecast, index) in rainfallForecast" :key="index">
|
|
|
+ <div class="forecast-date">{{ forecast.date }}</div>
|
|
|
+ <div class="forecast-icon" :class="forecast.icon"></div>
|
|
|
+ <div class="forecast-desc">{{ forecast.desc }}</div>
|
|
|
+ <div class="forecast-temp">{{ forecast.temp }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 降雨量柱状图 -->
|
|
|
+ <div class="rainfall-chart-container">
|
|
|
+ <h4 class="chart-title">降雨量</h4>
|
|
|
+ <VChart ref="rainfallChart" :option="polderRainfallChartOption" :autoresize="true" style="width: 100%; height: 120px;" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </m-card>
|
|
|
+
|
|
|
+ <!-- 圩区AI内涝识别 -->
|
|
|
+ <m-card title="圩区AI内涝识别" class="water-station-card water-station-card-bottom" :width="398" :height="480">
|
|
|
+ <div class="waterlogging-detection-panel">
|
|
|
+ <!-- 内涝统计 -->
|
|
|
+ <div class="waterlogging-stats">
|
|
|
+ <div class="stat-item">
|
|
|
+ <div class="stat-label">积水点数量</div>
|
|
|
+ <div class="stat-value">{{ waterloggingStats.count }}/{{ waterloggingStats.total }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="stat-item">
|
|
|
+ <div class="stat-label">是否积水</div>
|
|
|
+ <div class="stat-value" :class="{ 'status-active': !waterloggingStats.isWaterlogging, 'status-inactive': waterloggingStats.isWaterlogging }">{{ waterloggingStats.isWaterlogging ? '是' : '否' }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 监控点查看按钮 -->
|
|
|
+ <div class="monitoring-button-container">
|
|
|
+ <button class="monitoring-button" @click="showMonitoringPoints = !showMonitoringPoints">
|
|
|
+ {{ showMonitoringPoints ? '收起监控点' : '查看监控点' }}
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 监控点图片 -->
|
|
|
+ <div class="monitoring-points" v-if="showMonitoringPoints">
|
|
|
+ <div class="monitoring-point" v-for="(point, index) in monitoringPoints" :key="index">
|
|
|
+ <div class="point-name">{{ point.name }}</div>
|
|
|
+ <div class="point-image">
|
|
|
+ <img :src="point.image" alt="监控点" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </m-card>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
<!-- 孔巷联圩详情 -->
|
|
|
<template v-if="selectedPolderDetail === 'konggang' && !showHydrologyDetail">
|
|
|
<!-- 侧边开关控制 -->
|
|
|
@@ -319,6 +379,11 @@ import TopStats from "./TopStats.vue"
|
|
|
import mSvglineAnimation from "@/components/mSvglineAnimation/index.vue"
|
|
|
import gsap from "gsap"
|
|
|
|
|
|
+// 引入监控点图片
|
|
|
+import cityFlood1 from "@/assets/images/城市积水1.png"
|
|
|
+import cityFlood2 from "@/assets/images/城市积水2.png"
|
|
|
+import cityFlood3 from "@/assets/images/城市积水3.png"
|
|
|
+
|
|
|
defineProps({
|
|
|
selectedPolderDetail: {
|
|
|
type: String,
|
|
|
@@ -569,7 +634,7 @@ const currentWaterLevelChartOption = computed(() => {
|
|
|
left: '4%',
|
|
|
top: '12%',
|
|
|
right: '10%',
|
|
|
- bottom: '13%',
|
|
|
+ bottom: '18%',
|
|
|
containLabel: true
|
|
|
},
|
|
|
legend: {
|
|
|
@@ -953,6 +1018,105 @@ const rainfallChartOption = ref({
|
|
|
]
|
|
|
})
|
|
|
|
|
|
+// 降雨预报数据
|
|
|
+const rainfallForecast = ref([
|
|
|
+ { date: '今天', icon: 'rainy', desc: '小雨', temp: '4°C' },
|
|
|
+ { date: '明天', icon: 'cloudy', desc: '多云', temp: '6°C' },
|
|
|
+ { date: '后天', icon: 'sunny', desc: '晴', temp: '8°C' },
|
|
|
+ { date: '周四', icon: 'rainy', desc: '中雨', temp: '5°C' }
|
|
|
+])
|
|
|
+
|
|
|
+// 降雨量图表配置
|
|
|
+const polderRainfallChartOption = ref({
|
|
|
+ grid: {
|
|
|
+ left: '5%',
|
|
|
+ top: '20%',
|
|
|
+ right: '5%',
|
|
|
+ bottom: '15%',
|
|
|
+ containLabel: true
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ type: 'category',
|
|
|
+ data: ['00:00', '03:00', '06:00', '09:00', '12:00', '15:00', '18:00', '21:00'],
|
|
|
+ axisLine: {
|
|
|
+ lineStyle: {
|
|
|
+ color: 'rgba(48, 220, 255, 0.6)'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ axisLabel: {
|
|
|
+ color: 'rgba(255, 255, 255, 0.8)',
|
|
|
+ fontSize: 9
|
|
|
+ }
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ type: 'value',
|
|
|
+ min: 0,
|
|
|
+ max: 5,
|
|
|
+ axisLine: {
|
|
|
+ lineStyle: {
|
|
|
+ color: 'rgba(48, 220, 255, 0.6)'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ axisLabel: {
|
|
|
+ color: 'rgba(255, 255, 255, 0.8)',
|
|
|
+ fontSize: 9,
|
|
|
+ formatter: '{value} mm'
|
|
|
+ },
|
|
|
+ splitLine: {
|
|
|
+ lineStyle: {
|
|
|
+ color: 'rgba(48, 220, 255, 0.2)'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'axis',
|
|
|
+ backgroundColor: 'rgba(0, 20, 40, 0.9)',
|
|
|
+ borderColor: 'rgba(48, 220, 255, 0.5)',
|
|
|
+ textStyle: {
|
|
|
+ color: '#fff'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ name: '降雨量',
|
|
|
+ type: 'bar',
|
|
|
+ barWidth: '20%',
|
|
|
+ data: [0.2, 0.5, 1.2, 0.8, 0.3, 0.1, 0.2, 0.4],
|
|
|
+ itemStyle: {
|
|
|
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
|
+ {
|
|
|
+ offset: 0,
|
|
|
+ color: 'rgba(48, 220, 255, 0.8)'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ offset: 1,
|
|
|
+ color: 'rgba(48, 220, 255, 0.3)'
|
|
|
+ }
|
|
|
+ ]),
|
|
|
+ shadowColor: 'rgba(48, 220, 255, 0.6)',
|
|
|
+ shadowBlur: 10
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+})
|
|
|
+
|
|
|
+// 内涝识别数据
|
|
|
+const waterloggingStats = ref({
|
|
|
+ count: 0,
|
|
|
+ total: 15,
|
|
|
+ isWaterlogging: false
|
|
|
+})
|
|
|
+
|
|
|
+// 监控点数据
|
|
|
+const monitoringPoints = ref([
|
|
|
+ { name: '监控点1', image: cityFlood1 },
|
|
|
+ { name: '监控点2', image: cityFlood2 },
|
|
|
+ { name: '监控点3', image: cityFlood3 }
|
|
|
+])
|
|
|
+
|
|
|
+// 显示监控点状态
|
|
|
+const showMonitoringPoints = ref(true)
|
|
|
+
|
|
|
// 组件挂载时执行动画
|
|
|
onMounted(() => {
|
|
|
nextTick(() => {
|
|
|
@@ -1764,8 +1928,8 @@ onMounted(() => {
|
|
|
|
|
|
.polder-layer-controls {
|
|
|
position: absolute;
|
|
|
- right: 20px;
|
|
|
- top: 50%;
|
|
|
+ right: 420px;
|
|
|
+ top: 65%;
|
|
|
transform: translateY(-50%);
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
@@ -1911,4 +2075,209 @@ onMounted(() => {
|
|
|
height: 100% !important;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+.rainfall-forecast-panel {
|
|
|
+ height: 100%;
|
|
|
+ padding: 8px;
|
|
|
+ box-sizing: border-box;
|
|
|
+ background: rgba(0, 30, 60, 0.5);
|
|
|
+ border-radius: 6px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.forecast-cards {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(4, 1fr);
|
|
|
+ gap: 6px;
|
|
|
+}
|
|
|
+
|
|
|
+.forecast-card {
|
|
|
+ background: rgba(0, 100, 150, 0.3);
|
|
|
+ border: 1px solid rgba(48, 220, 255, 0.3);
|
|
|
+ border-radius: 4px;
|
|
|
+ padding: 6px;
|
|
|
+ text-align: center;
|
|
|
+
|
|
|
+ .forecast-date {
|
|
|
+ font-size: 10px;
|
|
|
+ color: rgba(255, 255, 255, 0.9);
|
|
|
+ margin-bottom: 4px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .forecast-icon {
|
|
|
+ width: 32px;
|
|
|
+ height: 32px;
|
|
|
+ margin: 0 auto 4px;
|
|
|
+ background-size: contain;
|
|
|
+ background-repeat: no-repeat;
|
|
|
+ background-position: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .forecast-icon.rainy {
|
|
|
+ background-image: url('@/assets/images/rain.svg');
|
|
|
+ }
|
|
|
+
|
|
|
+ .forecast-icon.cloudy {
|
|
|
+ background-image: url('@/assets/images/storm.svg');
|
|
|
+ }
|
|
|
+
|
|
|
+ .forecast-icon.sunny {
|
|
|
+ background-image: url('@/assets/images/heat.svg');
|
|
|
+ }
|
|
|
+
|
|
|
+ .forecast-desc {
|
|
|
+ font-size: 10px;
|
|
|
+ color: #30dcff;
|
|
|
+ margin-bottom: 2px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .forecast-temp {
|
|
|
+ font-size: 9px;
|
|
|
+ color: rgba(255, 255, 255, 0.8);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.rainfall-chart-container {
|
|
|
+ flex: 1;
|
|
|
+ background: rgba(0, 100, 150, 0.2);
|
|
|
+ border: 1px solid rgba(48, 220, 255, 0.3);
|
|
|
+ border-radius: 4px;
|
|
|
+ padding: 6px;
|
|
|
+ min-height: 100px;
|
|
|
+
|
|
|
+ .chart-title {
|
|
|
+ font-size: 10px;
|
|
|
+ color: #30dcff;
|
|
|
+ margin-bottom: 4px;
|
|
|
+ text-align: center;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.echarts-container) {
|
|
|
+ width: 100% !important;
|
|
|
+ height: 100% !important;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.waterlogging-detection-panel {
|
|
|
+ height: 100%;
|
|
|
+ padding: 10px;
|
|
|
+ box-sizing: border-box;
|
|
|
+ background: rgba(0, 30, 60, 0.5);
|
|
|
+ border-radius: 6px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.waterlogging-stats {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(2, 1fr);
|
|
|
+ gap: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.waterlogging-stats .stat-item {
|
|
|
+ background: rgba(0, 100, 150, 0.3);
|
|
|
+ border: 1px solid rgba(48, 220, 255, 0.3);
|
|
|
+ border-radius: 4px;
|
|
|
+ padding: 10px;
|
|
|
+ text-align: center;
|
|
|
+
|
|
|
+ .stat-label {
|
|
|
+ font-size: 12px;
|
|
|
+ color: rgba(255, 255, 255, 0.9);
|
|
|
+ margin-bottom: 4px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .stat-value {
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #30dcff;
|
|
|
+ font-family: "D-DIN";
|
|
|
+
|
|
|
+ &.status-active {
|
|
|
+ color: #00ff88;
|
|
|
+ text-shadow: 0 0 10px rgba(0, 255, 136, 0.5);
|
|
|
+ }
|
|
|
+
|
|
|
+ &.status-inactive {
|
|
|
+ color: #ff6b6b;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.monitoring-button-container {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ margin: 5px 0;
|
|
|
+}
|
|
|
+
|
|
|
+.monitoring-button {
|
|
|
+ background: linear-gradient(135deg, rgba(48, 220, 255, 0.3) 0%, rgba(0, 191, 255, 0.2) 100%);
|
|
|
+ border: 1px solid rgba(48, 220, 255, 0.4);
|
|
|
+ border-radius: 4px;
|
|
|
+ padding: 6px 12px;
|
|
|
+ color: #30dcff;
|
|
|
+ font-size: 12px;
|
|
|
+ font-weight: bold;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background: linear-gradient(135deg, rgba(48, 220, 255, 0.4) 0%, rgba(0, 191, 255, 0.3) 100%);
|
|
|
+ border-color: rgba(48, 220, 255, 0.6);
|
|
|
+ box-shadow: 0 0 8px rgba(48, 220, 255, 0.3);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.monitoring-points {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 8px;
|
|
|
+ overflow-y: auto;
|
|
|
+
|
|
|
+ &::-webkit-scrollbar {
|
|
|
+ width: 4px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &::-webkit-scrollbar-track {
|
|
|
+ background: rgba(0, 0, 0, 0.3);
|
|
|
+ }
|
|
|
+
|
|
|
+ &::-webkit-scrollbar-thumb {
|
|
|
+ background: rgba(48, 220, 255, 0.4);
|
|
|
+ border-radius: 2px;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.monitoring-point {
|
|
|
+ background: rgba(0, 100, 150, 0.3);
|
|
|
+ border: 1px solid rgba(48, 220, 255, 0.3);
|
|
|
+ border-radius: 4px;
|
|
|
+ padding: 8px;
|
|
|
+
|
|
|
+ .point-name {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #30dcff;
|
|
|
+ margin-bottom: 4px;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+
|
|
|
+ .point-image {
|
|
|
+ width: 100%;
|
|
|
+ height: 120px;
|
|
|
+ border-radius: 4px;
|
|
|
+ overflow: hidden;
|
|
|
+ border: 1px solid rgba(48, 220, 255, 0.3);
|
|
|
+
|
|
|
+ img {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ object-fit: cover;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
</style>
|