spring
2025-08-13 c2f399f2c085a1ce803059c2e8c6399b6d077dd2
完成能源驾驶舱
已添加1个文件
1380 ■■■■■ 文件已修改
src/views/energyManagement/energyCockpit/index.vue 1380 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/energyManagement/energyCockpit/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1380 @@
<template>
  <div class="app-container">
    <!-- é¡µé¢æ ‡é¢˜ -->
    <div class="page-header">
      <h2>能源驾驶舱</h2>
      <div class="header-info">
        <span class="update-time">最后更新:{{ lastUpdateTime }}</span>
        <el-button type="primary" size="small" @click="refreshData">
          <el-icon><Refresh /></el-icon>
          åˆ·æ–°æ•°æ®
        </el-button>
      </div>
    </div>
    <!-- å®žæ—¶èƒ½è€—监控 -->
    <div class="real-time-monitor">
      <el-row :gutter="20">
        <el-col :span="8">
          <el-card class="monitor-card">
            <template #header>
              <div class="card-header">
                <span>电力消耗</span>
                <el-tag type="success" size="small">实时</el-tag>
              </div>
            </template>
            <div class="monitor-content">
              <div class="monitor-value">
                <span class="value">{{ electricityConsumption }}</span>
                <span class="unit">kW·h</span>
              </div>
              <div class="monitor-trend">
                <span class="trend-label">趋势:</span>
                <el-tag :type="getTrendType(electricityTrend)" size="small">
                  {{ electricityTrend > 0 ? '↑' : '↓' }} {{ Math.abs(electricityTrend) }}%
                </el-tag>
              </div>
            </div>
          </el-card>
        </el-col>
        <el-col :span="8">
          <el-card class="monitor-card">
            <template #header>
              <div class="card-header">
                <span>水消耗</span>
                <el-tag type="primary" size="small">实时</el-tag>
              </div>
            </template>
            <div class="monitor-content">
              <div class="monitor-value">
                <span class="value">{{ waterConsumption }}</span>
                <span class="unit">m³</span>
              </div>
              <div class="monitor-trend">
                <span class="trend-label">趋势:</span>
                <el-tag :type="getTrendType(waterTrend)" size="small">
                  {{ waterTrend > 0 ? '↑' : '↓' }} {{ Math.abs(waterTrend) }}%
                </el-tag>
              </div>
            </div>
          </el-card>
        </el-col>
        <el-col :span="8">
          <el-card class="monitor-card">
            <template #header>
              <div class="card-header">
                <span>气体消耗</span>
                <el-tag type="warning" size="small">实时</el-tag>
              </div>
            </template>
            <div class="monitor-content">
              <div class="monitor-value">
                <span class="value">{{ gasConsumption }}</span>
                <span class="unit">m³</span>
              </div>
              <div class="monitor-trend">
                <span class="trend-label">趋势:</span>
                <el-tag :type="getTrendType(gasTrend)" size="small">
                  {{ gasTrend > 0 ? '↑' : '↓' }} {{ Math.abs(gasTrend) }}%
                </el-tag>
              </div>
            </div>
          </el-card>
        </el-col>
      </el-row>
    </div>
    <!-- èƒ½è€—趋势分析 -->
    <div class="trend-analysis">
      <el-card>
        <template #header>
          <div class="card-header">
            <span>能耗趋势分析</span>
            <div class="time-selector">
              <el-radio-group v-model="trendTimeUnit" @change="handleTrendTimeChange">
                <el-radio value="hour">小时</el-radio>
                <el-radio value="day">日</el-radio>
                <el-radio value="week">周</el-radio>
                <el-radio value="month">月</el-radio>
                <el-radio value="year">å¹´</el-radio>
              </el-radio-group>
            </div>
          </div>
        </template>
        <div class="chart-container">
          <div ref="trendChart" style="width: 100%; height: 400px;"></div>
        </div>
      </el-card>
    </div>
    <!-- èƒ½è€—统计与排名 -->
    <div class="statistics-ranking">
      <el-row :gutter="20">
        <el-col :span="12">
          <el-card class="statistics-card">
            <template #header>
              <div class="card-header">
                <span class="card-title">能耗统计报表</span>
                <div class="header-actions">
                  <el-select v-model="statisticsPeriod" @change="handleStatisticsChange" size="small" style="width: 100px;">
                    <el-option label="日统计" value="day" />
                    <el-option label="周统计" value="week" />
                    <el-option label="月统计" value="month" />
                    <el-option label="年统计" value="year" />
                  </el-select>
                </div>
              </div>
            </template>
            <div class="statistics-content">
              <div class="statistics-item">
                <span class="label">总能耗:</span>
                <span class="value">{{ totalEnergyConsumption }} kW·h</span>
              </div>
              <div class="statistics-item">
                <span class="label">同比:</span>
                <span class="value" :class="getComparisonClass(yearOverYear)">
                  {{ yearOverYear > 0 ? '+' : '' }}{{ yearOverYear }}%
                </span>
              </div>
              <div class="statistics-item">
                <span class="label">环比:</span>
                <span class="value" :class="getComparisonClass(monthOverMonth)">
                  {{ monthOverMonth > 0 ? '+' : '' }}{{ monthOverMonth }}%
                </span>
              </div>
              <div class="statistics-item">
                <span class="label">节能率:</span>
                <span class="value success">{{ energySavingRate }}%</span>
              </div>
            </div>
          </el-card>
        </el-col>
        <el-col :span="12">
          <el-card class="ranking-card">
            <template #header>
              <div class="card-header">
                <span class="card-title">能耗排名</span>
                <el-select v-model="rankingType" @change="handleRankingChange" size="small" style="width: 120px;">
                  <el-option label="部门排名" value="department" />
                  <el-option label="车间排名" value="workshop" />
                  <el-option label="设备排名" value="equipment" />
                </el-select>
              </div>
            </template>
            <div class="ranking-list">
              <div v-for="(item, index) in rankingList" :key="index" class="ranking-item">
                <div class="ranking-number" :class="getRankingClass(index + 1)">{{ index + 1 }}</div>
                <div class="ranking-info">
                  <div class="ranking-name">{{ item.name }}</div>
                  <div class="ranking-value">{{ item.value }} kW·h</div>
                </div>
                <div class="ranking-trend">
                  <el-tag :type="getTrendType(item.trend)" size="small">
                    {{ item.trend > 0 ? '↑' : '↓' }} {{ Math.abs(item.trend) }}%
                  </el-tag>
                </div>
              </div>
            </div>
          </el-card>
        </el-col>
      </el-row>
    </div>
    <!-- å¼‚常分析与智能控制 -->
    <div class="analysis-control">
      <el-row :gutter="20">
        <el-col :span="12">
          <el-card class="abnormal-card">
            <template #header>
              <div class="card-header">
                <span class="card-title">异常分析</span>
                <el-tag type="danger" size="small">{{ abnormalCount }}个异常</el-tag>
              </div>
            </template>
            <div class="abnormal-list">
              <div v-for="(item, index) in abnormalList" :key="index" class="abnormal-item">
                <div class="abnormal-icon">
                  <el-icon :color="getAbnormalColor(item.level)">
                    <Warning v-if="item.level === 'warning'" />
                    <CircleClose v-else />
                  </el-icon>
                </div>
                <div class="abnormal-content">
                  <div class="abnormal-title">{{ item.title }}</div>
                  <div class="abnormal-desc">{{ item.description }}</div>
                  <div class="abnormal-time">{{ item.time }}</div>
                </div>
                <div class="abnormal-action">
                  <el-button link size="small" @click="handleAbnormal(item)">处理</el-button>
                </div>
              </div>
            </div>
          </el-card>
        </el-col>
        <el-col :span="12">
          <el-card class="control-card">
            <template #header>
              <div class="card-header">
                <span class="card-title">智能控制系统</span>
                <el-switch v-model="autoControlEnabled" @change="handleAutoControlChange" />
              </div>
            </template>
            <div class="control-content">
              <div class="control-item">
                <span class="label">峰谷平电价管理:</span>
                <el-tag :type="getPriceType(currentPriceType)" size="small">
                  {{ getPriceTypeText(currentPriceType) }}
                </el-tag>
              </div>
              <div class="control-item">
                <span class="label">负荷预测:</span>
                <span class="value">{{ loadForecast }} kW</span>
              </div>
              <div class="control-item">
                <span class="label">自动启停:</span>
                <el-tag :type="autoStartStop ? 'success' : 'info'" size="small">
                  {{ autoStartStop ? '已启用' : '已禁用' }}
                </el-tag>
              </div>
              <div class="control-item">
                <span class="label">智能调节:</span>
                <el-progress :percentage="intelligentAdjustment" :color="getProgressColor" />
              </div>
            </div>
          </el-card>
        </el-col>
      </el-row>
    </div>
    <!-- çŽ¯ä¿æŒ‡æ ‡ -->
    <div class="environmental-indicators">
      <el-card>
        <template #header>
          <div class="card-header">
            <span>环保指标监控</span>
          </div>
        </template>
        <el-row :gutter="20">
          <el-col :span="8">
            <div class="indicator-item">
              <div class="indicator-title">碳排放量</div>
              <div class="indicator-value">{{ carbonEmission }} kg</div>
              <div class="indicator-trend">
                <span>同比:</span>
                <span :class="getComparisonClass(carbonEmissionTrend)">
                  {{ carbonEmissionTrend > 0 ? '+' : '' }}{{ carbonEmissionTrend }}%
                </span>
              </div>
            </div>
          </el-col>
          <el-col :span="8">
            <div class="indicator-item">
              <div class="indicator-title">环保达标率</div>
              <div class="indicator-value">{{ environmentalCompliance }}%</div>
              <div class="indicator-trend">
                <span>目标:</span>
                <span class="success">95%</span>
              </div>
            </div>
          </el-col>
          <el-col :span="8">
            <div class="indicator-item">
              <div class="indicator-title">绿色能源占比</div>
              <div class="indicator-value">{{ greenEnergyRatio }}%</div>
              <div class="indicator-trend">
                <span>目标:</span>
                <span class="success">30%</span>
              </div>
            </div>
          </el-col>
        </el-row>
      </el-card>
    </div>
    <!-- å¤šç»´åº¦æŠ¥è¡¨ -->
    <div class="multi-dimensional-reports">
      <el-card>
        <template #header>
          <div class="card-header">
            <span>多维度报表</span>
          </div>
        </template>
        <div class="report-filters">
          <el-row :gutter="20">
            <el-col :span="6">
              <el-form-item label="时间维度">
                <el-select v-model="reportTimeDimension" placeholder="选择时间维度">
                  <el-option label="小时" value="hour" />
                  <el-option label="日" value="day" />
                  <el-option label="周" value="week" />
                  <el-option label="月" value="month" />
                  <el-option label="å¹´" value="year" />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="6">
              <el-form-item label="部门维度">
                <el-select v-model="reportDepartmentDimension" placeholder="选择部门">
                  <el-option label="全部部门" value="all" />
                  <el-option label="生产部" value="production" />
                  <el-option label="技术部" value="technology" />
                  <el-option label="行政部" value="administration" />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="6">
              <el-form-item label="设备维度">
                <el-select v-model="reportEquipmentDimension" placeholder="选择设备类型">
                  <el-option label="全部设备" value="all" />
                  <el-option label="电力设备" value="electricity" />
                  <el-option label="水处理设备" value="water" />
                  <el-option label="气体设备" value="gas" />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="6">
              <el-form-item>
                <el-button type="primary" @click="generateReport">生成报表</el-button>
              </el-form-item>
            </el-col>
          </el-row>
        </div>
        <div class="report-preview">
          <div class="report-data">
            <el-row :gutter="20">
              <el-col :span="8">
                <div class="data-card">
                  <div class="data-title">电力消耗</div>
                  <div class="data-value">{{ reportData.electricity }} kW·h</div>
                  <div class="data-trend">
                    <span :class="getTrendClass(reportData.electricityTrend)">
                      {{ reportData.electricityTrend > 0 ? '↑' : '↓' }} {{ Math.abs(reportData.electricityTrend) }}%
                    </span>
                  </div>
                </div>
              </el-col>
              <el-col :span="8">
                <div class="data-card">
                  <div class="data-title">水消耗</div>
                  <div class="data-value">{{ reportData.water }} m³</div>
                  <div class="data-trend">
                    <span :class="getTrendClass(reportData.waterTrend)">
                      {{ reportData.waterTrend > 0 ? '↑' : '↓' }} {{ Math.abs(reportData.waterTrend) }}%
                    </span>
                  </div>
                </div>
              </el-col>
              <el-col :span="8">
                <div class="data-card">
                  <div class="data-title">气体消耗</div>
                  <div class="data-value">{{ reportData.gas }} m³</div>
                  <div class="data-trend">
                    <span :class="getTrendClass(reportData.gasTrend)">
                      {{ reportData.gasTrend > 0 ? '↑' : '↓' }} {{ Math.abs(reportData.gasTrend) }}%
                    </span>
                  </div>
                </div>
              </el-col>
            </el-row>
            <div class="report-chart">
              <div class="chart-title">能耗趋势图</div>
              <div class="chart-bars">
                <div v-for="(item, index) in reportData.chartData" :key="index" class="chart-bar">
                  <div class="bar-label">{{ item.label }}</div>
                  <div class="bar-container">
                    <div class="bar-fill" :style="{ height: item.percentage + '%', backgroundColor: item.color }"></div>
                  </div>
                  <div class="bar-value">{{ item.value }}</div>
                </div>
              </div>
            </div>
            <div class="report-summary">
              <div class="summary-item">
                <span class="summary-label">总能耗:</span>
                <span class="summary-value">{{ reportData.totalEnergy }} kW·h</span>
              </div>
              <div class="summary-item">
                <span class="summary-label">平均能耗:</span>
                <span class="summary-value">{{ reportData.averageEnergy }} kW·h</span>
              </div>
              <div class="summary-item">
                <span class="summary-label">能耗效率:</span>
                <span class="summary-value">{{ reportData.efficiency }}%</span>
              </div>
            </div>
          </div>
        </div>
      </el-card>
    </div>
  </div>
</template>
<script setup>
import { ref, reactive, onMounted, onUnmounted, nextTick } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import * as echarts from 'echarts'
import {
  Refresh,
  Download,
  Warning,
  CircleClose,
  Document,
  Edit,
  Bell
} from '@element-plus/icons-vue'
// å“åº”式数据
const lastUpdateTime = ref('')
const electricityConsumption = ref(0)
const waterConsumption = ref(0)
const gasConsumption = ref(0)
const electricityTrend = ref(0)
const waterTrend = ref(0)
const gasTrend = ref(0)
// è¶‹åŠ¿åˆ†æž
const trendTimeUnit = ref('day')
const trendChart = ref(null)
let chartInstance = null
// ç»Ÿè®¡æŠ¥è¡¨
const statisticsPeriod = ref('month')
const totalEnergyConsumption = ref(0)
const yearOverYear = ref(0)
const monthOverMonth = ref(0)
const energySavingRate = ref(0)
// èƒ½è€—排名
const rankingType = ref('department')
const rankingList = ref([])
// å¼‚常分析
const abnormalCount = ref(0)
const abnormalList = ref([])
// æ™ºèƒ½æŽ§åˆ¶
const autoControlEnabled = ref(true)
const currentPriceType = ref('peak')
const loadForecast = ref(0)
const autoStartStop = ref(true)
const intelligentAdjustment = ref(0)
// çŽ¯ä¿æŒ‡æ ‡
const carbonEmission = ref(0)
const carbonEmissionTrend = ref(0)
const environmentalCompliance = ref(0)
const greenEnergyRatio = ref(0)
// å¤šç»´åº¦æŠ¥è¡¨
const reportTimeDimension = ref('month')
const reportDepartmentDimension = ref('all')
const reportEquipmentDimension = ref('all')
const reportData = ref({
  electricity: 0,
  water: 0,
  gas: 0,
  electricityTrend: 0,
  waterTrend: 0,
  gasTrend: 0,
  totalEnergy: 0,
  averageEnergy: 0,
  efficiency: 0,
  chartData: []
})
// å®šæ—¶å™¨
let updateTimer = null
// èŽ·å–è¶‹åŠ¿ç±»åž‹æ ·å¼
const getTrendType = (trend) => {
  if (trend > 0) return 'danger'
  if (trend < 0) return 'success'
  return 'info'
}
// èŽ·å–å¯¹æ¯”ç±»åž‹æ ·å¼
const getComparisonClass = (value) => {
  if (value > 0) return 'danger'
  if (value < 0) return 'success'
  return 'info'
}
// èŽ·å–æŽ’åæ ·å¼
const getRankingClass = (rank) => {
  if (rank === 1) return 'ranking-first'
  if (rank === 2) return 'ranking-second'
  if (rank === 3) return 'ranking-third'
  return 'ranking-normal'
}
// èŽ·å–å¼‚å¸¸é¢œè‰²
const getAbnormalColor = (level) => {
  return level === 'warning' ? '#E6A23C' : '#F56C6C'
}
// èŽ·å–ç”µä»·ç±»åž‹æ ·å¼
const getPriceType = (type) => {
  const typeMap = {
    peak: 'danger',
    normal: 'warning',
    valley: 'success'
  }
  return typeMap[type] || 'info'
}
// èŽ·å–ç”µä»·ç±»åž‹æ–‡æœ¬
const getPriceTypeText = (type) => {
  const typeMap = {
    peak: '峰时',
    normal: '平时',
    valley: '谷时'
  }
  return typeMap[type] || '未知'
}
// èŽ·å–è¿›åº¦æ¡é¢œè‰²
const getProgressColor = (percentage) => {
  if (percentage < 50) return '#67C23A'
  if (percentage < 80) return '#E6A23C'
  return '#F56C6C'
}
// èŽ·å–è¶‹åŠ¿æ ·å¼
const getTrendClass = (trend) => {
  if (trend > 0) return 'trend-up'
  if (trend < 0) return 'trend-down'
  return 'trend-stable'
}
// æ¨¡æ‹Ÿæ•°æ®ç”Ÿæˆ
const generateMockData = () => {
  // å®žæ—¶èƒ½è€—数据
  electricityConsumption.value = Math.floor(Math.random() * 1000) + 2000
  waterConsumption.value = Math.floor(Math.random() * 100) + 150
  gasConsumption.value = Math.floor(Math.random() * 50) + 80
  // è¶‹åŠ¿æ•°æ®
  electricityTrend.value = (Math.random() * 20 - 10).toFixed(1)
  waterTrend.value = (Math.random() * 15 - 7.5).toFixed(1)
  gasTrend.value = (Math.random() * 12 - 6).toFixed(1)
  // ç»Ÿè®¡æ•°æ®
  totalEnergyConsumption.value = Math.floor(Math.random() * 50000) + 100000
  yearOverYear.value = (Math.random() * 20 - 10).toFixed(1)
  monthOverMonth.value = (Math.random() * 15 - 7.5).toFixed(1)
  energySavingRate.value = (Math.random() * 10 + 5).toFixed(1)
  // æŽ’名数据
  rankingList.value = [
    { name: '生产车间A', value: Math.floor(Math.random() * 5000) + 10000, trend: (Math.random() * 20 - 10).toFixed(1) },
    { name: '生产车间B', value: Math.floor(Math.random() * 4000) + 8000, trend: (Math.random() * 20 - 10).toFixed(1) },
    { name: '技术研发部', value: Math.floor(Math.random() * 3000) + 6000, trend: (Math.random() * 20 - 10).toFixed(1) },
    { name: '行政办公区', value: Math.floor(Math.random() * 2000) + 4000, trend: (Math.random() * 20 - 10).toFixed(1) },
    { name: '后勤保障区', value: Math.floor(Math.random() * 1500) + 3000, trend: (Math.random() * 20 - 10).toFixed(1) }
  ].sort((a, b) => b.value - a.value)
  // å¼‚常数据
  abnormalCount.value = Math.floor(Math.random() * 5) + 1
  abnormalList.value = [
    { level: 'warning', title: '电力负荷过高', description: '生产车间A电力负荷达到85%,建议检查设备运行状态', time: '2分钟前' },
    { level: 'error', title: '水压异常', description: '水处理设备压力异常,当前压力0.3MPa,低于正常范围', time: '5分钟前' }
  ]
  // æ™ºèƒ½æŽ§åˆ¶æ•°æ®
  loadForecast.value = Math.floor(Math.random() * 500) + 1500
  intelligentAdjustment.value = Math.floor(Math.random() * 30) + 60
  // çŽ¯ä¿æŒ‡æ ‡
  carbonEmission.value = Math.floor(Math.random() * 1000) + 5000
  carbonEmissionTrend.value = (Math.random() * 15 - 7.5).toFixed(1)
  environmentalCompliance.value = (Math.random() * 5 + 95).toFixed(1)
  greenEnergyRatio.value = (Math.random() * 10 + 25).toFixed(1)
  // æ›´æ–°æœ€åŽæ›´æ–°æ—¶é—´
  lastUpdateTime.value = new Date().toLocaleString()
  // åŒæ—¶æ›´æ–°æŠ¥è¡¨æ•°æ®
  generateReportData()
}
// åˆå§‹åŒ–趋势图表
const initTrendChart = () => {
  if (chartInstance) {
    chartInstance.dispose()
  }
  chartInstance = echarts.init(trendChart.value)
  const option = {
    title: {
      text: '能耗趋势分析',
      left: 'center'
    },
    tooltip: {
      trigger: 'axis'
    },
    legend: {
      data: ['电力', 'æ°´', '气体'],
      bottom: 10
    },
    xAxis: {
      type: 'category',
      data: generateTimeData()
    },
    yAxis: {
      type: 'value',
      name: '消耗量'
    },
    series: [
      {
        name: '电力',
        type: 'line',
        data: generateSeriesData(),
        smooth: true
      },
      {
        name: 'æ°´',
        type: 'line',
        data: generateSeriesData(),
        smooth: true
      },
      {
        name: '气体',
        type: 'line',
        data: generateSeriesData(),
        smooth: true
      }
    ]
  }
  chartInstance.setOption(option)
}
// ç”Ÿæˆæ—¶é—´æ•°æ®
const generateTimeData = () => {
  const data = []
  const now = new Date()
  switch (trendTimeUnit.value) {
    case 'hour':
      for (let i = 23; i >= 0; i--) {
        const time = new Date(now.getTime() - i * 60 * 60 * 1000)
        data.unshift(time.getHours() + ':00')
      }
      break
    case 'day':
      for (let i = 29; i >= 0; i--) {
        const time = new Date(now.getTime() - i * 24 * 60 * 60 * 1000)
        data.unshift(time.getDate() + '日')
      }
      break
    case 'week':
      for (let i = 11; i >= 0; i--) {
        data.unshift(`第${12 - i}周`)
      }
      break
    case 'month':
      for (let i = 11; i >= 0; i--) {
        const month = (12 - i) % 12 || 12
        data.unshift(`${month}月`)
      }
      break
    case 'year':
      for (let i = 4; i >= 0; i--) {
        const year = new Date().getFullYear() - i
        data.unshift(`${year}å¹´`)
      }
      break
  }
  return data
}
// ç”Ÿæˆç³»åˆ—数据
const generateSeriesData = () => {
  const data = []
  const count = trendTimeUnit.value === 'hour' ? 24 :
                trendTimeUnit.value === 'day' ? 30 :
                trendTimeUnit.value === 'week' ? 12 :
                trendTimeUnit.value === 'month' ? 12 : 5
  for (let i = 0; i < count; i++) {
    data.push(Math.floor(Math.random() * 1000) + 500)
  }
  return data
}
// å¤„理趋势时间变化
const handleTrendTimeChange = () => {
  nextTick(() => {
    initTrendChart()
  })
}
// å¤„理统计周期变化
const handleStatisticsChange = () => {
  generateMockData()
}
// å¤„理排名类型变化
const handleRankingChange = () => {
  // æ ¹æ®ç±»åž‹é‡æ–°ç”ŸæˆæŽ’名数据
  generateMockData()
}
// å¤„理自动控制变化
const handleAutoControlChange = (value) => {
  ElMessage.success(`智能控制系统已${value ? '启用' : '禁用'}`)
}
// å¤„理异常
const handleAbnormal = (item) => {
  ElMessage.info(`正在处理异常:${item.title}`)
}
// åˆ·æ–°æ•°æ®
const refreshData = () => {
  generateMockData()
  if (chartInstance) {
    initTrendChart()
  }
  ElMessage.success('数据已刷新')
}
// å¯¼å‡ºç»Ÿè®¡
const exportStatistics = () => {
  ElMessage.success('统计数据导出成功')
}
// å¯¼å‡ºçŽ¯ä¿æŠ¥å‘Š
const exportEnvironmentalReport = () => {
  ElMessage.success('环保报告导出成功')
}
// ç”Ÿæˆè‡ªå®šä¹‰æŠ¥è¡¨
const generateCustomReport = () => {
  ElMessage.info('自定义报表功能开发中...')
}
// è®¢é˜…报表
const subscribeReport = () => {
  ElMessage.info('报表订阅功能开发中...')
}
// ç”ŸæˆæŠ¥è¡¨æ•°æ®
const generateReportData = () => {
  // ç”ŸæˆåŸºç¡€æ•°æ®
  reportData.value.electricity = Math.floor(Math.random() * 5000) + 8000
  reportData.value.water = Math.floor(Math.random() * 200) + 300
  reportData.value.gas = Math.floor(Math.random() * 100) + 150
  // ç”Ÿæˆè¶‹åŠ¿æ•°æ®
  reportData.value.electricityTrend = (Math.random() * 20 - 10).toFixed(1)
  reportData.value.waterTrend = (Math.random() * 15 - 7.5).toFixed(1)
  reportData.value.gasTrend = (Math.random() * 12 - 6).toFixed(1)
  // è®¡ç®—总能耗和平均能耗
  reportData.value.totalEnergy = reportData.value.electricity + reportData.value.water * 0.1 + reportData.value.gas * 0.05
  reportData.value.averageEnergy = Math.floor(reportData.value.totalEnergy / 3)
  reportData.value.efficiency = (Math.random() * 20 + 80).toFixed(1)
  // ç”Ÿæˆå›¾è¡¨æ•°æ®
  const labels = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
  const colors = ['#409eff', '#67c23a', '#e6a23c', '#f56c6c', '#909399', '#9c27b0', '#ff9800']
  reportData.value.chartData = labels.map((label, index) => ({
    label,
    value: Math.floor(Math.random() * 1000) + 500,
    percentage: Math.floor(Math.random() * 40) + 30,
    color: colors[index]
  }))
}
// ç”ŸæˆæŠ¥è¡¨
const generateReport = () => {
  generateReportData()
  ElMessage.success('报表生成成功')
}
// å¯åŠ¨å®šæ—¶æ›´æ–°
const startAutoUpdate = () => {
  updateTimer = setInterval(() => {
    generateMockData()
    if (chartInstance) {
      initTrendChart()
    }
  }, 60000) // æ¯åˆ†é’Ÿæ›´æ–°ä¸€æ¬¡
}
// åœæ­¢å®šæ—¶æ›´æ–°
const stopAutoUpdate = () => {
  if (updateTimer) {
    clearInterval(updateTimer)
    updateTimer = null
  }
}
// ç»„件挂载
onMounted(() => {
  generateMockData()
  nextTick(() => {
    initTrendChart()
  })
  startAutoUpdate()
})
// ç»„件卸载
onUnmounted(() => {
  stopAutoUpdate()
  if (chartInstance) {
    chartInstance.dispose()
  }
})
</script>
<style lang="scss" scoped>
.app-container {
  padding: 12px;
  background: #f5f5f5;
  min-height: 100vh;
}
.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  padding: 16px;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  h2 {
    margin: 0;
    color: #303133;
    font-size: 22px;
  }
  .header-info {
    display: flex;
    align-items: center;
    gap: 12px;
    .update-time {
      color: #909399;
      font-size: 14px;
    }
  }
}
.real-time-monitor {
  margin-bottom: 12px;
  .monitor-card {
    .monitor-content {
      text-align: center;
      padding: 16px 0;
      .monitor-value {
        margin-bottom: 12px;
        .value {
          font-size: 28px;
          font-weight: bold;
          color: #409eff;
        }
        .unit {
          font-size: 14px;
          color: #909399;
          margin-left: 4px;
        }
      }
      .monitor-trend {
        .trend-label {
          font-size: 14px;
          color: #606266;
          margin-right: 6px;
        }
      }
    }
  }
}
.trend-analysis {
  margin-bottom: 12px;
  .card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    .time-selector {
      .el-radio-group {
        .el-radio {
          margin-right: 4px;
        }
      }
    }
  }
  .chart-container {
    padding: 16px 0;
  }
}
.statistics-ranking {
  margin-bottom: 12px;
  .statistics-card, .ranking-card {
    height: 100%;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
    border-radius: 8px;
    transition: all 0.3s ease;
    &:hover {
      transform: translateY(-2px);
      box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
    }
  }
  .card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 12px 16px;
    border-bottom: 1px solid #f0f0f0;
    background: #fafafa;
    .card-title {
      font-size: 15px;
      font-weight: 600;
      color: #303133;
    }
    .header-actions {
      display: flex;
      gap: 8px;
      align-items: center;
    }
  }
  .statistics-content {
    padding: 16px;
    .statistics-item {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 12px;
      padding: 10px 12px;
      background: #f8f9fa;
      border-radius: 6px;
      transition: background-color 0.3s ease;
      &:hover {
        background: #e9ecef;
      }
      &:last-child {
        margin-bottom: 0;
      }
      .label {
        color: #606266;
        font-size: 14px;
        font-weight: 500;
      }
      .value {
        font-weight: bold;
        font-size: 15px;
        &.success {
          color: #67c23a;
        }
      }
    }
  }
  .ranking-list {
    padding: 16px;
    .ranking-item {
      display: flex;
      align-items: center;
      padding: 12px;
      margin-bottom: 6px;
      background: #f8f9fa;
      border-radius: 6px;
      transition: all 0.3s ease;
      &:hover {
        background: #e9ecef;
        transform: translateX(4px);
      }
      &:last-child {
        margin-bottom: 0;
      }
      .ranking-number {
        width: 32px;
        height: 32px;
        border-radius: 50%;
        display: flex;
        align-items: center;
        justify-content: center;
        font-weight: bold;
        font-size: 14px;
        margin-right: 12px;
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
        &.ranking-first {
          background: linear-gradient(135deg, #ffd700 0%, #ffed4e 100%);
          color: #fff;
        }
        &.ranking-second {
          background: linear-gradient(135deg, #c0c0c0 0%, #d4d4d4 100%);
          color: #fff;
        }
        &.ranking-third {
          background: linear-gradient(135deg, #cd7f32 0%, #daa520 100%);
          color: #fff;
        }
        &.ranking-normal {
          background: linear-gradient(135deg, #f5f5f5 0%, #e9ecef 100%);
          color: #909399;
        }
      }
      .ranking-info {
        flex: 1;
        .ranking-name {
          font-weight: 600;
          color: #303133;
          margin-bottom: 4px;
          font-size: 14px;
        }
        .ranking-value {
          color: #606266;
          font-size: 13px;
          font-weight: 500;
        }
      }
      .ranking-trend {
        margin-left: 12px;
      }
    }
  }
}
.analysis-control {
  margin-bottom: 20px;
  .card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  .abnormal-list {
    .abnormal-item {
      display: flex;
      align-items: flex-start;
      padding: 15px 0;
      border-bottom: 1px solid #f0f0f0;
      &:last-child {
        border-bottom: none;
      }
      .abnormal-icon {
        margin-right: 15px;
        margin-top: 2px;
      }
      .abnormal-content {
        flex: 1;
        .abnormal-title {
          font-weight: bold;
          color: #303133;
          margin-bottom: 5px;
        }
        .abnormal-desc {
          color: #606266;
          font-size: 14px;
          margin-bottom: 5px;
        }
        .abnormal-time {
          color: #909399;
          font-size: 12px;
        }
      }
      .abnormal-action {
        margin-left: 15px;
      }
    }
  }
  .control-content {
    .control-item {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 20px;
      &:last-child {
        margin-bottom: 0;
      }
      .label {
        color: #606266;
        font-size: 14px;
      }
      .value {
        font-weight: bold;
        color: #303133;
      }
    }
  }
}
.environmental-indicators {
  margin-bottom: 20px;
  .card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    .header-actions {
      display: flex;
      gap: 10px;
    }
  }
  .indicator-item {
    text-align: center;
    padding: 20px 0;
    .indicator-title {
      color: #606266;
      font-size: 14px;
      margin-bottom: 10px;
    }
    .indicator-value {
      font-size: 24px;
      font-weight: bold;
      color: #409eff;
      margin-bottom: 10px;
    }
    .indicator-trend {
      font-size: 12px;
      color: #909399;
      .success {
        color: #67c23a;
      }
    }
  }
}
.multi-dimensional-reports {
  .card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    .header-actions {
      display: flex;
      gap: 10px;
    }
  }
  .report-filters {
    padding: 20px 0;
    border-bottom: 1px solid #f0f0f0;
    margin-bottom: 20px;
  }
  .report-preview {
    .report-data {
      padding: 20px 0;
      .data-card {
        text-align: center;
        padding: 16px;
        background: #f8f9fa;
        border-radius: 8px;
        margin-bottom: 16px;
        .data-title {
          color: #606266;
          font-size: 14px;
          margin-bottom: 8px;
        }
        .data-value {
          font-size: 20px;
          font-weight: bold;
          color: #303133;
          margin-bottom: 8px;
        }
        .data-trend {
          font-size: 12px;
          .trend-up {
            color: #f56c6c;
          }
          .trend-down {
            color: #67c23a;
          }
          .trend-stable {
            color: #909399;
          }
        }
      }
      .report-chart {
        margin: 20px 0;
        padding: 20px;
        background: #f8f9fa;
        border-radius: 8px;
        .chart-title {
          text-align: center;
          font-size: 16px;
          font-weight: 600;
          color: #303133;
          margin-bottom: 16px;
        }
        .chart-bars {
          display: flex;
          justify-content: space-around;
          align-items: flex-end;
          height: 120px;
          .chart-bar {
            text-align: center;
            flex: 1;
            margin: 0 8px;
            .bar-label {
              font-size: 12px;
              color: #606266;
              margin-bottom: 8px;
            }
            .bar-container {
              height: 80px;
              background: #e9ecef;
              border-radius: 4px;
              position: relative;
              margin-bottom: 8px;
            }
            .bar-fill {
              position: absolute;
              bottom: 0;
              left: 0;
              right: 0;
              border-radius: 4px;
              transition: height 0.3s ease;
            }
            .bar-value {
              font-size: 12px;
              color: #303133;
              font-weight: 500;
            }
          }
        }
      }
      .report-summary {
        display: flex;
        justify-content: space-around;
        padding: 20px;
        background: #f8f9fa;
        border-radius: 8px;
        .summary-item {
          text-align: center;
          .summary-label {
            display: block;
            color: #606266;
            font-size: 14px;
            margin-bottom: 8px;
          }
          .summary-value {
            font-size: 18px;
            font-weight: bold;
            color: #303133;
          }
        }
      }
    }
  }
}
// é€šç”¨æ ·å¼
.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.success {
  color: #67c23a;
}
.danger {
  color: #f56c6c;
}
.warning {
  color: #e6a23c;
}
.info {
  color: #909399;
}
</style>