Sfoglia il codice sorgente

新建水文四预页面和水资源调配页面

WQQ 1 settimana fa
parent
commit
8014efecfa

+ 731 - 0
src/components/HydrologyForecastPanel.vue

@@ -0,0 +1,731 @@
+<template>
+  <div class="forecast-panel">
+    <div class="left-sidebar">
+      <div class="data-card">
+        <div class="card-header" @click="toggleHydrologyForecast">
+          <h3 class="card-title">水文预报</h3>
+          <div class="header-actions">
+            <span class="toggle-btn">{{ hydrologyForecastExpanded ? '▼' : '▶' }}</span>
+          </div>
+        </div>
+        <div v-if="hydrologyForecastExpanded" class="card-body">
+          <div class="forecast-content">
+            <div class="chart-box">
+              <div class="chart-title">未来24小时水位预报</div>
+              <canvas id="forecastWaterLevelChart" width="300" height="180"></canvas>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div class="data-card mt-20">
+        <div class="card-header" @click="toggleDistrictRainfall">
+          <h3 class="card-title">分区降雨预报</h3>
+          <div class="header-actions">
+            <span class="update-time">{{ rainfallDateRange }}</span>
+            <span class="toggle-btn">{{ districtRainfallExpanded ? '▼' : '▶' }}</span>
+          </div>
+        </div>
+        <div v-if="districtRainfallExpanded" class="card-body">
+          <div class="district-rainfall-content">
+            <div class="rainfall-map-container">
+              <img :src="rainfallMapImage" alt="连云港降雨分布图" class="rainfall-map-image">
+            </div>
+            <div class="rainfall-legend">
+              <div class="legend-item">
+                <div class="legend-color level-0"></div>
+                <span class="legend-text">0~10</span>
+              </div>
+              <div class="legend-item">
+                <div class="legend-color level-1"></div>
+                <span class="legend-text">10~25</span>
+              </div>
+              <div class="legend-item">
+                <div class="legend-color level-2"></div>
+                <span class="legend-text">25~50</span>
+              </div>
+              <div class="legend-item">
+                <div class="legend-color level-3"></div>
+                <span class="legend-text">50~100</span>
+              </div>
+              <div class="legend-item">
+                <div class="legend-color level-4"></div>
+                <span class="legend-text">100~250</span>
+              </div>
+              <div class="legend-item">
+                <div class="legend-color level-5"></div>
+                <span class="legend-text">&gt;=250</span>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div class="data-card mt-20">
+        <div class="card-header" @click="toggleFlowForecast">
+          <h3 class="card-title">流量预报</h3>
+          <div class="header-actions">
+            <span class="toggle-btn">{{ flowForecastExpanded ? '▼' : '▶' }}</span>
+          </div>
+        </div>
+        <div v-if="flowForecastExpanded" class="card-body">
+          <div class="flow-forecast-content">
+            <div class="chart-box">
+              <div class="chart-title">未来72小时流量预报</div>
+              <canvas id="forecastFlowChart" width="300" height="180"></canvas>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div class="right-sidebar">
+      <div class="data-card">
+        <div class="card-header" @click="toggleWarningLevel">
+          <h3 class="card-title">预警级别</h3>
+          <div class="header-actions">
+            <span class="toggle-btn">{{ warningLevelExpanded ? '▼' : '▶' }}</span>
+          </div>
+        </div>
+        <div v-if="warningLevelExpanded" class="card-body">
+          <div class="warning-levels">
+            <div class="warning-item" v-for="(level, index) in warningLevels" :key="index">
+              <div class="warning-indicator" :class="level.class"></div>
+              <div class="warning-info">
+                <div class="warning-name">{{ level.name }}</div>
+                <div class="warning-desc">{{ level.desc }}</div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div class="data-card mt-20">
+        <div class="card-header" @click="toggleForecastStations">
+          <h3 class="card-title">预报站点</h3>
+          <div class="header-actions">
+            <span class="toggle-btn">{{ forecastStationsExpanded ? '▼' : '▶' }}</span>
+          </div>
+        </div>
+        <div v-if="forecastStationsExpanded" class="card-body">
+          <div class="stations-list">
+            <div class="station-item" v-for="(station, index) in forecastStations" :key="index">
+              <div class="station-name">{{ station.name }}</div>
+              <div class="station-value" :class="station.status === 'normal' ? 'normal' : 'warning'">
+                {{ station.value }}m
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div class="data-card mt-20">
+        <div class="card-header" @click="toggleForecastSummary">
+          <h3 class="card-title">预报摘要</h3>
+          <div class="header-actions">
+            <span class="toggle-btn">{{ forecastSummaryExpanded ? '▼' : '▶' }}</span>
+          </div>
+        </div>
+        <div v-if="forecastSummaryExpanded" class="card-body">
+          <div class="summary-content">
+            <div class="summary-item">
+              <div class="summary-label">最高水位</div>
+              <div class="summary-value">4.2m</div>
+            </div>
+            <div class="summary-item">
+              <div class="summary-label">最大流量</div>
+              <div class="summary-value">68.5m³/s</div>
+            </div>
+            <div class="summary-item">
+              <div class="summary-label">预计降雨</div>
+              <div class="summary-value">32.8mm</div>
+            </div>
+            <div class="summary-item">
+              <div class="summary-label">预警等级</div>
+              <div class="summary-value warning">蓝色预警</div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import DataCard from './DataCard.vue'
+import * as echarts from 'echarts'
+import rainfallMapImage from '../assets/images/连云港降雨分布图.png'
+
+export default {
+  name: 'HydrologyForecastPanel',
+  components: {
+    DataCard
+  },
+  data() {
+    return {
+      rainfallDateRange: '',
+      hydrologyForecastExpanded: true,
+      districtRainfallExpanded: true,
+      flowForecastExpanded: true,
+      warningLevelExpanded: true,
+      forecastStationsExpanded: true,
+      forecastSummaryExpanded: true,
+      forecastWaterLevelChart: null,
+      forecastFlowChart: null,
+      rainfallMapImage: rainfallMapImage,
+      warningLevels: [
+        { name: '蓝色预警', desc: '水位接近警戒', class: 'blue' },
+        { name: '黄色预警', desc: '水位超过警戒', class: 'yellow' },
+        { name: '橙色预警', desc: '水位接近保证', class: 'orange' },
+        { name: '红色预警', desc: '水位超过保证', class: 'red' }
+      ],
+      forecastStations: [
+        { name: '黑林站', value: 3.8, status: 'normal' },
+        { name: '小塔山站', value: 18.6, status: 'normal' },
+        { name: '吴山站', value: 2.9, status: 'normal' },
+        { name: '陡沟站', value: 3.2, status: 'warning' }
+      ]
+    }
+  },
+  mounted() {
+    const now = new Date()
+    const month = now.getMonth() + 1
+    const day = now.getDate()
+    this.rainfallDateRange = `${month}月${day}日至今`
+    
+    setTimeout(() => {
+      this.initCharts()
+    }, 100)
+  },
+  beforeUnmount() {
+    this.destroyCharts()
+  },
+  methods: {
+    toggleHydrologyForecast() {
+      this.hydrologyForecastExpanded = !this.hydrologyForecastExpanded
+      if (this.hydrologyForecastExpanded) {
+        setTimeout(() => {
+          this.initForecastWaterLevelChart()
+        }, 100)
+      }
+    },
+    toggleDistrictRainfall() {
+      this.districtRainfallExpanded = !this.districtRainfallExpanded
+    },
+    toggleFlowForecast() {
+      this.flowForecastExpanded = !this.flowForecastExpanded
+      if (this.flowForecastExpanded) {
+        setTimeout(() => {
+          this.initForecastFlowChart()
+        }, 100)
+      }
+    },
+    toggleWarningLevel() {
+      this.warningLevelExpanded = !this.warningLevelExpanded
+    },
+    toggleForecastStations() {
+      this.forecastStationsExpanded = !this.forecastStationsExpanded
+    },
+    toggleForecastSummary() {
+      this.forecastSummaryExpanded = !this.forecastSummaryExpanded
+    },
+    initCharts() {
+      this.initForecastWaterLevelChart()
+      this.initForecastFlowChart()
+    },
+    destroyCharts() {
+      if (this.forecastWaterLevelChart) {
+        this.forecastWaterLevelChart.dispose()
+      }
+      if (this.forecastFlowChart) {
+        this.forecastFlowChart.dispose()
+      }
+    },
+    initForecastWaterLevelChart() {
+      if (document.getElementById('forecastWaterLevelChart')) {
+        if (this.forecastWaterLevelChart) {
+          this.forecastWaterLevelChart.dispose()
+        }
+        this.forecastWaterLevelChart = echarts.init(document.getElementById('forecastWaterLevelChart'))
+        const option = {
+          animation: false,
+          tooltip: {
+            trigger: 'axis'
+          },
+          grid: {
+            left: '3%',
+            right: '4%',
+            bottom: '15%',
+            top: '15%',
+            containLabel: true
+          },
+          xAxis: {
+            type: 'category',
+            boundaryGap: false,
+            data: ['00:00', '06:00', '12:00', '18:00', '次日00:00'],
+            axisLine: {
+              lineStyle: {
+                color: '#7bbef6'
+              }
+            },
+            axisLabel: {
+              color: '#7bbef6'
+            }
+          },
+          yAxis: {
+            type: 'value',
+            name: '水位(m)',
+            nameTextStyle: {
+              color: '#7bbef6'
+            },
+            min: 0,
+            max: 5,
+            axisLine: {
+              lineStyle: {
+                color: '#7bbef6'
+              }
+            },
+            axisLabel: {
+              color: '#7bbef6'
+            },
+            splitLine: {
+              lineStyle: {
+                color: 'rgba(123, 190, 246, 0.2)'
+              }
+            }
+          },
+          series: [
+            {
+              name: '预报水位',
+              type: 'line',
+              data: [2.5, 2.8, 3.5, 4.2, 3.8],
+              lineStyle: {
+                color: '#62f6fb',
+                width: 2
+              },
+              itemStyle: {
+                color: '#62f6fb'
+              },
+              areaStyle: {
+                color: 'rgba(98, 246, 251, 0.2)'
+              }
+            },
+            {
+              name: '警戒水位',
+              type: 'line',
+              data: [4.5, 4.5, 4.5, 4.5, 4.5],
+              symbol: 'none',
+              lineStyle: {
+                color: '#ff6b6b',
+                width: 2,
+                type: 'dashed'
+              }
+            }
+          ]
+        }
+        this.forecastWaterLevelChart.setOption(option)
+      }
+    },
+    initForecastFlowChart() {
+      if (document.getElementById('forecastFlowChart')) {
+        if (this.forecastFlowChart) {
+          this.forecastFlowChart.dispose()
+        }
+        this.forecastFlowChart = echarts.init(document.getElementById('forecastFlowChart'))
+        const option = {
+          animation: false,
+          tooltip: {
+            trigger: 'axis'
+          },
+          grid: {
+            left: '3%',
+            right: '4%',
+            bottom: '15%',
+            top: '15%',
+            containLabel: true
+          },
+          xAxis: {
+            type: 'category',
+            boundaryGap: false,
+            data: ['00:00', '12:00', '24:00', '36:00', '48:00', '60:00', '72:00'],
+            axisLine: {
+              lineStyle: {
+                color: '#7bbef6'
+              }
+            },
+            axisLabel: {
+              color: '#7bbef6'
+            }
+          },
+          yAxis: {
+            type: 'value',
+            name: '流量(m³/s)',
+            nameTextStyle: {
+              color: '#7bbef6'
+            },
+            min: 0,
+            max: 100,
+            axisLine: {
+              lineStyle: {
+                color: '#7bbef6'
+              }
+            },
+            axisLabel: {
+              color: '#7bbef6'
+            },
+            splitLine: {
+              lineStyle: {
+                color: 'rgba(123, 190, 246, 0.2)'
+              }
+            }
+          },
+          series: [
+            {
+              name: '预报流量',
+              type: 'line',
+              data: [45.2, 52.8, 68.5, 62.3, 55.7, 48.2, 42.5],
+              lineStyle: {
+                color: '#00d4ff',
+                width: 2
+              },
+              itemStyle: {
+                color: '#00d4ff'
+              },
+              areaStyle: {
+                color: 'rgba(0, 212, 255, 0.2)'
+              }
+            }
+          ]
+        }
+        this.forecastFlowChart.setOption(option)
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+.forecast-panel {
+  width: 100%;
+  height: 100%;
+}
+
+.left-sidebar {
+  position: absolute;
+  left: 20px;
+  top: 120px;
+  width: 350px;
+  z-index: 5;
+}
+
+.right-sidebar {
+  position: absolute;
+  right: 20px;
+  top: 120px;
+  width: 350px;
+  z-index: 5;
+}
+
+.mt-20 {
+  margin-top: 20px;
+}
+
+.data-card {
+  width: 100%;
+  background: rgba(0, 20, 40, 0.7);
+  border-radius: 4px;
+  overflow: hidden;
+  box-shadow: 0 0 10px rgba(0, 212, 255, 0.2);
+}
+
+.card-header {
+  height: 50px;
+  background-image: url('/src/assets/images/数据小标题.png');
+  background-size: 100% 100%;
+  background-position: center;
+  background-repeat: no-repeat;
+  display: flex;
+  align-items: flex-start;
+  justify-content: space-between;
+  padding: 6px 20px 0;
+  cursor: pointer;
+}
+
+.card-title {
+  font-size: 18px;
+  font-weight: bold;
+  color: #e0fcff;
+  margin: 0;
+  text-shadow: 0 0 5px rgba(0, 212, 255, 0.5);
+  padding-left: 20px;
+}
+
+.header-actions {
+  display: flex;
+  align-items: center;
+  gap: 15px;
+  margin-top: 5px;
+}
+
+.update-time {
+  color: #62f6fb;
+  font-size: 14px;
+  font-family: monospace;
+}
+
+.toggle-btn {
+  color: #e0fcff;
+  font-size: 14px;
+  cursor: pointer;
+}
+
+.card-body {
+  padding: 12px;
+  min-height: auto;
+  font-size: 16px;
+  line-height: 1.6;
+  margin-top: -10px;
+}
+
+.chart-box {
+  background: rgba(0, 20, 40, 0.5);
+  border-radius: 4px;
+  border: 1px solid rgba(0, 212, 255, 0.2);
+  padding: 8px;
+}
+
+.chart-title {
+  color: #7bbef6;
+  font-size: 13px;
+  font-weight: bold;
+  margin-bottom: 6px;
+  text-align: left;
+}
+
+.five-day-rainfall {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-around;
+  gap: 10px;
+}
+
+.rainfall-day {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  padding: 2px 2px;
+  background: rgba(0, 20, 40, 0.5);
+  border-radius: 4px;
+  border: 1px solid rgba(0, 212, 255, 0.2);
+  flex: 1;
+  min-width: 50px;
+}
+
+.rainfall-icon {
+  font-size: 24px;
+}
+
+.day-name {
+  color: #7bbef6;
+  font-size: 12px;
+  font-weight: bold;
+  margin-top: 2px;
+}
+
+.rainfall-value {
+  color: #62f6fb;
+  font-size: 11px;
+  font-weight: bold;
+  margin-top: 4px;
+}
+
+.warning-levels {
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+}
+
+.warning-item {
+  display: flex;
+  align-items: center;
+  gap: 12px;
+  padding: 8px;
+  background: rgba(0, 20, 40, 0.5);
+  border-radius: 4px;
+  border: 1px solid rgba(0, 212, 255, 0.2);
+}
+
+.warning-indicator {
+  width: 20px;
+  height: 20px;
+  border-radius: 4px;
+}
+
+.warning-indicator.blue {
+  background-color: #3b82f6;
+}
+
+.warning-indicator.yellow {
+  background-color: #ffd93d;
+}
+
+.warning-indicator.orange {
+  background-color: #f97316;
+}
+
+.warning-indicator.red {
+  background-color: #ef4444;
+}
+
+.warning-info {
+  flex: 1;
+}
+
+.warning-name {
+  color: #e0fcff;
+  font-size: 14px;
+  font-weight: bold;
+}
+
+.warning-desc {
+  color: #7bbef6;
+  font-size: 12px;
+  margin-top: 2px;
+}
+
+.stations-list {
+  display: flex;
+  flex-direction: column;
+  gap: 8px;
+}
+
+.station-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 8px 12px;
+  background: rgba(0, 20, 40, 0.5);
+  border-radius: 4px;
+  border: 1px solid rgba(0, 212, 255, 0.2);
+}
+
+.station-name {
+  color: #e0fcff;
+  font-size: 14px;
+  font-weight: bold;
+}
+
+.station-value {
+  font-size: 14px;
+  font-weight: bold;
+}
+
+.station-value.normal {
+  color: #62f6fb;
+}
+
+.station-value.warning {
+  color: #ffd93d;
+}
+
+.summary-content {
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+}
+
+.summary-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 6px 10px;
+  background: rgba(0, 20, 40, 0.5);
+  border-radius: 4px;
+}
+
+.summary-label {
+  color: #7bbef6;
+  font-size: 13px;
+}
+
+.summary-value {
+  color: #e0fcff;
+  font-size: 14px;
+  font-weight: bold;
+}
+
+.summary-value.warning {
+  color: #3b82f6;
+}
+
+.district-rainfall-content {
+  display: flex;
+  gap: 12px;
+}
+
+.rainfall-map-container {
+  flex: 1;
+  height: 140px;
+  background: rgba(0, 20, 40, 0.5);
+  border-radius: 4px;
+  border: 1px solid rgba(0, 212, 255, 0.2);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.rainfall-map-image {
+  width: 100%;
+  height: 100%;
+  object-fit: fill;
+}
+
+.rainfall-legend {
+  display: flex;
+  flex-direction: column;
+  gap: 6px;
+  justify-content: center;
+}
+
+.legend-item {
+  display: flex;
+  align-items: center;
+  gap: 2px;
+}
+
+.legend-color {
+  width: 10px;
+  height: 10px;
+  border-radius: 1px;
+}
+
+.legend-color.level-0 {
+  background-color: #4ade80;
+}
+
+.legend-color.level-1 {
+  background-color: #22c55e;
+}
+
+.legend-color.level-2 {
+  background-color: #38bdf8;
+}
+
+.legend-color.level-3 {
+  background-color: #3b82f6;
+}
+
+.legend-color.level-4 {
+  background-color: #f472b6;
+}
+
+.legend-color.level-5 {
+  background-color: #9f1239;
+}
+
+.legend-text {
+  color: #e0fcff;
+  font-size: 10px;
+}
+</style>

+ 281 - 0
src/components/HydrologyPlanPanel.vue

@@ -0,0 +1,281 @@
+<template>
+  <div class="plan-panel">
+    <div class="left-sidebar">
+      <div class="data-card">
+        <div class="card-header">
+          <h3 class="card-title">预案类型</h3>
+        </div>
+        <div class="card-body">
+          <div class="plan-types">
+            <div class="plan-type active">
+              <div class="plan-name">防汛应急预案</div>
+              <div class="plan-desc">蓝色预警级别响应</div>
+            </div>
+            <div class="plan-type">
+              <div class="plan-name">水库调度预案</div>
+              <div class="plan-desc">汛期调洪方案</div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div class="data-card mt-20">
+        <div class="card-header">
+          <h3 class="card-title">责任单位</h3>
+        </div>
+        <div class="card-body">
+          <div class="unit-list">
+            <div class="unit-item">
+              <div class="unit-name">黑林镇防汛办</div>
+              <div class="unit-contact">张主任</div>
+            </div>
+            <div class="unit-item">
+              <div class="unit-name">小塔山水库管理处</div>
+              <div class="unit-contact">李处长</div>
+            </div>
+            <div class="unit-item">
+              <div class="unit-name">黑林水文站</div>
+              <div class="unit-contact">王站长</div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div class="right-sidebar">
+      <div class="data-card">
+        <div class="card-header">
+          <h3 class="card-title">预案内容</h3>
+        </div>
+        <div class="card-body">
+          <div class="plan-content-list">
+            <div class="plan-content-item">
+              <div class="content-title">预警信息发布</div>
+              <div class="content-desc">2小时内发布预警通知</div>
+            </div>
+            <div class="plan-content-item">
+              <div class="content-title">人员转移</div>
+              <div class="content-desc">危险区域人员撤离</div>
+            </div>
+            <div class="plan-content-item">
+              <div class="content-title">物资调配</div>
+              <div class="content-desc">应急物资准备到位</div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div class="data-card mt-20">
+        <div class="card-header">
+          <h3 class="card-title">预案状态</h3>
+        </div>
+        <div class="card-body">
+          <div class="plan-status">
+            <div class="status-item">
+              <div class="status-label">预案等级</div>
+              <div class="status-value blue">IV级</div>
+            </div>
+            <div class="status-item">
+              <div class="status-label">更新时间</div>
+              <div class="status-value">2026-03-09</div>
+            </div>
+            <div class="status-item">
+              <div class="status-label">执行状态</div>
+              <div class="status-value">待命</div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import DataCard from './DataCard.vue'
+
+export default {
+  name: 'HydrologyPlanPanel',
+  components: {
+    DataCard
+  }
+}
+</script>
+
+<style scoped>
+.plan-panel {
+  width: 100%;
+  height: 100%;
+}
+
+.left-sidebar {
+  position: absolute;
+  left: 20px;
+  top: 120px;
+  width: 350px;
+  z-index: 5;
+}
+
+.right-sidebar {
+  position: absolute;
+  right: 20px;
+  top: 120px;
+  width: 350px;
+  z-index: 5;
+}
+
+.mt-20 {
+  margin-top: 20px;
+}
+
+.data-card {
+  width: 100%;
+  background: rgba(0, 20, 40, 0.7);
+  border-radius: 4px;
+  overflow: hidden;
+  box-shadow: 0 0 10px rgba(0, 212, 255, 0.2);
+}
+
+.card-header {
+  height: 50px;
+  background-image: url('/src/assets/images/数据小标题.png');
+  background-size: 100% 100%;
+  background-position: center;
+  background-repeat: no-repeat;
+  display: flex;
+  align-items: flex-start;
+  padding: 6px 20px 0;
+}
+
+.card-title {
+  font-size: 18px;
+  font-weight: bold;
+  color: #e0fcff;
+  margin: 0;
+  text-shadow: 0 0 5px rgba(0, 212, 255, 0.5);
+  padding-left: 20px;
+}
+
+.card-body {
+  padding: 12px;
+  min-height: auto;
+  font-size: 16px;
+  line-height: 1.6;
+  margin-top: -10px;
+}
+
+.plan-types {
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+}
+
+.plan-type {
+  padding: 12px;
+  background: rgba(0, 20, 40, 0.5);
+  border-radius: 4px;
+  border: 1px solid rgba(0, 212, 255, 0.2);
+  cursor: pointer;
+  transition: all 0.3s ease;
+}
+
+.plan-type:hover,
+.plan-type.active {
+  border-color: #62f6fb;
+  background: rgba(98, 246, 251, 0.1);
+}
+
+.plan-name {
+  color: #e0fcff;
+  font-size: 15px;
+  font-weight: bold;
+}
+
+.plan-desc {
+  color: #7bbef6;
+  font-size: 13px;
+  margin-top: 4px;
+}
+
+.unit-list {
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+}
+
+.unit-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 10px 12px;
+  background: rgba(0, 20, 40, 0.5);
+  border-radius: 4px;
+  border: 1px solid rgba(0, 212, 255, 0.2);
+}
+
+.unit-name {
+  color: #e0fcff;
+  font-size: 14px;
+  font-weight: bold;
+}
+
+.unit-contact {
+  color: #7bbef6;
+  font-size: 13px;
+}
+
+.plan-content-list {
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+}
+
+.plan-content-item {
+  padding: 10px 12px;
+  background: rgba(0, 20, 40, 0.5);
+  border-radius: 4px;
+  border: 1px solid rgba(0, 212, 255, 0.2);
+}
+
+.content-title {
+  color: #e0fcff;
+  font-size: 14px;
+  font-weight: bold;
+}
+
+.content-desc {
+  color: #7bbef6;
+  font-size: 13px;
+  margin-top: 4px;
+}
+
+.plan-status {
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+}
+
+.status-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 10px 12px;
+  background: rgba(0, 20, 40, 0.5);
+  border-radius: 4px;
+  border: 1px solid rgba(0, 212, 255, 0.2);
+}
+
+.status-label {
+  color: #7bbef6;
+  font-size: 14px;
+}
+
+.status-value {
+  color: #e0fcff;
+  font-size: 14px;
+  font-weight: bold;
+}
+
+.status-value.blue {
+  color: #3b82f6;
+}
+</style>

+ 281 - 0
src/components/HydrologySimulationPanel.vue

@@ -0,0 +1,281 @@
+<template>
+  <div class="simulation-panel">
+    <div class="left-sidebar">
+      <div class="data-card">
+        <div class="card-header">
+          <h3 class="card-title">预演场景</h3>
+        </div>
+        <div class="card-body">
+          <div class="scene-list">
+            <div class="scene-item active">
+              <div class="scene-name">暴雨红色预警</div>
+              <div class="scene-desc">模拟100mm/24h暴雨</div>
+            </div>
+            <div class="scene-item">
+              <div class="scene-name">水库泄洪</div>
+              <div class="scene-desc">模拟小塔山泄洪</div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div class="data-card mt-20">
+        <div class="card-header">
+          <h3 class="card-title">预演参数</h3>
+        </div>
+        <div class="card-body">
+          <div class="param-list">
+            <div class="param-item">
+              <div class="param-name">预演时长</div>
+              <div class="param-value">72小时</div>
+            </div>
+            <div class="param-item">
+              <div class="param-name">时间步长</div>
+              <div class="param-value">1小时</div>
+            </div>
+            <div class="param-item">
+              <div class="param-name">计算精度</div>
+              <div class="param-value">高精度</div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div class="right-sidebar">
+      <div class="data-card">
+        <div class="card-header">
+          <h3 class="card-title">预演结果</h3>
+        </div>
+        <div class="card-body">
+          <div class="result-list">
+            <div class="result-item">
+              <div class="result-label">最高洪峰</div>
+              <div class="result-value">4.8m</div>
+            </div>
+            <div class="result-item">
+              <div class="result-label">最大流量</div>
+              <div class="result-value">85.2m³/s</div>
+            </div>
+            <div class="result-item">
+              <div class="result-label">影响范围</div>
+              <div class="result-value">3个行政村</div>
+            </div>
+            <div class="result-item">
+              <div class="result-label">预计损失</div>
+              <div class="result-value warning">中</div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div class="data-card mt-20">
+        <div class="card-header">
+          <h3 class="card-title">预演进度</h3>
+        </div>
+        <div class="card-body">
+          <div class="progress-container">
+            <div class="progress-bar">
+              <div class="progress-fill" style="width: 75%"></div>
+            </div>
+            <div class="progress-text">75%</div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import DataCard from './DataCard.vue'
+
+export default {
+  name: 'HydrologySimulationPanel',
+  components: {
+    DataCard
+  }
+}
+</script>
+
+<style scoped>
+.simulation-panel {
+  width: 100%;
+  height: 100%;
+}
+
+.left-sidebar {
+  position: absolute;
+  left: 20px;
+  top: 120px;
+  width: 350px;
+  z-index: 5;
+}
+
+.right-sidebar {
+  position: absolute;
+  right: 20px;
+  top: 120px;
+  width: 350px;
+  z-index: 5;
+}
+
+.mt-20 {
+  margin-top: 20px;
+}
+
+.data-card {
+  width: 100%;
+  background: rgba(0, 20, 40, 0.7);
+  border-radius: 4px;
+  overflow: hidden;
+  box-shadow: 0 0 10px rgba(0, 212, 255, 0.2);
+}
+
+.card-header {
+  height: 50px;
+  background-image: url('/src/assets/images/数据小标题.png');
+  background-size: 100% 100%;
+  background-position: center;
+  background-repeat: no-repeat;
+  display: flex;
+  align-items: flex-start;
+  padding: 6px 20px 0;
+}
+
+.card-title {
+  font-size: 18px;
+  font-weight: bold;
+  color: #e0fcff;
+  margin: 0;
+  text-shadow: 0 0 5px rgba(0, 212, 255, 0.5);
+  padding-left: 20px;
+}
+
+.card-body {
+  padding: 12px;
+  min-height: auto;
+  font-size: 16px;
+  line-height: 1.6;
+  margin-top: -10px;
+}
+
+.scene-list {
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+}
+
+.scene-item {
+  padding: 12px;
+  background: rgba(0, 20, 40, 0.5);
+  border-radius: 4px;
+  border: 1px solid rgba(0, 212, 255, 0.2);
+  cursor: pointer;
+  transition: all 0.3s ease;
+}
+
+.scene-item:hover,
+.scene-item.active {
+  border-color: #62f6fb;
+  background: rgba(98, 246, 251, 0.1);
+}
+
+.scene-name {
+  color: #e0fcff;
+  font-size: 15px;
+  font-weight: bold;
+}
+
+.scene-desc {
+  color: #7bbef6;
+  font-size: 13px;
+  margin-top: 4px;
+}
+
+.param-list {
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+}
+
+.param-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 10px 12px;
+  background: rgba(0, 20, 40, 0.5);
+  border-radius: 4px;
+  border: 1px solid rgba(0, 212, 255, 0.2);
+}
+
+.param-name {
+  color: #7bbef6;
+  font-size: 14px;
+}
+
+.param-value {
+  color: #e0fcff;
+  font-size: 14px;
+  font-weight: bold;
+}
+
+.result-list {
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+}
+
+.result-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 10px 12px;
+  background: rgba(0, 20, 40, 0.5);
+  border-radius: 4px;
+  border: 1px solid rgba(0, 212, 255, 0.2);
+}
+
+.result-label {
+  color: #7bbef6;
+  font-size: 14px;
+}
+
+.result-value {
+  color: #62f6fb;
+  font-size: 14px;
+  font-weight: bold;
+}
+
+.result-value.warning {
+  color: #ffd93d;
+}
+
+.progress-container {
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+}
+
+.progress-bar {
+  width: 100%;
+  height: 20px;
+  background: rgba(0, 20, 40, 0.5);
+  border-radius: 10px;
+  overflow: hidden;
+  border: 1px solid rgba(0, 212, 255, 0.2);
+}
+
+.progress-fill {
+  height: 100%;
+  background: linear-gradient(90deg, #3b82f6, #62f6fb);
+  border-radius: 10px;
+  transition: width 0.5s ease;
+}
+
+.progress-text {
+  color: #62f6fb;
+  font-size: 18px;
+  font-weight: bold;
+  text-align: center;
+}
+</style>

+ 240 - 0
src/components/HydrologyWarningPanel.vue

@@ -0,0 +1,240 @@
+<template>
+  <div class="warning-panel">
+    <div class="left-sidebar">
+      <div class="data-card">
+        <div class="card-header">
+          <h3 class="card-title">当前预警</h3>
+        </div>
+        <div class="card-body">
+          <div class="warning-current">
+            <div class="warning-level-indicator blue"></div>
+            <div class="warning-text">
+              <div class="warning-title">蓝色预警</div>
+              <div class="warning-desc">水位接近警戒,请密切关注</div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div class="data-card mt-20">
+        <div class="card-header">
+          <h3 class="card-title">预警站点</h3>
+        </div>
+        <div class="card-body">
+          <div class="warning-stations">
+            <div class="warning-station">
+              <div class="station-name">陡沟站</div>
+              <div class="station-level warning">3.2m</div>
+              <div class="station-status">黄色</div>
+            </div>
+            <div class="warning-station">
+              <div class="station-name">黑林站</div>
+              <div class="station-level normal">3.8m</div>
+              <div class="station-status">正常</div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div class="right-sidebar">
+      <div class="data-card">
+        <div class="card-header">
+          <h3 class="card-title">预警历史</h3>
+        </div>
+        <div class="card-body">
+          <div class="warning-history">
+            <div class="history-item">
+              <div class="history-time">2026-03-09 14:30</div>
+              <div class="history-level blue">蓝色预警</div>
+            </div>
+            <div class="history-item">
+              <div class="history-time">2026-03-08 18:20</div>
+              <div class="history-level blue">蓝色预警</div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import DataCard from './DataCard.vue'
+
+export default {
+  name: 'HydrologyWarningPanel',
+  components: {
+    DataCard
+  }
+}
+</script>
+
+<style scoped>
+.warning-panel {
+  width: 100%;
+  height: 100%;
+}
+
+.left-sidebar {
+  position: absolute;
+  left: 20px;
+  top: 120px;
+  width: 350px;
+  z-index: 5;
+}
+
+.right-sidebar {
+  position: absolute;
+  right: 20px;
+  top: 120px;
+  width: 350px;
+  z-index: 5;
+}
+
+.mt-20 {
+  margin-top: 20px;
+}
+
+.data-card {
+  width: 100%;
+  background: rgba(0, 20, 40, 0.7);
+  border-radius: 4px;
+  overflow: hidden;
+  box-shadow: 0 0 10px rgba(0, 212, 255, 0.2);
+}
+
+.card-header {
+  height: 50px;
+  background-image: url('/src/assets/images/数据小标题.png');
+  background-size: 100% 100%;
+  background-position: center;
+  background-repeat: no-repeat;
+  display: flex;
+  align-items: flex-start;
+  padding: 6px 20px 0;
+}
+
+.card-title {
+  font-size: 18px;
+  font-weight: bold;
+  color: #e0fcff;
+  margin: 0;
+  text-shadow: 0 0 5px rgba(0, 212, 255, 0.5);
+  padding-left: 20px;
+}
+
+.card-body {
+  padding: 12px;
+  min-height: auto;
+  font-size: 16px;
+  line-height: 1.6;
+  margin-top: -10px;
+}
+
+.warning-current {
+  display: flex;
+  align-items: center;
+  gap: 15px;
+  padding: 15px;
+  background: rgba(0, 20, 40, 0.5);
+  border-radius: 4px;
+  border: 1px solid rgba(0, 212, 255, 0.2);
+}
+
+.warning-level-indicator {
+  width: 40px;
+  height: 40px;
+  border-radius: 8px;
+}
+
+.warning-level-indicator.blue {
+  background-color: #3b82f6;
+}
+
+.warning-text {
+  flex: 1;
+}
+
+.warning-title {
+  color: #e0fcff;
+  font-size: 18px;
+  font-weight: bold;
+}
+
+.warning-desc {
+  color: #7bbef6;
+  font-size: 14px;
+  margin-top: 4px;
+}
+
+.warning-stations {
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+}
+
+.warning-station {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 10px 12px;
+  background: rgba(0, 20, 40, 0.5);
+  border-radius: 4px;
+  border: 1px solid rgba(0, 212, 255, 0.2);
+}
+
+.station-name {
+  color: #e0fcff;
+  font-size: 14px;
+  font-weight: bold;
+}
+
+.station-level {
+  font-size: 14px;
+  font-weight: bold;
+}
+
+.station-level.normal {
+  color: #62f6fb;
+}
+
+.station-level.warning {
+  color: #ffd93d;
+}
+
+.station-status {
+  font-size: 13px;
+  color: #7bbef6;
+}
+
+.warning-history {
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+}
+
+.history-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 10px 12px;
+  background: rgba(0, 20, 40, 0.5);
+  border-radius: 4px;
+  border: 1px solid rgba(0, 212, 255, 0.2);
+}
+
+.history-time {
+  color: #7bbef6;
+  font-size: 13px;
+}
+
+.history-level {
+  font-size: 14px;
+  font-weight: bold;
+}
+
+.history-level.blue {
+  color: #3b82f6;
+}
+</style>

+ 36 - 63
src/views/HomeView.vue

@@ -1,7 +1,8 @@
 <template>
   <div class="dashboard">
+    <div class="background-image"></div>
     <div class="bottom-bg" v-if="!showMap"></div>
-    <div class="top-title"></div>
+    <div class="top-title" :class="{ 'title-alt': activeTab === '水文四预' || activeTab === '水资源调配' }"></div>
     <div class="system-title">数字孪生黑林小流域</div>
     
     <!-- 全局地图 -->
@@ -51,74 +52,26 @@
     <!-- 流域总览视图 -->
     <OverviewView v-if="activeTab === '流域总览'" @selectTab="selectTab" />
     
-    <!-- 水文四预的二级标题 -->
-    <div v-if="activeTab === '水文四预'" class="secondary-title-container">
-      <div 
-        class="secondary-title" 
-        :class="{ active: activeSecondaryTab === '水文预报' }"
-        @click="selectSecondaryTab('水文预报')"
-      >
-        <span>水文预报</span>
-      </div>
-      <div 
-        class="secondary-title" 
-        :class="{ active: activeSecondaryTab === '水文预警' }"
-        @click="selectSecondaryTab('水文预警')"
-      >
-        <span>水文预警</span>
-      </div>
-      <div 
-        class="secondary-title" 
-        :class="{ active: activeSecondaryTab === '水文预演' }"
-        @click="selectSecondaryTab('水文预演')"
-      >
-        <span>水文预演</span>
-      </div>
-      <div 
-        class="secondary-title" 
-        :class="{ active: activeSecondaryTab === '水文预案' }"
-        @click="selectSecondaryTab('水文预案')"
-      >
-        <span>水文预案</span>
-      </div>
-    </div>
+    <!-- 水文四预视图 -->
+    <HydrologyForecastView 
+      v-if="activeTab === '水文四预'" 
+      :activeSecondaryTab="activeSecondaryTab"
+      @selectSecondaryTab="selectSecondaryTab"
+    />
     
-    <!-- 水资源调配的二级标题 -->
-    <div v-else-if="activeTab === '水资源调配'" class="secondary-title-container">
-      <div 
-        class="secondary-title" 
-        :class="{ active: activeSecondaryTab === '调配基础数据' }"
-        @click="selectSecondaryTab('调配基础数据')"
-      >
-        <span>调配基础数据</span>
-      </div>
-      <div 
-        class="secondary-title" 
-        :class="{ active: activeSecondaryTab === '供关系分析' }"
-        @click="selectSecondaryTab('供关系分析')"
-      >
-        <span>供关系分析</span>
-      </div>
-      <div 
-        class="secondary-title" 
-        :class="{ active: activeSecondaryTab === '需水优化建议' }"
-        @click="selectSecondaryTab('需水优化建议')"
-      >
-        <span>需水优化建议</span>
-      </div>
-      <div 
-        class="secondary-title" 
-        :class="{ active: activeSecondaryTab === '调配效果预演' }"
-        @click="selectSecondaryTab('调配效果预演')"
-      >
-        <span>调配效果预演</span>
-      </div>
-    </div>
+    <!-- 水资源调配视图 -->
+    <WaterResourceAllocationView 
+      v-if="activeTab === '水资源调配'" 
+      :activeSecondaryTab="activeSecondaryTab"
+      @selectSecondaryTab="selectSecondaryTab"
+    />
   </div>
 </template>
 
 <script>
 import OverviewView from './OverviewView.vue'
+import HydrologyForecastView from './HydrologyForecastView.vue'
+import WaterResourceAllocationView from './WaterResourceAllocationView.vue'
 import CesiumMap from '../components/CesiumMap.vue'
 import GradientOverlay from '../components/gradient-overlay.vue'
 
@@ -126,6 +79,8 @@ export default {
   name: 'HomeView',
   components: {
     OverviewView,
+    HydrologyForecastView,
+    WaterResourceAllocationView,
     CesiumMap,
     GradientOverlay
   },
@@ -163,6 +118,20 @@ export default {
   position: relative;
 }
 
+.background-image {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background-image: url('/src/assets/images/背景.png');
+  background-size: 100% 100%;
+  background-position: center;
+  background-repeat: no-repeat;
+  pointer-events: none;
+  z-index: 3;
+}
+
 .bottom-bg {
   position: absolute;
   bottom: 0;
@@ -191,6 +160,10 @@ export default {
   z-index: 4;
 }
 
+.top-title.title-alt {
+  background-image: url('/src/assets/images/顶部大标题1.png');
+}
+
 .system-title {
   position: absolute;
   top: 20px;

+ 123 - 0
src/views/HydrologyForecastView.vue

@@ -0,0 +1,123 @@
+<template>
+  <div class="hydrology-forecast-container">
+    <div class="secondary-title-container">
+      <div 
+        class="secondary-title" 
+        :class="{ active: activeSecondaryTab === '水文预报' }"
+        @click="selectSecondaryTab('水文预报')"
+      >
+        <span>水文预报</span>
+      </div>
+      <div 
+        class="secondary-title" 
+        :class="{ active: activeSecondaryTab === '水文预警' }"
+        @click="selectSecondaryTab('水文预警')"
+      >
+        <span>水文预警</span>
+      </div>
+      <div 
+        class="secondary-title" 
+        :class="{ active: activeSecondaryTab === '水文预演' }"
+        @click="selectSecondaryTab('水文预演')"
+      >
+        <span>水文预演</span>
+      </div>
+      <div 
+        class="secondary-title" 
+        :class="{ active: activeSecondaryTab === '水文预案' }"
+        @click="selectSecondaryTab('水文预案')"
+      >
+        <span>水文预案</span>
+      </div>
+    </div>
+
+    <HydrologyForecastPanel v-if="activeSecondaryTab === '水文预报'" />
+    <HydrologyWarningPanel v-if="activeSecondaryTab === '水文预警'" />
+    <HydrologySimulationPanel v-if="activeSecondaryTab === '水文预演'" />
+    <HydrologyPlanPanel v-if="activeSecondaryTab === '水文预案'" />
+  </div>
+</template>
+
+<script>
+import HydrologyForecastPanel from '../components/HydrologyForecastPanel.vue'
+import HydrologyWarningPanel from '../components/HydrologyWarningPanel.vue'
+import HydrologySimulationPanel from '../components/HydrologySimulationPanel.vue'
+import HydrologyPlanPanel from '../components/HydrologyPlanPanel.vue'
+
+export default {
+  name: 'HydrologyForecastView',
+  components: {
+    HydrologyForecastPanel,
+    HydrologyWarningPanel,
+    HydrologySimulationPanel,
+    HydrologyPlanPanel
+  },
+  props: {
+    activeSecondaryTab: {
+      type: String,
+      default: '水文预报'
+    }
+  },
+  emits: ['selectSecondaryTab'],
+  methods: {
+    selectSecondaryTab(tab) {
+      this.$emit('selectSecondaryTab', tab)
+    }
+  }
+}
+</script>
+
+<style scoped>
+.hydrology-forecast-container {
+  width: 100%;
+  height: 100%;
+  position: relative;
+}
+
+.secondary-title-container {
+  position: absolute;
+  bottom: 46px;
+  left: 50%;
+  transform: translateX(-50%);
+  display: flex;
+  gap: 20px;
+  z-index: 4;
+}
+
+.secondary-title {
+  width: 159px;
+  height: 31px;
+  background-image: url('/src/assets/images/未选中底部标题.png');
+  background-size: 100% 100%;
+  background-position: center;
+  background-repeat: no-repeat;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 14px;
+  font-weight: bold;
+  cursor: pointer;
+  transition: all 0.3s ease;
+}
+
+.secondary-title span {
+  background: linear-gradient(to bottom, #e2e8ff, #7bbef6);
+  -webkit-background-clip: text;
+  background-clip: text;
+  color: transparent;
+  text-shadow: 0 0 5px rgba(0, 212, 255, 0.3);
+}
+
+.secondary-title:hover,
+.secondary-title.active {
+  background-image: url('/src/assets/images/选中底部标题.png');
+}
+
+.secondary-title:hover span,
+.secondary-title.active span {
+  background: linear-gradient(to bottom, #e2e8ff, #62f6fb);
+  -webkit-background-clip: text;
+  background-clip: text;
+  color: transparent;
+}
+</style>

+ 612 - 0
src/views/WaterResourceAllocationView.vue

@@ -0,0 +1,612 @@
+<template>
+  <div class="water-allocation-container">
+    <div class="secondary-title-container">
+      <div 
+        class="secondary-title" 
+        :class="{ active: activeSecondaryTab === '调配基础数据' }"
+        @click="selectSecondaryTab('调配基础数据')"
+      >
+        <span>调配基础数据</span>
+      </div>
+      <div 
+        class="secondary-title" 
+        :class="{ active: activeSecondaryTab === '供水关系分析' }"
+        @click="selectSecondaryTab('供水关系分析')"
+      >
+        <span>供水关系分析</span>
+      </div>
+      <div 
+        class="secondary-title" 
+        :class="{ active: activeSecondaryTab === '需水优化建议' }"
+        @click="selectSecondaryTab('需水优化建议')"
+      >
+        <span>需水优化建议</span>
+      </div>
+      <div 
+        class="secondary-title" 
+        :class="{ active: activeSecondaryTab === '调配效果预演' }"
+        @click="selectSecondaryTab('调配效果预演')"
+      >
+        <span>调配效果预演</span>
+      </div>
+    </div>
+
+    <div class="left-sidebar">
+      <div class="data-card">
+        <div class="card-header" @click="toggleBasicData">
+          <h3 class="card-title">基础数据</h3>
+          <div class="header-actions">
+            <span class="toggle-btn">{{ basicDataExpanded ? '▼' : '▶' }}</span>
+          </div>
+        </div>
+        <div v-if="basicDataExpanded" class="card-body">
+          <div class="basic-data-content">
+            <div class="data-item">
+              <div class="data-label">当前库容</div>
+              <div class="data-value">2350.8 万m³</div>
+            </div>
+            <div class="data-item">
+              <div class="data-label">可用水量</div>
+              <div class="data-value">1820.5 万m³</div>
+            </div>
+            <div class="data-item">
+              <div class="data-label">日均需水</div>
+              <div class="data-value">85.2 万m³</div>
+            </div>
+            <div class="data-item">
+              <div class="data-label">日均供水</div>
+              <div class="data-value">82.6 万m³</div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div class="data-card mt-20">
+        <div class="card-header" @click="toggleReservoirStatus">
+          <h3 class="card-title">水库状态</h3>
+          <div class="header-actions">
+            <span class="toggle-btn">{{ reservoirStatusExpanded ? '▼' : '▶' }}</span>
+          </div>
+        </div>
+        <div v-if="reservoirStatusExpanded" class="card-body">
+          <div class="reservoir-list">
+            <div class="reservoir-item" v-for="(res, index) in reservoirs" :key="index">
+              <div class="reservoir-name">{{ res.name }}</div>
+              <div class="reservoir-level" :class="res.level > res.capacity * 0.8 ? 'warning' : 'normal'">
+                {{ res.level.toFixed(1) }}m
+              </div>
+              <div class="reservoir-capacity">
+                {{ (res.level / res.capacity * 100).toFixed(0) }}%
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div class="data-card mt-20">
+        <div class="card-header" @click="toggleAllocationPlan">
+          <h3 class="card-title">调配方案</h3>
+          <div class="header-actions">
+            <span class="toggle-btn">{{ allocationPlanExpanded ? '▼' : '▶' }}</span>
+          </div>
+        </div>
+        <div v-if="allocationPlanExpanded" class="card-body">
+          <div class="allocation-content">
+            <div class="chart-box">
+              <div class="chart-title">今日水资源分配</div>
+              <canvas id="allocationChart" width="300" height="180"></canvas>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div class="right-sidebar">
+      <div class="data-card">
+        <div class="card-header" @click="toggleDemandAnalysis">
+          <h3 class="card-title">需水分析</h3>
+          <div class="header-actions">
+            <span class="toggle-btn">{{ demandAnalysisExpanded ? '▼' : '▶' }}</span>
+          </div>
+        </div>
+        <div v-if="demandAnalysisExpanded" class="card-body">
+          <div class="demand-list">
+            <div class="demand-item" v-for="(demand, index) in demands" :key="index">
+              <div class="demand-name">{{ demand.name }}</div>
+              <div class="demand-value">{{ demand.value }} 万m³</div>
+              <div class="demand-percent">{{ demand.percent }}%</div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div class="data-card mt-20">
+        <div class="card-header" @click="toggleOptimization">
+          <h3 class="card-title">优化建议</h3>
+          <div class="header-actions">
+            <span class="toggle-btn">{{ optimizationExpanded ? '▼' : '▶' }}</span>
+          </div>
+        </div>
+        <div v-if="optimizationExpanded" class="card-body">
+          <div class="suggestion-list">
+            <div class="suggestion-item" v-for="(sug, index) in suggestions" :key="index">
+              <div class="suggestion-icon">{{ sug.icon }}</div>
+              <div class="suggestion-text">{{ sug.text }}</div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div class="data-card mt-20">
+        <div class="card-header" @click="toggleEffectPreview">
+          <h3 class="card-title">效果预演</h3>
+          <div class="header-actions">
+            <span class="toggle-btn">{{ effectPreviewExpanded ? '▼' : '▶' }}</span>
+          </div>
+        </div>
+        <div v-if="effectPreviewExpanded" class="card-body">
+          <div class="preview-content">
+            <div class="preview-stats">
+              <div class="stat-row">
+                <div class="stat-label">预计节水</div>
+                <div class="stat-value">+12.5%</div>
+              </div>
+              <div class="stat-row">
+                <div class="stat-label">供水保证率</div>
+                <div class="stat-value">98.2%</div>
+              </div>
+              <div class="stat-row">
+                <div class="stat-label">生态流量</div>
+                <div class="stat-value">达标</div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import DataCard from '../components/DataCard.vue'
+import * as echarts from 'echarts'
+
+export default {
+  name: 'WaterResourceAllocationView',
+  components: {
+    DataCard
+  },
+  props: {
+    activeSecondaryTab: {
+      type: String,
+      default: '调配基础数据'
+    }
+  },
+  emits: ['selectSecondaryTab'],
+  data() {
+    return {
+      basicDataExpanded: true,
+      reservoirStatusExpanded: true,
+      allocationPlanExpanded: true,
+      demandAnalysisExpanded: true,
+      optimizationExpanded: true,
+      effectPreviewExpanded: true,
+      allocationChart: null,
+      reservoirs: [
+        { name: '小塔山水库', level: 18.6, capacity: 22.5 },
+        { name: '吴山水库', level: 12.3, capacity: 15.0 },
+        { name: '陡沟水库', level: 8.5, capacity: 10.0 }
+      ],
+      demands: [
+        { name: '农业灌溉', value: 45.8, percent: 54 },
+        { name: '工业用水', value: 22.5, percent: 26 },
+        { name: '居民生活', value: 12.3, percent: 14 },
+        { name: '生态环境', value: 4.6, percent: 5 }
+      ],
+      suggestions: [
+        { icon: '💧', text: '建议灌区采用滴灌技术' },
+        { icon: '⚡', text: '优化工业用水循环利用率' },
+        { icon: '🌱', text: '加强生态补水调度' }
+      ]
+    }
+  },
+  mounted() {
+    setTimeout(() => {
+      this.initCharts()
+    }, 100)
+  },
+  beforeUnmount() {
+    this.destroyCharts()
+  },
+  methods: {
+    selectSecondaryTab(tab) {
+      this.$emit('selectSecondaryTab', tab)
+    },
+    toggleBasicData() {
+      this.basicDataExpanded = !this.basicDataExpanded
+    },
+    toggleReservoirStatus() {
+      this.reservoirStatusExpanded = !this.reservoirStatusExpanded
+    },
+    toggleAllocationPlan() {
+      this.allocationPlanExpanded = !this.allocationPlanExpanded
+      if (this.allocationPlanExpanded) {
+        setTimeout(() => {
+          this.initAllocationChart()
+        }, 100)
+      }
+    },
+    toggleDemandAnalysis() {
+      this.demandAnalysisExpanded = !this.demandAnalysisExpanded
+    },
+    toggleOptimization() {
+      this.optimizationExpanded = !this.optimizationExpanded
+    },
+    toggleEffectPreview() {
+      this.effectPreviewExpanded = !this.effectPreviewExpanded
+    },
+    initCharts() {
+      this.initAllocationChart()
+    },
+    destroyCharts() {
+      if (this.allocationChart) {
+        this.allocationChart.dispose()
+      }
+    },
+    initAllocationChart() {
+      if (document.getElementById('allocationChart')) {
+        if (this.allocationChart) {
+          this.allocationChart.dispose()
+        }
+        this.allocationChart = echarts.init(document.getElementById('allocationChart'))
+        const option = {
+          animation: false,
+          tooltip: {
+            trigger: 'item',
+            formatter: '{b}: {c}万m³ ({d}%)'
+          },
+          legend: {
+            orient: 'vertical',
+            left: 'left',
+            textStyle: {
+              color: '#7bbef6'
+            }
+          },
+          series: [
+            {
+              name: '水资源分配',
+              type: 'pie',
+              radius: ['40%', '70%'],
+              avoidLabelOverlap: false,
+              itemStyle: {
+                borderRadius: 10,
+                borderColor: 'rgba(0, 30, 60, 0.6)',
+                borderWidth: 2
+              },
+              label: {
+                show: false,
+                position: 'center'
+              },
+              emphasis: {
+                label: {
+                  show: true,
+                  fontSize: 14,
+                  fontWeight: 'bold',
+                  color: '#e0fcff'
+                }
+              },
+              labelLine: {
+                show: false
+              },
+              data: [
+                { value: 45.8, name: '农业灌溉', itemStyle: { color: '#62f6fb' } },
+                { value: 22.5, name: '工业用水', itemStyle: { color: '#00d4ff' } },
+                { value: 12.3, name: '居民生活', itemStyle: { color: '#38bdf8' } },
+                { value: 4.6, name: '生态环境', itemStyle: { color: 'rgba(123, 190, 246, 0.5)' } }
+              ]
+            }
+          ]
+        }
+        this.allocationChart.setOption(option)
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+.water-allocation-container {
+  width: 100%;
+  height: 100%;
+  position: relative;
+}
+
+.secondary-title-container {
+  position: absolute;
+  bottom: 46px;
+  left: 50%;
+  transform: translateX(-50%);
+  display: flex;
+  gap: 20px;
+  z-index: 4;
+}
+
+.secondary-title {
+  width: 159px;
+  height: 31px;
+  background-image: url('/src/assets/images/未选中底部标题.png');
+  background-size: 100% 100%;
+  background-position: center;
+  background-repeat: no-repeat;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 14px;
+  font-weight: bold;
+  cursor: pointer;
+  transition: all 0.3s ease;
+}
+
+.secondary-title span {
+  background: linear-gradient(to bottom, #e2e8ff, #7bbef6);
+  -webkit-background-clip: text;
+  background-clip: text;
+  color: transparent;
+  text-shadow: 0 0 5px rgba(0, 212, 255, 0.3);
+}
+
+.secondary-title:hover,
+.secondary-title.active {
+  background-image: url('/src/assets/images/选中底部标题.png');
+}
+
+.secondary-title:hover span,
+.secondary-title.active span {
+  background: linear-gradient(to bottom, #e2e8ff, #62f6fb);
+  -webkit-background-clip: text;
+  background-clip: text;
+  color: transparent;
+}
+
+.left-sidebar {
+  position: absolute;
+  left: 20px;
+  top: 120px;
+  width: 350px;
+  z-index: 5;
+}
+
+.right-sidebar {
+  position: absolute;
+  right: 20px;
+  top: 120px;
+  width: 350px;
+  z-index: 5;
+}
+
+.mt-20 {
+  margin-top: 20px;
+}
+
+.data-card {
+  width: 100%;
+  background: rgba(0, 20, 40, 0.7);
+  border-radius: 4px;
+  overflow: hidden;
+  box-shadow: 0 0 10px rgba(0, 212, 255, 0.2);
+}
+
+.card-header {
+  height: 50px;
+  background-image: url('/src/assets/images/数据小标题.png');
+  background-size: 100% 100%;
+  background-position: center;
+  background-repeat: no-repeat;
+  display: flex;
+  align-items: flex-start;
+  justify-content: space-between;
+  padding: 6px 20px 0;
+  cursor: pointer;
+}
+
+.card-title {
+  font-size: 18px;
+  font-weight: bold;
+  color: #e0fcff;
+  margin: 0;
+  text-shadow: 0 0 5px rgba(0, 212, 255, 0.5);
+  padding-left: 20px;
+}
+
+.header-actions {
+  display: flex;
+  align-items: center;
+  gap: 15px;
+  margin-top: 5px;
+}
+
+.toggle-btn {
+  color: #e0fcff;
+  font-size: 14px;
+  cursor: pointer;
+}
+
+.card-body {
+  padding: 12px;
+  min-height: auto;
+  font-size: 16px;
+  line-height: 1.6;
+  margin-top: -10px;
+}
+
+.basic-data-content {
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+}
+
+.data-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 8px 12px;
+  background: rgba(0, 20, 40, 0.5);
+  border-radius: 4px;
+  border: 1px solid rgba(0, 212, 255, 0.2);
+}
+
+.data-label {
+  color: #7bbef6;
+  font-size: 14px;
+}
+
+.data-value {
+  color: #e0fcff;
+  font-size: 14px;
+  font-weight: bold;
+}
+
+.reservoir-list {
+  display: flex;
+  flex-direction: column;
+  gap: 8px;
+}
+
+.reservoir-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 8px 12px;
+  background: rgba(0, 20, 40, 0.5);
+  border-radius: 4px;
+  border: 1px solid rgba(0, 212, 255, 0.2);
+}
+
+.reservoir-name {
+  color: #e0fcff;
+  font-size: 14px;
+  font-weight: bold;
+}
+
+.reservoir-level {
+  font-size: 14px;
+  font-weight: bold;
+}
+
+.reservoir-level.normal {
+  color: #62f6fb;
+}
+
+.reservoir-level.warning {
+  color: #ffd93d;
+}
+
+.reservoir-capacity {
+  color: #7bbef6;
+  font-size: 13px;
+}
+
+.chart-box {
+  background: rgba(0, 20, 40, 0.5);
+  border-radius: 4px;
+  border: 1px solid rgba(0, 212, 255, 0.2);
+  padding: 8px;
+}
+
+.chart-title {
+  color: #7bbef6;
+  font-size: 13px;
+  font-weight: bold;
+  margin-bottom: 6px;
+  text-align: left;
+}
+
+.demand-list {
+  display: flex;
+  flex-direction: column;
+  gap: 8px;
+}
+
+.demand-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 8px 12px;
+  background: rgba(0, 20, 40, 0.5);
+  border-radius: 4px;
+  border: 1px solid rgba(0, 212, 255, 0.2);
+}
+
+.demand-name {
+  color: #e0fcff;
+  font-size: 14px;
+  font-weight: bold;
+}
+
+.demand-value {
+  color: #62f6fb;
+  font-size: 14px;
+  font-weight: bold;
+}
+
+.demand-percent {
+  color: #7bbef6;
+  font-size: 13px;
+}
+
+.suggestion-list {
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+}
+
+.suggestion-item {
+  display: flex;
+  align-items: center;
+  gap: 10px;
+  padding: 10px;
+  background: rgba(0, 20, 40, 0.5);
+  border-radius: 4px;
+  border: 1px solid rgba(0, 212, 255, 0.2);
+}
+
+.suggestion-icon {
+  font-size: 20px;
+}
+
+.suggestion-text {
+  color: #e0fcff;
+  font-size: 13px;
+}
+
+.preview-content {
+  padding: 5px;
+}
+
+.preview-stats {
+  display: flex;
+  flex-direction: column;
+  gap: 12px;
+}
+
+.stat-row {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 8px 12px;
+  background: rgba(0, 20, 40, 0.5);
+  border-radius: 4px;
+  border: 1px solid rgba(0, 212, 255, 0.2);
+}
+
+.stat-label {
+  color: #7bbef6;
+  font-size: 14px;
+}
+
+.stat-value {
+  color: #62f6fb;
+  font-size: 14px;
+  font-weight: bold;
+}
+</style>