|
|
@@ -0,0 +1,1140 @@
|
|
|
+<template>
|
|
|
+ <div class="polder-detail-content">
|
|
|
+ <!-- 左侧面板 -->
|
|
|
+ <div class="left-panel">
|
|
|
+ <div class="left-panel-3d">
|
|
|
+ <!-- 圩区水位分析 -->
|
|
|
+ <m-card :title="selectedPolderDetail === 'konggang' ? '孔巷联圩水位分析' : '圩区水位分析'" class="water-station-card water-station-card-top" :width="398" :height="320">
|
|
|
+ <div class="water-level-analysis-panel">
|
|
|
+ <!-- 切换按钮 -->
|
|
|
+ <div class="water-level-tabs" v-if="selectedPolderDetail === 'konggang'">
|
|
|
+ <div class="tab-item" :class="{ active: currentWaterLevelTab === 'inner' }" @click="currentWaterLevelTab = 'inner'">
|
|
|
+ <span>圩内</span>
|
|
|
+ </div>
|
|
|
+ <div class="tab-item" :class="{ active: currentWaterLevelTab === 'outer' }" @click="currentWaterLevelTab = 'outer'">
|
|
|
+ <span>圩外</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 水位数据 -->
|
|
|
+ <div class="water-level-data">
|
|
|
+ <div class="data-item">
|
|
|
+ <div class="data-label">水位(m)</div>
|
|
|
+ <div class="data-value">{{ currentWaterLevelData.level }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="data-item">
|
|
|
+ <div class="data-label">比昨日(m)</div>
|
|
|
+ <div class="data-value" :class="{ negative: currentWaterLevelData.change < 0 }">{{ currentWaterLevelData.change }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="data-item">
|
|
|
+ <div class="data-label">历史最高(m)</div>
|
|
|
+ <div class="data-value">{{ currentWaterLevelData.historyMax }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="data-item">
|
|
|
+ <div class="data-label">生态水位(m)</div>
|
|
|
+ <div class="data-value">{{ currentWaterLevelData.ecological }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="data-item">
|
|
|
+ <div class="data-label">比警戒(m)</div>
|
|
|
+ <div class="data-value" :class="{ negative: currentWaterLevelData.alertDiff < 0 }">{{ currentWaterLevelData.alertDiff }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 水位趋势图 -->
|
|
|
+ <div class="water-level-chart">
|
|
|
+ <VChart ref="waterLevelChart" :option="currentWaterLevelChartOption" :autoresize="true" style="width: 100%; height: 100%;" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </m-card>
|
|
|
+
|
|
|
+ <!-- 圩区工情 -->
|
|
|
+ <m-card title="圩区工情" class="water-station-card water-station-card-bottom" :width="398" :height="480">
|
|
|
+ <div class="polder-work-status-panel">
|
|
|
+ <!-- 泵站启闭情况卡片 -->
|
|
|
+ <div class="pump-status-cards">
|
|
|
+ <div class="pump-status-card" v-for="(pump, index) in pumpStatus" :key="index">
|
|
|
+ <div class="pump-name">{{ pump.name }}</div>
|
|
|
+ <div class="pump-status" :class="{ 'status-active': pump.status === '运行中', 'status-inactive': pump.status === '停止' }">
|
|
|
+ {{ pump.status }}
|
|
|
+ </div>
|
|
|
+ <div class="pump-flow">{{ pump.flow }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 开泵流量折线图 -->
|
|
|
+ <div class="flow-chart-container">
|
|
|
+ <h4 class="chart-title">开泵流量</h4>
|
|
|
+ <VChart ref="flowChart" :option="pumpFlowChartOption" :autoresize="true" style="width: 100%; height: 140px;" />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 日排水量柱状图 -->
|
|
|
+ <div class="discharge-chart-container">
|
|
|
+ <h4 class="chart-title">日排水量</h4>
|
|
|
+ <VChart ref="dischargeChart" :option="dailyDischargeChartOption" :autoresize="true" style="width: 100%; height: 140px;" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </m-card>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 右侧面板 - 圩区详情 -->
|
|
|
+ <div class="right-panel">
|
|
|
+ <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'">
|
|
|
+ <!-- 侧边开关控制 -->
|
|
|
+ <div class="polder-layer-controls">
|
|
|
+ <div class="toggle-item">
|
|
|
+ <span class="toggle-text">泵站</span>
|
|
|
+ <div class="toggle-switch" :class="{ active: showGate }" @click="$emit('update:showGate', !showGate)">
|
|
|
+ <div class="toggle-knob"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="toggle-item">
|
|
|
+ <span class="toggle-text">水文站</span>
|
|
|
+ <div class="toggle-switch" :class="{ active: showHydrology }" @click="$emit('update:showHydrology', !showHydrology)">
|
|
|
+ <div class="toggle-knob"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { ref, computed } from "vue"
|
|
|
+import mCard from "@/components/mCard/index.vue"
|
|
|
+import VChart from "vue-echarts"
|
|
|
+import * as echarts from "echarts"
|
|
|
+
|
|
|
+// 引入监控点图片
|
|
|
+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,
|
|
|
+ default: null
|
|
|
+ },
|
|
|
+ showGate: {
|
|
|
+ type: Boolean,
|
|
|
+ default: true
|
|
|
+ },
|
|
|
+ showHydrology: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ }
|
|
|
+})
|
|
|
+defineEmits(['update:showGate', 'update:showHydrology'])
|
|
|
+
|
|
|
+// 泵站状态数据
|
|
|
+const pumpStatus = ref([
|
|
|
+ { name: '泵站1', status: '运行中', flow: '8.5 m³/s' },
|
|
|
+ { name: '泵站2', status: '停止', flow: '0 m³/s' }
|
|
|
+])
|
|
|
+
|
|
|
+// 开泵流量图表配置
|
|
|
+const pumpFlowChartOption = ref({
|
|
|
+ grid: {
|
|
|
+ left: '2%',
|
|
|
+ top: '15%',
|
|
|
+ right: '5%',
|
|
|
+ bottom: '15%',
|
|
|
+ containLabel: true
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ type: 'category',
|
|
|
+ data: ['08:00', '10:00', '12:00', '14:00', '16:00', '18:00'],
|
|
|
+ axisLine: {
|
|
|
+ lineStyle: {
|
|
|
+ color: 'rgba(48, 220, 255, 0.6)'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ axisLabel: {
|
|
|
+ color: 'rgba(255, 255, 255, 0.8)',
|
|
|
+ fontSize: 9
|
|
|
+ },
|
|
|
+ boundaryGap: true
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ type: 'value',
|
|
|
+ axisLine: {
|
|
|
+ lineStyle: {
|
|
|
+ color: 'rgba(48, 220, 255, 0.6)'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ axisLabel: {
|
|
|
+ color: 'rgba(255, 255, 255, 0.8)',
|
|
|
+ fontSize: 9,
|
|
|
+ formatter: '{value} m³/s'
|
|
|
+ },
|
|
|
+ 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: 'line',
|
|
|
+ data: [5.2, 7.8, 8.5, 8.2, 7.9, 8.5],
|
|
|
+ smooth: true,
|
|
|
+ symbol: 'circle',
|
|
|
+ symbolSize: 6,
|
|
|
+ lineStyle: {
|
|
|
+ color: '#30dcff',
|
|
|
+ width: 2,
|
|
|
+ shadowColor: 'rgba(48, 220, 255, 0.6)',
|
|
|
+ shadowBlur: 10
|
|
|
+ },
|
|
|
+ itemStyle: {
|
|
|
+ color: '#30dcff',
|
|
|
+ borderColor: '#fff',
|
|
|
+ borderWidth: 2
|
|
|
+ },
|
|
|
+ areaStyle: {
|
|
|
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
|
+ {
|
|
|
+ offset: 0,
|
|
|
+ color: 'rgba(48, 220, 255, 0.3)'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ offset: 1,
|
|
|
+ color: 'rgba(48, 220, 255, 0.1)'
|
|
|
+ }
|
|
|
+ ])
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+})
|
|
|
+
|
|
|
+// 日排水量图表配置
|
|
|
+const dailyDischargeChartOption = ref({
|
|
|
+ grid: {
|
|
|
+ left: '2%',
|
|
|
+ top: '15%',
|
|
|
+ right: '5%',
|
|
|
+ bottom: '15%',
|
|
|
+ containLabel: true
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ type: 'category',
|
|
|
+ data: ['1月1日', '1月2日', '1月3日', '1月4日', '1月5日'],
|
|
|
+ axisLine: {
|
|
|
+ lineStyle: {
|
|
|
+ color: 'rgba(48, 220, 255, 0.6)'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ axisLabel: {
|
|
|
+ color: 'rgba(255, 255, 255, 0.8)',
|
|
|
+ fontSize: 9,
|
|
|
+ rotate: 30
|
|
|
+ },
|
|
|
+ boundaryGap: true
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ type: 'value',
|
|
|
+ axisLine: {
|
|
|
+ lineStyle: {
|
|
|
+ color: 'rgba(48, 220, 255, 0.6)'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ axisLabel: {
|
|
|
+ color: 'rgba(255, 255, 255, 0.8)',
|
|
|
+ fontSize: 9,
|
|
|
+ formatter: '{value} 万m³'
|
|
|
+ },
|
|
|
+ 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: '40%',
|
|
|
+ data: [12.5, 15.8, 18.2, 16.5, 17.3],
|
|
|
+ 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 currentWaterLevelTab = ref('inner')
|
|
|
+
|
|
|
+// 圩内水位数据
|
|
|
+const innerWaterLevelData = {
|
|
|
+ level: '2.54',
|
|
|
+ change: '-0.05',
|
|
|
+ historyMax: '4.06',
|
|
|
+ ecological: '2.08',
|
|
|
+ alertDiff: '-0.79',
|
|
|
+ chartData: [2.60, 2.62, 2.58, 2.56, 2.54],
|
|
|
+ flowData: [0.4, 0.5, 0.3, 0.4, 0.3]
|
|
|
+}
|
|
|
+
|
|
|
+// 圩外水位数据
|
|
|
+const outerWaterLevelData = {
|
|
|
+ level: '2.65',
|
|
|
+ change: '+0.02',
|
|
|
+ historyMax: '4.12',
|
|
|
+ ecological: '2.10',
|
|
|
+ alertDiff: '-0.68',
|
|
|
+ chartData: [2.62, 2.63, 2.64, 2.65, 2.65],
|
|
|
+ flowData: [0.5, 0.6, 0.5, 0.4, 0.5]
|
|
|
+}
|
|
|
+
|
|
|
+// 当前水位数据
|
|
|
+const currentWaterLevelData = computed(() => {
|
|
|
+ return currentWaterLevelTab.value === 'inner' ? innerWaterLevelData : outerWaterLevelData
|
|
|
+})
|
|
|
+
|
|
|
+// 当前水位图表配置
|
|
|
+const currentWaterLevelChartOption = computed(() => {
|
|
|
+ const data = currentWaterLevelTab.value === 'inner' ? innerWaterLevelData : outerWaterLevelData
|
|
|
+ return {
|
|
|
+ grid: {
|
|
|
+ left: '4%',
|
|
|
+ top: '12%',
|
|
|
+ right: '10%',
|
|
|
+ bottom: '18%',
|
|
|
+ containLabel: true
|
|
|
+ },
|
|
|
+ legend: {
|
|
|
+ data: ['水位', '流量'],
|
|
|
+ top: '2%',
|
|
|
+ textStyle: {
|
|
|
+ color: 'rgba(255, 255, 255, 0.8)',
|
|
|
+ fontSize: 10
|
|
|
+ },
|
|
|
+ itemWidth: 10,
|
|
|
+ itemHeight: 10,
|
|
|
+ selected: {
|
|
|
+ '水位': true,
|
|
|
+ '流量': false
|
|
|
+ },
|
|
|
+ selectedMode: 'single'
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ type: 'category',
|
|
|
+ data: ['02-11 10:00', '02-11 16:00', '02-11 22:00', '02-12 04:00', '02-12 10:00'],
|
|
|
+ axisLine: {
|
|
|
+ lineStyle: {
|
|
|
+ color: 'rgba(48, 220, 255, 0.6)'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ axisLabel: {
|
|
|
+ color: 'rgba(255, 255, 255, 0.8)',
|
|
|
+ fontSize: 10
|
|
|
+ },
|
|
|
+ boundaryGap: false
|
|
|
+ },
|
|
|
+ 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: 10
|
|
|
+ },
|
|
|
+ splitLine: {
|
|
|
+ lineStyle: {
|
|
|
+ color: 'rgba(48, 220, 255, 0.2)'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ axisPointer: {
|
|
|
+ show: true
|
|
|
+ },
|
|
|
+ markLine: {
|
|
|
+ silent: true,
|
|
|
+ lineStyle: {
|
|
|
+ width: 1,
|
|
|
+ type: 'dashed'
|
|
|
+ },
|
|
|
+ symbol: 'none',
|
|
|
+ label: {
|
|
|
+ position: 'end',
|
|
|
+ distance: 10
|
|
|
+ },
|
|
|
+ data: [
|
|
|
+ {
|
|
|
+ yAxis: 3.32,
|
|
|
+ label: {
|
|
|
+ formatter: '警戒水位',
|
|
|
+ color: '#ffcc00'
|
|
|
+ },
|
|
|
+ lineStyle: {
|
|
|
+ color: '#ffcc00'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ },
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'axis',
|
|
|
+ backgroundColor: 'rgba(0, 20, 40, 0.9)',
|
|
|
+ borderColor: 'rgba(48, 220, 255, 0.5)',
|
|
|
+ textStyle: {
|
|
|
+ color: '#fff'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ name: '水位',
|
|
|
+ type: 'line',
|
|
|
+ data: data.chartData,
|
|
|
+ smooth: true,
|
|
|
+ symbol: 'circle',
|
|
|
+ symbolSize: 8,
|
|
|
+ lineStyle: {
|
|
|
+ color: '#30dcff',
|
|
|
+ width: 2,
|
|
|
+ shadowColor: 'rgba(48, 220, 255, 0.6)',
|
|
|
+ shadowBlur: 10
|
|
|
+ },
|
|
|
+ itemStyle: {
|
|
|
+ color: '#30dcff',
|
|
|
+ borderColor: '#fff',
|
|
|
+ borderWidth: 2
|
|
|
+ },
|
|
|
+ areaStyle: {
|
|
|
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
|
+ {
|
|
|
+ offset: 0,
|
|
|
+ color: 'rgba(48, 220, 255, 0.3)'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ offset: 1,
|
|
|
+ color: 'rgba(48, 220, 255, 0.1)'
|
|
|
+ }
|
|
|
+ ])
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '流量',
|
|
|
+ type: 'line',
|
|
|
+ data: data.flowData,
|
|
|
+ smooth: true,
|
|
|
+ symbol: 'circle',
|
|
|
+ symbolSize: 6,
|
|
|
+ lineStyle: {
|
|
|
+ color: '#00ff88',
|
|
|
+ width: 2,
|
|
|
+ shadowColor: 'rgba(0, 255, 136, 0.6)',
|
|
|
+ shadowBlur: 10
|
|
|
+ },
|
|
|
+ itemStyle: {
|
|
|
+ color: '#00ff88',
|
|
|
+ borderColor: '#fff',
|
|
|
+ borderWidth: 2
|
|
|
+ },
|
|
|
+ areaStyle: {
|
|
|
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
|
+ {
|
|
|
+ offset: 0,
|
|
|
+ color: 'rgba(0, 255, 136, 0.3)'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ offset: 1,
|
|
|
+ color: 'rgba(0, 255, 136, 0.1)'
|
|
|
+ }
|
|
|
+ ])
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+// 降雨预报数据
|
|
|
+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)
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.polder-detail-content {
|
|
|
+ position: relative;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.left-panel {
|
|
|
+ position: absolute;
|
|
|
+ z-index: 4;
|
|
|
+ width: 398px;
|
|
|
+ left: 32px;
|
|
|
+ top: 100px;
|
|
|
+ bottom: 50px;
|
|
|
+ perspective: 500px;
|
|
|
+ perspective-origin: 50% 50%;
|
|
|
+}
|
|
|
+
|
|
|
+.left-panel-3d {
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ top: 0;
|
|
|
+ right: 0;
|
|
|
+ bottom: 0;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 10px;
|
|
|
+ transform: translate3d(0px, 0px, 0px) scaleX(1) scaleY(1) rotateX(0deg) rotateY(6deg) rotateZ(0deg) skewX(0deg) skewY(0deg);
|
|
|
+ z-index: 4;
|
|
|
+}
|
|
|
+
|
|
|
+.right-panel {
|
|
|
+ position: absolute;
|
|
|
+ z-index: 4;
|
|
|
+ width: 398px;
|
|
|
+ right: 32px;
|
|
|
+ top: 100px;
|
|
|
+ bottom: 50px;
|
|
|
+ perspective: 500px;
|
|
|
+ perspective-origin: 50% 50%;
|
|
|
+}
|
|
|
+
|
|
|
+.right-panel-3d {
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ top: 0;
|
|
|
+ right: 0;
|
|
|
+ bottom: 0;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 10px;
|
|
|
+ transform: translate3d(0px, 0px, 0px) scaleX(1) scaleY(1) rotateX(0deg) rotateY(-6deg) rotateZ(0deg) skewX(0deg) skewY(0deg);
|
|
|
+ z-index: 4;
|
|
|
+}
|
|
|
+
|
|
|
+.water-station-card {
|
|
|
+ pointer-events: auto;
|
|
|
+
|
|
|
+ &.water-station-card-top {
|
|
|
+ flex-shrink: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.water-station-card-bottom {
|
|
|
+ flex: 1;
|
|
|
+ min-height: 200px;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.water-level-analysis-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: 6px;
|
|
|
+}
|
|
|
+
|
|
|
+.water-level-tabs {
|
|
|
+ display: flex;
|
|
|
+ gap: 4px;
|
|
|
+ padding: 2px;
|
|
|
+ background: rgba(0, 100, 150, 0.3);
|
|
|
+ border-radius: 3px;
|
|
|
+
|
|
|
+ .tab-item {
|
|
|
+ flex: 1;
|
|
|
+ padding: 3px 6px;
|
|
|
+ text-align: center;
|
|
|
+ border-radius: 2px;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+ background: rgba(0, 50, 100, 0.5);
|
|
|
+ border: 1px solid rgba(48, 220, 255, 0.3);
|
|
|
+
|
|
|
+ span {
|
|
|
+ font-size: 9px;
|
|
|
+ color: rgba(255, 255, 255, 0.8);
|
|
|
+ }
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background: rgba(0, 80, 120, 0.6);
|
|
|
+ border-color: rgba(48, 220, 255, 0.5);
|
|
|
+ }
|
|
|
+
|
|
|
+ &.active {
|
|
|
+ background: rgba(48, 220, 255, 0.2);
|
|
|
+ border-color: rgba(48, 220, 255, 0.8);
|
|
|
+ box-shadow: 0 0 6px rgba(48, 220, 255, 0.3);
|
|
|
+
|
|
|
+ span {
|
|
|
+ color: #30dcff;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.water-level-data {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(5, 1fr);
|
|
|
+ gap: 4px;
|
|
|
+ padding: 6px;
|
|
|
+ background: rgba(0, 100, 150, 0.3);
|
|
|
+ border-radius: 4px;
|
|
|
+
|
|
|
+ .data-item {
|
|
|
+ text-align: center;
|
|
|
+
|
|
|
+ .data-label {
|
|
|
+ font-size: 9px;
|
|
|
+ color: rgba(255, 255, 255, 0.7);
|
|
|
+ margin-bottom: 1px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .data-value {
|
|
|
+ font-size: 11px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #30dcff;
|
|
|
+ font-family: "D-DIN";
|
|
|
+
|
|
|
+ &.negative {
|
|
|
+ color: #ff6b6b;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.water-level-chart {
|
|
|
+ flex: 1;
|
|
|
+ min-height: 240px;
|
|
|
+ padding: 0;
|
|
|
+
|
|
|
+ :deep(.echarts-container) {
|
|
|
+ width: 100% !important;
|
|
|
+ height: 100% !important;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.polder-work-status-panel {
|
|
|
+ height: 100%;
|
|
|
+ padding: 6px;
|
|
|
+ box-sizing: border-box;
|
|
|
+ background: rgba(0, 30, 60, 0.5);
|
|
|
+ border-radius: 6px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 6px;
|
|
|
+}
|
|
|
+
|
|
|
+.pump-status-cards {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(2, 1fr);
|
|
|
+ gap: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.pump-status-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;
|
|
|
+
|
|
|
+ .pump-name {
|
|
|
+ font-size: 11px;
|
|
|
+ color: rgba(255, 255, 255, 0.9);
|
|
|
+ margin-bottom: 4px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .pump-status {
|
|
|
+ font-size: 12px;
|
|
|
+ font-weight: bold;
|
|
|
+ margin-bottom: 2px;
|
|
|
+
|
|
|
+ &.status-active {
|
|
|
+ color: #00ff88;
|
|
|
+ text-shadow: 0 0 10px rgba(0, 255, 136, 0.5);
|
|
|
+ }
|
|
|
+
|
|
|
+ &.status-inactive {
|
|
|
+ color: #ff6b6b;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .pump-flow {
|
|
|
+ font-size: 10px;
|
|
|
+ color: #30dcff;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.flow-chart-container,
|
|
|
+.discharge-chart-container {
|
|
|
+ flex: 1;
|
|
|
+ background: rgba(0, 100, 150, 0.2);
|
|
|
+ border: 1px solid rgba(48, 220, 255, 0.3);
|
|
|
+ border-radius: 4px;
|
|
|
+ padding: 4px;
|
|
|
+ min-height: 160px;
|
|
|
+
|
|
|
+ .chart-title {
|
|
|
+ font-size: 9px;
|
|
|
+ color: #30dcff;
|
|
|
+ margin-bottom: 2px;
|
|
|
+ text-align: center;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.echarts-container) {
|
|
|
+ width: 100% !important;
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.polder-layer-controls {
|
|
|
+ position: absolute;
|
|
|
+ right: 420px;
|
|
|
+ top: 65%;
|
|
|
+ transform: translateY(-50%);
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 15px;
|
|
|
+ z-index: 1000;
|
|
|
+ pointer-events: auto;
|
|
|
+
|
|
|
+ .toggle-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 10px;
|
|
|
+ padding: 8px 12px;
|
|
|
+ background: rgba(0, 20, 40, 0.8);
|
|
|
+ border-radius: 6px;
|
|
|
+
|
|
|
+ .toggle-text {
|
|
|
+ color: #fff;
|
|
|
+ font-size: 14px;
|
|
|
+ text-shadow: 0 0 5px rgba(0, 0, 0, 0.8);
|
|
|
+ }
|
|
|
+
|
|
|
+ .toggle-switch {
|
|
|
+ width: 44px;
|
|
|
+ height: 22px;
|
|
|
+ background: rgba(100, 100, 100, 0.5);
|
|
|
+ border-radius: 11px;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+ position: relative;
|
|
|
+
|
|
|
+ .toggle-knob {
|
|
|
+ position: absolute;
|
|
|
+ left: 2px;
|
|
|
+ top: 2px;
|
|
|
+ width: 18px;
|
|
|
+ height: 18px;
|
|
|
+ background: #a3dcde;
|
|
|
+ border-radius: 50%;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.active {
|
|
|
+ background: rgba(48, 220, 255, 0.4);
|
|
|
+ box-shadow: 0 0 10px rgba(48, 220, 255, 0.3);
|
|
|
+
|
|
|
+ .toggle-knob {
|
|
|
+ left: 24px;
|
|
|
+ background: #30dcff;
|
|
|
+ box-shadow: 0 0 8px rgba(48, 220, 255, 0.5);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|