From 33e6e77746eaea0fc06adb9b359b02e355887061 Mon Sep 17 00:00:00 2001 From: spring <2396852758@qq.com> Date: 星期四, 14 八月 2025 11:03:33 +0800 Subject: [PATCH] 完成动态节能 --- src/views/energyManagement/dynamicEnergySaving/index.vue | 659 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 659 insertions(+), 0 deletions(-) diff --git a/src/views/energyManagement/dynamicEnergySaving/index.vue b/src/views/energyManagement/dynamicEnergySaving/index.vue new file mode 100644 index 0000000..eb6f0b1 --- /dev/null +++ b/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> -- Gitblit v1.9.3