Bladeren bron

水资源页面修改

WQQ 1 maand geleden
bovenliggende
commit
7a6c94c952
2 gewijzigde bestanden met toevoegingen van 514 en 98 verwijderingen
  1. 2 9
      src/views/HomeView.vue
  2. 512 89
      src/views/WaterResourceAllocationView.vue

+ 2 - 9
src/views/HomeView.vue

@@ -2,7 +2,7 @@
   <div class="dashboard">
     <div class="background-image"></div>
     <div class="bottom-bg" v-if="!showMap"></div>
-    <div class="top-title" :class="{ 'title-alt': activeTab === '水文四预' || activeTab === '水资源调配' }"></div>
+    <div class="top-title" :class="{ 'title-alt': activeTab === '水文四预' }"></div>
     <div class="system-title">数字孪生黑林小流域</div>
     
     <!-- 全局地图 -->
@@ -37,7 +37,7 @@
       :class="{ active: activeTab === '水资源调配' }"
       @click="selectTab('水资源调配')"
     >
-      水资源调配
+      水资源
     </div>
     <div 
       class="sub-title right-2" 
@@ -46,13 +46,6 @@
     >
       孪生水文站
     </div>
-    <div 
-      class="sub-title right-3" 
-      :class="{ active: activeTab === '智能巡检' }"
-      @click="selectTab('智能巡检')"
-    >
-      智能巡检
-    </div>
     
     <!-- 流域总览视图 -->
     <OverviewView v-if="activeTab === '流域总览'" @selectTab="selectTab" />

+ 512 - 89
src/views/WaterResourceAllocationView.vue

@@ -4,7 +4,7 @@
     <div class="left-sidebar">
       <div class="data-card">
         <div class="card-header" @click="toggleBasicData">
-          <h3 class="card-title">基础数据</h3>
+          <h3 class="card-title">水资源评价</h3>
           <div class="header-actions">
             <span class="toggle-btn">{{ basicDataExpanded ? '▼' : '▶' }}</span>
           </div>
@@ -12,61 +12,33 @@
         <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 class="data-label">多年平均</div>
+              <div class="data-value">{{ basicData.multiYearAverage }} 万m³</div>
             </div>
             <div class="data-item">
-              <div class="data-label">可用水量</div>
-              <div class="data-value">1820.5 万m³</div>
+              <div class="data-label">今年已来水</div>
+              <div class="data-value">{{ basicData.currentYearInflow }} 万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 class="data-item" :class="getAnomalyClass()">
+              <div class="data-label">同期距平</div>
+              <div class="data-value" :class="basicData.anomalyPercent >= 0 ? 'positive' : 'negative'">
+                {{ basicData.anomalyPercent >= 0 ? '+' : '' }}{{ basicData.anomalyPercent }} %
               </div>
             </div>
           </div>
+          <canvas id="anomalyChart" width="380" height="280"></canvas>
         </div>
       </div>
 
       <div class="data-card mt-20">
         <div class="card-header" @click="toggleAllocationPlan">
-          <h3 class="card-title">调配方案</h3>
+          <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>
+          <canvas id="allocationChart" width="350" height="280"></canvas>
         </div>
       </div>
     </div>
@@ -185,6 +157,7 @@ export default {
       demandAnalysisExpanded: true,
       allocationChart: null,
       demandStructureChart: null,
+      anomalyChart: null,
       showDatePicker: false,
       startDate: formatDate(weekAgo),
       endDate: formatDate(today),
@@ -192,16 +165,37 @@ export default {
       currentMonth: today.getMonth(),
       currentYear: today.getFullYear(),
       weekdays: ['日', '一', '二', '三', '四', '五', '六'],
+      basicData: {
+        multiYearAverage: 285.6,
+        currentYearInflow: 85.6,
+        anomalyPercent: 9.6
+      },
+      anomalyData: {
+        months: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
+        currentYearCumulative: [15.2, 32.8, 48.5, 65.3, 85.6, 102.5, 118.2, 132.8, 147.5, 162.2, 176.5, 190.8],
+        multiYearAverageCumulative: [14.5, 30.2, 45.8, 62.5, 80.3, 95.6, 110.8, 125.2, 139.5, 153.8, 168.2, 182.5]
+      },
       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: 68 },
-        { name: '居民生活', value: 12.3, percent: 18 },
-        { name: '生态环境', value: 9.1, percent: 14 }
-      ],
+      soilMoistureData: {
+        dates: [],
+        historical: {
+          layer10: [],
+          layer20: [],
+          layer40: []
+        },
+        forecast: {
+          layer10: [],
+          layer20: [],
+          layer40: []
+        },
+        suitableRange: [0, 0],
+        lightDroughtRange: [0, 0],
+        severeDroughtRange: [0, 0]
+      },
       demandData: {
         totalDemand: 67.2,
         changePercent: 5.3,
@@ -253,16 +247,28 @@ export default {
     const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
     this.generateDemandTrendData(start, end, diffDays)
     this.generateDemandComparisonData()
+    this.generateSoilMoistureData()
     setTimeout(() => {
       this.initCharts()
       this.initDemandTrendChart()
       this.initDemandComparisonChart()
+      this.initAnomalyChart()
+      this.initAllocationChart()
     }, 100)
   },
   beforeUnmount() {
     this.destroyCharts()
   },
   methods: {
+    getAnomalyClass() {
+      if (this.basicData.anomalyPercent > 0) {
+        return 'abundant'
+      } else if (this.basicData.anomalyPercent < 0) {
+        return 'dry'
+      } else {
+        return 'normal'
+      }
+    },
     formatDate(date) {
       const year = date.getFullYear()
       const month = String(date.getMonth() + 1).padStart(2, '0')
@@ -321,6 +327,19 @@ export default {
     },
     toggleBasicData() {
       this.basicDataExpanded = !this.basicDataExpanded
+      if (this.basicDataExpanded) {
+        setTimeout(() => {
+          this.initAnomalyChart()
+        }, 100)
+      }
+    },
+    toggleAnomalyChart() {
+      this.anomalyChartExpanded = !this.anomalyChartExpanded
+      if (this.anomalyChartExpanded) {
+        setTimeout(() => {
+          this.initAnomalyChart()
+        }, 100)
+      }
     },
     toggleReservoirStatus() {
       this.reservoirStatusExpanded = !this.reservoirStatusExpanded
@@ -399,6 +418,7 @@ export default {
       const totalDemand = []
       const agriculturalDemand = []
       const residentialDemand = []
+      const evaporation = []
       const heilinInflow = []
       const xiaotaishanSupply = []
       
@@ -410,16 +430,19 @@ export default {
         
         const baseAg = 6.5
         const baseRes = 1.8
+        const baseEvap = 1.2
         const factor = 0.8 + Math.random() * 0.4
         
         const ag = parseFloat((baseAg * factor).toFixed(1))
         const res = parseFloat((baseRes * factor).toFixed(1))
+        const evap = parseFloat((baseEvap * factor).toFixed(1))
         const total = parseFloat((ag + res).toFixed(1))
         const inflow = parseFloat((total * (0.7 + Math.random() * 0.6)).toFixed(1))
         const supply = parseFloat((total * (0.8 + Math.random() * 0.5)).toFixed(1))
         
         agriculturalDemand.push(ag)
         residentialDemand.push(res)
+        evaporation.push(evap)
         totalDemand.push(total)
         heilinInflow.push(inflow)
         xiaotaishanSupply.push(supply)
@@ -432,17 +455,18 @@ export default {
         totalDemand,
         agriculturalDemand,
         residentialDemand,
+        evaporation,
         heilinInflow,
         xiaotaishanSupply
       }
     },
     generateDemandComparisonData() {
-      const currentData = [45.8, 12.3]
-      const lastYearData = [42.5, 11.8]
-      const lastMonthData = [44.2, 12.0]
+      const currentData = [45.8, 12.3, 8.5]
+      const lastYearData = [42.5, 11.8, 7.9]
+      const lastMonthData = [44.2, 12.0, 8.2]
       
       this.demandComparisonData = {
-        categories: ['农业灌溉', '居民用水'],
+        categories: ['农业灌溉', '居民用水', '蒸发量'],
         current: currentData,
         lastYear: lastYearData,
         lastMonth: lastMonthData
@@ -461,6 +485,58 @@ export default {
       if (this.demandComparisonChart) {
         this.demandComparisonChart.dispose()
       }
+      if (this.anomalyChart) {
+        this.anomalyChart.dispose()
+      }
+    },
+    generateSoilMoistureData() {
+      const today = new Date()
+      const dates = []
+      const historicalLayer10 = []
+      const historicalLayer20 = []
+      const historicalLayer40 = []
+      const forecastLayer10 = []
+      const forecastLayer20 = []
+      const forecastLayer40 = []
+
+      for (let i = 6; i >= 0; i--) {
+        const date = new Date(today.getTime() - i * 24 * 60 * 60 * 1000)
+        const month = date.getMonth() + 1
+        const day = date.getDate()
+        dates.push(`${month}月${day}日`)
+        
+        historicalLayer10.push(23 + (Math.random() - 0.5) * 6)
+        historicalLayer20.push(28 + (Math.random() - 0.5) * 6)
+        historicalLayer40.push(43 + (Math.random() - 0.5) * 6)
+      }
+
+      for (let i = 1; i <= 3; i++) {
+        const date = new Date(today.getTime() + i * 24 * 60 * 60 * 1000)
+        const month = date.getMonth() + 1
+        const day = date.getDate()
+        dates.push(`${month}月${day}日`)
+        
+        forecastLayer10.push(23 + (Math.random() - 0.5) * 6)
+        forecastLayer20.push(28 + (Math.random() - 0.5) * 6)
+        forecastLayer40.push(43 + (Math.random() - 0.5) * 6)
+      }
+
+      this.soilMoistureData = {
+        dates,
+        historical: {
+          layer10: historicalLayer10,
+          layer20: historicalLayer20,
+          layer40: historicalLayer40
+        },
+        forecast: {
+          layer10: forecastLayer10,
+          layer20: forecastLayer20,
+          layer40: forecastLayer40
+        },
+        suitableRange: [20, 35],
+        lightDroughtRange: [12, 20],
+        severeDroughtRange: [0, 12]
+      }
     },
     initAllocationChart() {
       if (document.getElementById('allocationChart')) {
@@ -468,56 +544,228 @@ export default {
           this.allocationChart.dispose()
         }
         this.allocationChart = echarts.init(document.getElementById('allocationChart'))
+        
+        const { dates, historical, forecast, suitableRange, lightDroughtRange, severeDroughtRange } = this.soilMoistureData
+        const historicalData = dates.map((date, index) => {
+          if (index < 7) {
+            return historical.layer10[index]
+          }
+          return null
+        })
+        const forecastData10 = dates.map((date, index) => {
+          if (index >= 7) {
+            return forecast.layer10[index - 7]
+          }
+          return null
+        })
+        const forecastData20 = dates.map((date, index) => {
+          if (index >= 7) {
+            return forecast.layer20[index - 7]
+          }
+          return null
+        })
+        const forecastData40 = dates.map((date, index) => {
+          if (index >= 7) {
+            return forecast.layer40[index - 7]
+          }
+          return null
+        })
+        
         const option = {
           animation: false,
           tooltip: {
-            trigger: 'item',
-            formatter: '{b}: {c}万m³ ({d}%)'
+            trigger: 'axis',
+            axisPointer: {
+              type: 'cross'
+            },
+            formatter: (params) => {
+              let result = `${params[0].name}<br/>`
+              params.forEach((param) => {
+                if (param.seriesName === '-10cm') {
+                  result += `${param.seriesName}:${param.data ? param.data.toFixed(1) : '-'}%<br/>`
+                }
+              })
+              return result
+            }
+          },
+          grid: {
+            left: 30,
+            right: 30,
+            bottom: 60,
+            top: 40,
+            containLabel: true
+          },
+          xAxis: {
+            type: 'category',
+            data: dates,
+            axisLine: {
+              lineStyle: {
+                color: '#7bbef6'
+              }
+            },
+            axisLabel: {
+              color: '#ffffff',
+              fontSize: 10,
+              interval: 0,
+              rotate: 45
+            }
+          },
+          yAxis: {
+            type: 'value',
+            name: '土壤含水率(%)',
+            nameLocation: 'end',
+            nameGap: 5,
+            nameTextStyle: {
+              color: '#ffffff',
+              fontSize: 11,
+              align: 'left',
+              verticalAlign: 'bottom',
+              padding: [0, 0, 0, -15]
+            },
+            axisLine: {
+              lineStyle: {
+                color: '#7bbef6'
+              }
+            },
+            axisLabel: {
+              color: '#ffffff',
+              fontSize: 10
+            },
+            splitLine: {
+              lineStyle: {
+                color: 'rgba(123, 190, 246, 0.2)'
+              }
+            }
           },
           legend: {
-            orient: 'vertical',
-            left: 'left',
+            data: ['-10cm', '-20cm', '-40cm'],
             textStyle: {
-              color: '#7bbef6',
+              color: '#ffffff',
               fontSize: 10
             },
-            itemWidth: 10,
-            itemHeight: 10,
-            itemGap: 6
+            itemWidth: 12,
+            itemHeight: 12,
+            itemGap: 8,
+            bottom: '0%'
+          },
+          markArea: {
+            silent: true,
+            itemStyle: {
+              opacity: 0.3
+            },
+            data: [
+              {
+                name: '适宜区间',
+                xAxis: 0,
+                yAxis: suitableRange[0],
+                label: {
+                  show: false
+                },
+                itemStyle: {
+                  color: '#4ade80'
+                }
+              },
+              {
+                name: '适宜区间',
+                xAxis: dates.length - 1,
+                yAxis: suitableRange[1],
+                label: {
+                  show: false
+                },
+                itemStyle: {
+                  color: '#4ade80'
+                }
+              }
+            ]
           },
           series: [
             {
-              name: '水资源分配',
-              type: 'pie',
-              radius: '60%',
-              avoidLabelOverlap: false,
-              label: {
-                show: true,
-                position: 'outside',
-                formatter: '{b}: {c}万m³ ({d}%)',
-                color: '#e0fcff',
-                fontSize: 11
+              name: '-10cm',
+              type: 'line',
+              data: dates.map((date, index) => {
+                if (index < 7) {
+                  return historical.layer10[index]
+                } else if (index >= 7) {
+                  return forecast.layer10[index - 7]
+                }
+                return null
+              }),
+              smooth: true,
+              itemStyle: {
+                color: (params) => {
+                  if (params.dataIndex >= 7) {
+                    return '#ffd93d'
+                  }
+                  return '#62f6fb'
+                }
               },
-              emphasis: {
-                label: {
-                  show: true,
-                  fontSize: 12,
-                  fontWeight: 'bold',
-                  color: '#e0fcff'
+              lineStyle: {
+                color: '#62f6fb',
+                width: 2,
+                type: (params) => {
+                  return params.dataIndex >= 7 ? 'dashed' : 'solid'
                 }
               },
-              labelLine: {
-                show: true,
-                lineStyle: {
-                  color: '#7bbef6'
-                },
-                length: 10,
-                length2: 15
+              symbol: 'circle',
+              symbolSize: 4
+            },
+            {
+              name: '-20cm',
+              type: 'line',
+              data: dates.map((date, index) => {
+                if (index < 7) {
+                  return historical.layer20[index]
+                } else if (index >= 7) {
+                  return forecast.layer20[index - 7]
+                }
+                return null
+              }),
+              smooth: true,
+              itemStyle: {
+                color: (params) => {
+                  if (params.dataIndex >= 7) {
+                    return '#ffd93d'
+                  }
+                  return '#38bdf8'
+                }
+              },
+              lineStyle: {
+                color: '#38bdf8',
+                width: 2,
+                type: (params) => {
+                  return params.dataIndex >= 7 ? 'dashed' : 'solid'
+                }
+              },
+              symbol: 'circle',
+              symbolSize: 4
+            },
+            {
+              name: '-40cm',
+              type: 'line',
+              data: dates.map((date, index) => {
+                if (index < 7) {
+                  return historical.layer40[index]
+                } else if (index >= 7) {
+                  return forecast.layer40[index - 7]
+                }
+                return null
+              }),
+              smooth: true,
+              itemStyle: {
+                color: (params) => {
+                  if (params.dataIndex >= 7) {
+                    return '#ffd93d'
+                  }
+                  return '#22c55e'
+                }
+              },
+              lineStyle: {
+                color: '#22c55e',
+                width: 2,
+                type: 'solid'
               },
-              data: [
-                { value: 45.8, name: '农业灌溉', itemStyle: { color: '#62f6fb' } },
-                { value: 12.3, name: '居民用水', itemStyle: { color: '#38bdf8' } }
-              ]
+              symbol: 'circle',
+              symbolSize: 4
             }
           ]
         }
@@ -539,10 +787,10 @@ export default {
         animation: false,
         tooltip: {
           trigger: 'axis',
-          formatter: '{b}<br/>{a0}: {c0}万m³<br/>{a1}: {c1}万m³<br/>{a2}: {c2}万m³<br/>{a3}: {c3}万m³'
+          formatter: '{b}<br/>{a0}: {c0}万m³<br/>{a1}: {c1}万m³<br/>{a2}: {c2}万m³<br/>{a3}: {c3}万m³<br/>{a4}: {c4}万m³'
         },
         legend: {
-          data: ['农业灌溉', '居民用水', '黑林水文站来水', '小塔山水库供水'],
+          data: ['农业灌溉', '居民用水', '蒸发量', '黑林水文站来水', '小塔山水库供水'],
           textStyle: {
             color: '#e0fcff',
             fontSize: 11
@@ -620,6 +868,15 @@ export default {
               color: '#a78bfa'
             }
           },
+          {
+            name: '蒸发量',
+            type: 'bar',
+            stack: 'total',
+            data: this.demandTrendData.evaporation,
+            itemStyle: {
+              color: '#fbbf24'
+            }
+          },
           {
             name: '黑林水文站来水',
             type: 'line',
@@ -808,6 +1065,138 @@ export default {
         ]
       }
       this.demandComparisonChart.setOption(option)
+    },
+    initAnomalyChart() {
+      if (document.getElementById('anomalyChart')) {
+        if (this.anomalyChart) {
+          this.anomalyChart.dispose()
+        }
+        this.anomalyChart = echarts.init(document.getElementById('anomalyChart'))
+        
+        const { months, currentYearCumulative, multiYearAverageCumulative } = this.anomalyData
+        
+        const option = {
+          animation: false,
+          tooltip: {
+            trigger: 'axis',
+            axisPointer: {
+              type: 'line'
+            },
+            formatter: (params) => {
+              let result = `${params[0].name}<br/>`
+              params.forEach((param) => {
+                const isForecast = param.dataIndex >= 5
+                const diff = param.data - (param.seriesName === '今年累计' ? multiYearAverageCumulative[param.dataIndex] : currentYearCumulative[param.dataIndex])
+                const diffPercent = ((diff / (param.seriesName === '今年累计' ? multiYearAverageCumulative[param.dataIndex] : currentYearCumulative[param.dataIndex])) * 100).toFixed(1)
+                const sign = diff >= 0 ? '+' : ''
+                const label = isForecast && param.seriesName === '今年累计' ? '(预报)' : ''
+                result += `${param.seriesName}:${param.data}万m³${label} (${sign}${diff}万m³, ${sign}${diffPercent}%)<br/>`
+              })
+              return result
+            }
+          },
+          legend: {
+            data: ['今年累计', '多年同期平均累计'],
+            textStyle: {
+              color: '#ffffff',
+              fontSize: 11
+            },
+            itemWidth: 12,
+            itemHeight: 12,
+            itemGap: 8,
+            bottom: '0%'
+          },
+          grid: {
+            left: 0,
+            right: 55,
+            bottom: 45,
+            top: 25,
+            containLabel: true
+          },
+          xAxis: {
+            type: 'category',
+            data: months,
+            axisLine: {
+              lineStyle: {
+                color: '#7bbef6'
+              }
+            },
+            axisLabel: {
+              color: '#ffffff',
+              fontSize: 10,
+              interval: 0,
+              rotate: 0
+            }
+          },
+          yAxis: {
+            type: 'value',
+            name: '累计水量(万m³)',
+            nameLocation: 'end',
+            nameGap: 5,
+            nameTextStyle: {
+              color: '#ffffff',
+              fontSize: 11,
+              align: 'left',
+              verticalAlign: 'bottom',
+              padding: [0, 0, 0, -15]
+            },
+            axisLine: {
+              lineStyle: {
+                color: '#7bbef6'
+              }
+            },
+            axisLabel: {
+              color: '#ffffff',
+              fontSize: 10,
+              formatter: (value) => {
+                return value > 0 ? `+${value}` : value
+              }
+            },
+            splitLine: {
+              lineStyle: {
+                color: 'rgba(123, 190, 246, 0.2)'
+              }
+            }
+          },
+          series: [
+            {
+              name: '今年累计',
+              type: 'line',
+              data: currentYearCumulative,
+              smooth: true,
+              itemStyle: {
+                color: (params) => {
+                  return params.dataIndex >= 5 ? '#ffd93d' : '#62f6fb'
+                }
+              },
+              lineStyle: {
+                color: (params) => {
+                  return params.dataIndex >= 5 ? '#ffd93d' : '#62f6fb'
+                },
+                width: 2
+              },
+              symbol: 'circle',
+              symbolSize: 6
+            },
+            {
+              name: '多年同期平均累计',
+              type: 'line',
+              data: multiYearAverageCumulative,
+              smooth: true,
+              itemStyle: {
+                color: '#a78bfa'
+              },
+              lineStyle: {
+                width: 2,
+                type: 'dashed'
+              },
+              symbol: 'circle',
+              symbolSize: 6
+            }
+          ]
+        }
+        this.anomalyChart.setOption(option)
+      }
     }
   }
 }
@@ -893,18 +1282,44 @@ export default {
 
 .basic-data-content {
   display: flex;
-  flex-direction: column;
+  flex-direction: row;
   gap: 10px;
 }
 
 .data-item {
+  flex: 1;
   display: flex;
-  justify-content: space-between;
+  flex-direction: column;
+  justify-content: center;
   align-items: center;
-  padding: 8px 12px;
+  padding: 15px 10px;
   background: rgba(0, 20, 40, 0.5);
   border-radius: 4px;
   border: 1px solid rgba(0, 212, 255, 0.2);
+  min-height: 80px;
+}
+
+.data-item.abundant {
+  border-color: #4ade80;
+  box-shadow: 0 0 15px rgba(74, 222, 128, 0.6), 0 0 30px rgba(74, 222, 128, 0.3);
+}
+
+.data-item.dry {
+  border-color: #ff6b6b;
+  box-shadow: 0 0 15px rgba(255, 107, 107, 0.6), 0 0 30px rgba(255, 107, 107, 0.3);
+}
+
+.data-item.normal {
+  border-color: #9ca3af;
+  box-shadow: 0 0 15px rgba(156, 163, 175, 0.6), 0 0 30px rgba(156, 163, 175, 0.3);
+}
+
+.data-item .data-label {
+  margin-bottom: 8px;
+}
+
+.data-item .data-value {
+  font-size: 16px;
 }
 
 .data-label {
@@ -918,6 +1333,14 @@ export default {
   font-weight: bold;
 }
 
+.data-value.positive {
+  color: #4ade80;
+}
+
+.data-value.negative {
+  color: #ff6b6b;
+}
+
 .reservoir-list {
   display: flex;
   flex-direction: column;