¶Ô±ÈÐÂÎļþ |
| | |
| | | <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> |