<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>
|