spring
10 天以前 33e6e77746eaea0fc06adb9b359b02e355887061
完成动态节能
已添加1个文件
659 ■■■■■ 文件已修改
src/views/energyManagement/dynamicEnergySaving/index.vue 659 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/energyManagement/dynamicEnergySaving/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,659 @@
<template>
  <div class="app-container">
    <!-- è¾¹ç¼˜è®¡ç®—状态监控 -->
    <el-row :gutter="20" class="status-section">
      <el-col :span="8">
        <el-card class="status-card">
          <div class="status-item">
            <div class="status-icon">
              <el-icon><Monitor /></el-icon>
            </div>
            <div class="status-info">
              <div class="status-title">边缘服务器状态</div>
              <div class="status-value" :class="edgeServerStatus.status">
                {{ edgeServerStatus.status === 'online' ? '在线' : '离线' }}
              </div>
              <div class="status-detail">最后心跳: {{ formatTime(edgeServerStatus.lastHeartbeat) }}</div>
            </div>
          </div>
        </el-card>
      </el-col>
      <el-col :span="8">
        <el-card class="status-card">
          <div class="status-item">
            <div class="status-icon">
              <el-icon><Cpu /></el-icon>
            </div>
            <div class="status-info">
              <div class="status-title">模型运行状态</div>
              <div class="status-value" :class="modelStatus.status">
                {{ modelStatus.status === 'running' ? '运行中' : '已停止' }}
              </div>
              <div class="status-detail">运行模型: {{ modelStatus.modelCount }}个</div>
            </div>
          </div>
        </el-card>
      </el-col>
      <el-col :span="8">
        <el-card class="status-card">
          <div class="status-item">
            <div class="status-icon">
              <el-icon><TrendCharts /></el-icon>
            </div>
            <div class="status-info">
              <div class="status-title">节能效果</div>
              <div class="status-value success">{{ energySavingRate.toFixed(1) }}%</div>
              <div class="status-detail">累计节能: {{ totalEnergySaved.toFixed(1) }}kWh</div>
            </div>
          </div>
        </el-card>
      </el-col>
    </el-row>
    <!-- æ³¨æ°´æ³µé¢‘率优化控制 -->
    <el-card class="control-section">
      <template #header>
        <span>注水泵频率优化控制</span>
      </template>
      <el-row :gutter="20">
        <el-col :span="12">
          <div class="pump-control">
            <h4>实时参数监控</h4>
            <el-form label-width="120px">
              <el-form-item label="地层压力 (MPa)">
                <el-input v-model="pumpData.formationPressure" readonly>
                  <template #append>MPa</template>
                </el-input>
              </el-form-item>
              <el-form-item label="当前泵速 (Hz)">
                <el-input v-model="pumpData.currentFrequency" readonly>
                  <template #append>Hz</template>
                </el-input>
              </el-form-item>
              <el-form-item label="优化后泵速 (Hz)">
                <el-input v-model="pumpData.optimizedFrequency" readonly>
                  <template #append>Hz</template>
                </el-input>
              </el-form-item>
              <el-form-item label="能耗降低">
                <el-progress
                  :percentage="pumpData.energyReduction"
                  :color="getProgressColor"
                  :format="format => `${format}%`"
                />
              </el-form-item>
              <el-form-item label="流量 (m³/h)">
                <el-input v-model="pumpData.flowRate" readonly>
                  <template #append>m³/h</template>
                </el-input>
              </el-form-item>
              <el-form-item label="功率 (kW)">
                <el-input v-model="pumpData.power" readonly>
                  <template #append>kW</template>
                </el-input>
              </el-form-item>
            </el-form>
          </div>
        </el-col>
        <el-col :span="12">
          <div class="pump-chart">
            <h4>频率优化趋势</h4>
            <div ref="frequencyChart" style="height: 300px;"></div>
          </div>
        </el-col>
      </el-row>
      <el-row :gutter="20" class="control-buttons">
        <el-col :span="24">
          <el-button
            type="primary"
            :disabled="!canControl"
            @click="applyOptimization"
          >
            åº”用优化设置
          </el-button>
          <el-button
            type="warning"
            :disabled="!canControl"
            @click="emergencyStop"
          >
            ç´§æ€¥åœæ­¢
          </el-button>
          <el-button
            type="info"
            @click="showOptimizationHistory"
          >
            ä¼˜åŒ–历史
          </el-button>
          <el-button
            type="success"
            @click="toggleAutoRefresh"
          >
            {{ autoRefreshStatus ? '停止自动刷新' : '开启自动刷新' }}
          </el-button>
        </el-col>
      </el-row>
    </el-card>
    <!-- è¾¹ç¼˜è®¡ç®—模型配置 -->
    <el-card class="model-section">
      <template #header>
        <span>边缘计算模型配置</span>
      </template>
      <el-table :data="modelConfigs" style="width: 100%">
        <el-table-column prop="modelName" label="模型名称" />
        <el-table-column prop="version" label="版本" />
        <el-table-column prop="status" label="状态">
          <template #default="scope">
            <el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
              {{ scope.row.status === 'active' ? '激活' : '待机' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="accuracy" label="准确率" />
        <el-table-column prop="lastUpdate" label="最后更新" />
        <el-table-column label="操作">
          <template #default="scope">
            <el-button
              size="small"
              @click="updateModel(scope.row)"
            >
              æ›´æ–°æ¨¡åž‹
            </el-button>
            <el-button
              size="small"
              type="danger"
              @click="deleteModel(scope.row)"
            >
              åˆ é™¤
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-card>
    <!-- èƒ½è€—分析图表 -->
    <el-card class="analysis-section">
      <template #header>
        <span>能耗分析</span>
      </template>
      <el-row :gutter="20">
        <el-col :span="12">
          <div ref="energyChart" style="height: 400px;"></div>
        </el-col>
        <el-col :span="12">
          <div ref="savingChart" style="height: 400px;"></div>
        </el-col>
      </el-row>
    </el-card>
    <!-- ä¼˜åŒ–历史对话框 -->
    <el-dialog v-model="historyDialogVisible" title="优化历史记录" width="80%">
      <el-table :data="optimizationHistory" style="width: 100%">
        <el-table-column prop="timestamp" label="时间" />
        <el-table-column prop="formationPressure" label="地层压力 (MPa)" />
        <el-table-column prop="oldFrequency" label="原频率 (Hz)" />
        <el-table-column prop="newFrequency" label="新频率 (Hz)" />
        <el-table-column prop="energySaved" label="节能 (kWh)" />
        <el-table-column prop="status" label="状态">
          <template #default="scope">
            <el-tag :type="scope.row.status === 'success' ? 'success' : 'warning'">
              {{ scope.row.status === 'success' ? '成功' : '失败' }}
            </el-tag>
          </template>
        </el-table-column>
      </el-table>
    </el-dialog>
  </div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, computed } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Monitor, Cpu, TrendCharts } from '@element-plus/icons-vue'
import * as echarts from 'echarts'
// å“åº”式数据
const edgeServerStatus = ref({ status: 'online', lastHeartbeat: Date.now() })
const modelStatus = ref({ status: 'running', modelCount: 3 })
const energySavingRate = ref(15.8)
const totalEnergySaved = ref(1250.5)
const pumpData = ref({
  formationPressure: 25.6,
  currentFrequency: 45.2,
  optimizedFrequency: 42.1,
  energyReduction: 23,
  flowRate: 180.5,
  power: 85.3
})
const modelConfigs = ref([
  {
    modelName: '注水泵频率优化模型',
    version: 'v2.1.0',
    status: 'active',
    accuracy: '94.2%',
    lastUpdate: '2024-01-15 14:30:00'
  },
  {
    modelName: '地层压力预测模型',
    version: 'v1.8.5',
    status: 'active',
    accuracy: '91.7%',
    lastUpdate: '2024-01-14 09:15:00'
  },
  {
    modelName: '能耗分析模型',
    version: 'v2.0.3',
    status: 'standby',
    accuracy: '89.3%',
    lastUpdate: '2024-01-13 16:45:00'
  }
])
const historyDialogVisible = ref(false)
const optimizationHistory = ref([])
// å›¾è¡¨å¼•用
const frequencyChart = ref(null)
const energyChart = ref(null)
const savingChart = ref(null)
// è‡ªåŠ¨åˆ·æ–°ç›¸å…³
const autoRefreshStatus = ref(true)
const autoRefreshTimer = ref(null)
const chartInstances = ref([])
// è®¡ç®—属性
const canControl = computed(() => {
  return edgeServerStatus.value.status === 'online' && modelStatus.value.status === 'running'
})
const getProgressColor = computed(() => {
  return (percentage) => {
    if (percentage < 20) return '#909399'
    if (percentage < 40) return '#E6A23C'
    if (percentage < 60) return '#409EFF'
    return '#67C23A'
  }
})
// ç”Ÿæˆæ¨¡æ‹Ÿæ•°æ®
const generateMockData = () => {
  // ç”Ÿæˆéšæœºåœ°å±‚压力 (20-30 MPa)
  const formationPressure = 20 + Math.random() * 10
  // æ ¹æ®åœ°å±‚压力计算优化频率
  const baseFrequency = 40 + (formationPressure - 25) * 2
  const currentFrequency = baseFrequency + (Math.random() - 0.5) * 4
  const optimizedFrequency = Math.max(35, baseFrequency - Math.random() * 3)
  // è®¡ç®—能耗降低
  const energyReduction = Math.round((currentFrequency - optimizedFrequency) / currentFrequency * 100)
  // è®¡ç®—流量和功率
  const flowRate = 150 + Math.random() * 60
  const power = 70 + Math.random() * 30
  // æ›´æ–°æ³µæ•°æ®
  pumpData.value = {
    formationPressure: parseFloat(formationPressure.toFixed(1)),
    currentFrequency: parseFloat(currentFrequency.toFixed(1)),
    optimizedFrequency: parseFloat(optimizedFrequency.toFixed(1)),
    energyReduction: Math.min(energyReduction, 35),
    flowRate: parseFloat(flowRate.toFixed(1)),
    power: parseFloat(power.toFixed(1))
  }
  // æ›´æ–°èŠ‚èƒ½æ•ˆæžœ
  energySavingRate.value = 12 + Math.random() * 8
  totalEnergySaved.value += Math.random() * 2
  // æ›´æ–°è¾¹ç¼˜æœåŠ¡å™¨çŠ¶æ€
  edgeServerStatus.value.lastHeartbeat = Date.now()
  // éšæœºæ›´æ–°æ¨¡åž‹çŠ¶æ€
  if (Math.random() > 0.95) {
    modelStatus.value.modelCount = Math.max(1, modelStatus.value.modelCount + (Math.random() > 0.5 ? 1 : -1))
  }
  // æ·»åŠ ä¼˜åŒ–åŽ†å²è®°å½•
  if (Math.random() > 0.7) {
    addOptimizationHistory()
  }
  // æ›´æ–°å›¾è¡¨æ•°æ®
  updateCharts()
}
// æ·»åŠ ä¼˜åŒ–åŽ†å²è®°å½•
const addOptimizationHistory = () => {
  const timestamp = new Date().toLocaleString()
  const record = {
    timestamp,
    formationPressure: pumpData.value.formationPressure,
    oldFrequency: pumpData.value.currentFrequency,
    newFrequency: pumpData.value.optimizedFrequency,
    energySaved: parseFloat((Math.random() * 5 + 1).toFixed(2)),
    status: Math.random() > 0.1 ? 'success' : 'failed'
  }
  optimizationHistory.value.unshift(record)
  // ä¿æŒæœ€å¤š100条记录
  if (optimizationHistory.value.length > 100) {
    optimizationHistory.value = optimizationHistory.value.slice(0, 100)
  }
}
// æ›´æ–°å›¾è¡¨æ•°æ®
const updateCharts = () => {
  chartInstances.value.forEach(instance => {
    if (instance && instance.setOption) {
      // è¿™é‡Œå¯ä»¥æ›´æ–°å›¾è¡¨æ•°æ®
      // ä¸ºäº†ç®€åŒ–,我们只是重新初始化图表
    }
  })
}
// æ–¹æ³•
const refreshData = () => {
  generateMockData()
  ElMessage.success('数据刷新成功')
}
const applyOptimization = async () => {
  try {
    await ElMessageBox.confirm('确定要应用当前的优化设置吗?', '确认操作', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
    // åº”用优化设置
    pumpData.value.currentFrequency = pumpData.value.optimizedFrequency
    ElMessage.success('优化设置应用成功')
    refreshData()
  } catch (error) {
    if (error !== 'cancel') {
      ElMessage.error('应用优化设置失败')
    }
  }
}
const emergencyStop = async () => {
  try {
    await ElMessageBox.confirm('确定要紧急停止所有注水泵吗?', '紧急操作', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'error'
    })
    // æ‰§è¡Œç´§æ€¥åœæ­¢é€»è¾‘
    pumpData.value.currentFrequency = 0
    pumpData.value.optimizedFrequency = 0
    ElMessage.success('紧急停止执行成功')
  } catch (error) {
    if (error !== 'cancel') {
      ElMessage.error('紧急停止执行失败')
    }
  }
}
const showOptimizationHistory = () => {
  historyDialogVisible.value = true
}
const updateModel = (model) => {
  ElMessage.info(`更新模型: ${model.modelName}`)
}
const deleteModel = async (model) => {
  try {
    await ElMessageBox.confirm(`确定要删除模型 ${model.modelName} å—?`, '确认删除', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
    const index = modelConfigs.value.findIndex(m => m.modelName === model.modelName)
    if (index > -1) {
      modelConfigs.value.splice(index, 1)
      ElMessage.success('模型删除成功')
    }
  } catch (error) {
    if (error !== 'cancel') {
      ElMessage.error('模型删除失败')
    }
  }
}
const toggleAutoRefresh = () => {
  autoRefreshStatus.value = !autoRefreshStatus.value
  if (autoRefreshStatus.value) {
    startAutoRefresh()
    ElMessage.success('自动刷新已开启')
  } else {
    stopAutoRefresh()
    ElMessage.info('自动刷新已关闭')
  }
}
const startAutoRefresh = () => {
  stopAutoRefresh() // å…ˆåœæ­¢ä¹‹å‰çš„定时器
  autoRefreshTimer.value = setInterval(() => {
    generateMockData()
  }, 60000) // 1分钟 = 60000毫秒
}
const stopAutoRefresh = () => {
  if (autoRefreshTimer.value) {
    clearInterval(autoRefreshTimer.value)
    autoRefreshTimer.value = null
  }
}
const formatTime = (timestamp) => {
  return new Date(timestamp).toLocaleTimeString()
}
// åˆå§‹åŒ–图表
const initCharts = () => {
  // é¢‘率优化趋势图
  const frequencyChartInstance = echarts.init(frequencyChart.value)
  const frequencyOption = {
    title: { text: '泵频率优化趋势' },
    tooltip: { trigger: 'axis' },
    legend: { data: ['当前频率', '优化频率', '地层压力'] },
    xAxis: { type: 'category', data: ['00:00', '04:00', '08:00', '12:00', '16:00', '20:00'] },
    yAxis: [
      { type: 'value', name: '频率 (Hz)' },
      { type: 'value', name: '压力 (MPa)' }
    ],
    series: [
      {
        name: '当前频率',
        type: 'line',
        data: [45.2, 44.8, 45.5, 45.1, 44.9, 45.2]
      },
      {
        name: '优化频率',
        type: 'line',
        data: [42.1, 41.8, 42.3, 41.9, 41.7, 42.1]
      },
      {
        name: '地层压力',
        type: 'line',
        yAxisIndex: 1,
        data: [25.6, 25.8, 26.1, 25.9, 25.7, 25.6]
      }
    ]
  }
  frequencyChartInstance.setOption(frequencyOption)
  chartInstances.value.push(frequencyChartInstance)
  // èƒ½è€—分析图
  const energyChartInstance = echarts.init(energyChart.value)
  const energyOption = {
    title: { text: '日能耗对比' },
    tooltip: { trigger: 'item' },
    legend: { orient: 'vertical', left: 'left',top: 'center' },
    series: [
      {
        name: '能耗分布',
        type: 'pie',
        radius: '50%',
        data: [
          { value: 45, name: '注水泵' },
          { value: 25, name: '照明系统' },
          { value: 20, name: '通风系统' },
          { value: 10, name: '其他设备' }
        ]
      }
    ]
  }
  energyChartInstance.setOption(energyOption)
  chartInstances.value.push(energyChartInstance)
  // èŠ‚èƒ½æ•ˆæžœå›¾
  const savingChartInstance = echarts.init(savingChart.value)
  const savingOption = {
    title: { text: '节能效果趋势' },
    tooltip: { trigger: 'axis' },
    xAxis: { type: 'category', data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'] },
    yAxis: { type: 'value', name: '节能率 (%)' },
    series: [
      {
        name: '节能率',
        type: 'bar',
        data: [12.5, 15.2, 18.7, 16.3, 19.1, 17.8, 15.8]
      }
    ]
  }
  savingChartInstance.setOption(savingOption)
  chartInstances.value.push(savingChartInstance)
}
// ç”Ÿæˆåˆå§‹åŽ†å²æ•°æ®
const generateInitialHistory = () => {
  for (let i = 0; i < 20; i++) {
    const timestamp = new Date(Date.now() - i * 3600000).toLocaleString()
    const record = {
      timestamp,
      formationPressure: parseFloat((20 + Math.random() * 10).toFixed(1)),
      oldFrequency: parseFloat((40 + Math.random() * 10).toFixed(1)),
      newFrequency: parseFloat((35 + Math.random() * 8).toFixed(1)),
      energySaved: parseFloat((Math.random() * 5 + 1).toFixed(2)),
      status: Math.random() > 0.1 ? 'success' : 'failed'
    }
    optimizationHistory.value.push(record)
  }
}
// ç”Ÿå‘½å‘¨æœŸ
onMounted(() => {
  initCharts()
  generateInitialHistory()
  refreshData()
  if (autoRefreshStatus.value) {
    startAutoRefresh()
  }
})
onUnmounted(() => {
  stopAutoRefresh()
  chartInstances.value.forEach(instance => {
    if (instance && instance.dispose) {
      instance.dispose()
    }
  })
})
</script>
<style scoped>
.app-container {
  padding: 20px;
}
.status-section {
  margin-bottom: 20px;
}
.status-card {
  height: 140px;
}
.status-item {
  display: flex;
  align-items: center;
  height: 100%;
}
.status-icon {
  font-size: 48px;
  margin-right: 20px;
  color: #409EFF;
}
.status-info {
  flex: 1;
}
.status-title {
  font-size: 14px;
  color: #909399;
  margin-bottom: 8px;
}
.status-value {
  font-size: 24px;
  font-weight: bold;
  margin-bottom: 8px;
}
.status-detail {
  font-size: 12px;
  color: #909399;
}
.status-value.online,
.status-value.running {
  color: #67C23A;
}
.status-value.offline,
.status-value.stopped {
  color: #F56C6C;
}
.status-value.success {
  color: #67C23A;
}
.control-section,
.model-section,
.analysis-section {
  margin-bottom: 20px;
}
.pump-control h4,
.pump-chart h4 {
  margin-bottom: 20px;
  color: #303133;
}
.control-buttons {
  margin-top: 20px;
  text-align: center;
}
.control-buttons .el-button {
  margin: 0 10px;
}
</style>