Prechádzať zdrojové kódy

feat(圩区详情): 新增圩区详情页面,包含水位分析、工情、降雨和内涝识别功能

BAI 2 týždňov pred
rodič
commit
eeaf0624e7

+ 1140 - 0
src/views/waterStation/PolderDetail.vue

@@ -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>

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 64 - 900
src/views/waterStation/index.vue


Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov