- 调整了设备情况、电站一次系统图等组件的布局 - 优化了卡片样式,添加了新的运行步骤日志卡片 - 修改了标题组件的样式,增加了字体大小等属性 - 调整了安全运行天数的展示方式,增加了背景图片
350 lines
12 KiB
Vue
350 lines
12 KiB
Vue
<template>
|
|
<el-card style="width: 100%;">
|
|
<div class="circuit-container">
|
|
<!-- 状态指示器 -->
|
|
<div class="status-indicators">
|
|
<div class="status-item">
|
|
<span class="status-dot closed"></span>
|
|
<span>闭合</span>
|
|
</div>
|
|
<div class="status-item">
|
|
<span class="status-dot open"></span>
|
|
<span>断开</span>
|
|
</div>
|
|
<div class="status-item">
|
|
<span class="status-dot running"></span>
|
|
<span>运行中</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 控制按钮 -->
|
|
<div class="control-buttons">
|
|
<button v-for="(device, index) in devices" :key="index" @click="toggleDevice(device.id)"
|
|
:class="{ 'btn-active': device.status === 'closed' }">
|
|
{{ device.name }}: {{ device.statusText }}
|
|
</button>
|
|
</div>
|
|
|
|
<!-- 电路图 SVG -->
|
|
<svg class="circuit-svg" viewBox="0 0 800 400" xmlns="http://www.w3.org/2000/svg">
|
|
<!-- 背景网格 -->
|
|
<pattern id="grid" width="50" height="50" patternUnits="userSpaceOnUse">
|
|
<path d="M 50 0 L 0 0 0 50" fill="none" stroke="#f0f0f0" stroke-width="1" />
|
|
</pattern>
|
|
<rect width="100%" height="100%" fill="url(#grid)" />
|
|
|
|
<!-- 主线路径 -->
|
|
<!-- 发电站到主开关 -->
|
|
<line x1="100" y1="200" x2="180" y2="200" stroke="#22c55e" stroke-width="4" />
|
|
|
|
<!-- 主开关到变压器 -->
|
|
<line x1="220" y1="200" x2="280" y2="200" stroke="#22c55e" stroke-width="4" />
|
|
|
|
<!-- 变压器到母线开关 -->
|
|
<line x1="360" y1="200" x2="420" y2="200" stroke="#22c55e" stroke-width="4" />
|
|
|
|
<!-- 母线开关到分支点 -->
|
|
<line x1="460" y1="200" x2="500" y2="200" stroke="#22c55e" stroke-width="4" />
|
|
|
|
<!-- 分支点到馈线开关A -->
|
|
<line x1="500" y1="200" x2="500" y2="100" stroke="#22c55e" stroke-width="4" />
|
|
<line x1="500" y1="100" x2="580" y2="100" stroke="#22c55e" stroke-width="4" />
|
|
|
|
<!-- 分支点到馈线开关B -->
|
|
<line x1="500" y1="200" x2="500" y2="300" stroke="#ef4444" stroke-width="4" stroke-dasharray="5,5" />
|
|
<line x1="500" y1="300" x2="580" y2="300" stroke="#ef4444" stroke-width="4" stroke-dasharray="5,5" />
|
|
|
|
<!-- 馈线开关B到保护开关 -->
|
|
<line x1="620" y1="300" x2="700" y2="300" stroke="#ef4444" stroke-width="4" stroke-dasharray="5,5" />
|
|
|
|
<!-- 发电站 -->
|
|
<circle cx="100" cy="200" r="30" fill="#3b82f6" stroke="#1e40af" stroke-width="2" />
|
|
<text x="100" y="205" text-anchor="middle" fill="white" font-weight="bold">发电站</text>
|
|
|
|
<!-- 主开关 -->
|
|
<g :class="{ 'switch-closed': devices[0].status === 'closed' }">
|
|
<circle cx="200" cy="200" r="15" :fill="devices[0].status === 'closed' ? '#10b981' : '#ef4444'" />
|
|
<text x="200" y="250" text-anchor="middle" font-size="12">主开关</text>
|
|
<text x="200" y="270" text-anchor="middle" font-size="10" fill="#666">220kV</text>
|
|
<text x="200" y="285" text-anchor="middle" font-size="10"
|
|
:fill="devices[0].status === 'closed' ? '#10b981' : '#ef4444'">
|
|
{{ devices[0].statusText }}
|
|
</text>
|
|
</g>
|
|
|
|
<!-- 变压器 -->
|
|
<g>
|
|
<rect x="300" y="170" width="60" height="60" fill="white" stroke="#666" stroke-width="2" />
|
|
<line x1="315" y1="190" x2="345" y2="190" stroke="#666" stroke-width="2" />
|
|
<line x1="315" y1="210" x2="345" y2="210" stroke="#666" stroke-width="2" />
|
|
<line x1="315" y1="230" x2="345" y2="230" stroke="#666" stroke-width="2" />
|
|
<text x="330" y="285" text-anchor="middle" font-size="10" fill="#10b981">已完成</text>
|
|
</g>
|
|
|
|
<!-- 母线开关 -->
|
|
<g :class="{ 'switch-closed': devices[1].status === 'closed' }">
|
|
<circle cx="440" cy="200" r="15" :fill="devices[1].status === 'closed' ? '#10b981' : '#ef4444'" />
|
|
<text x="440" y="250" text-anchor="middle" font-size="12">母线开关</text>
|
|
<text x="440" y="270" text-anchor="middle" font-size="10" fill="#666">110kV</text>
|
|
<text x="440" y="285" text-anchor="middle" font-size="10"
|
|
:fill="devices[1].status === 'closed' ? '#10b981' : '#ef4444'">
|
|
{{ devices[1].statusText }}
|
|
</text>
|
|
</g>
|
|
|
|
<!-- 分支点 -->
|
|
<circle cx="500" cy="200" r="8" fill="#666" />
|
|
|
|
<!-- 馈线开关A -->
|
|
<g :class="{ 'switch-closed': devices[2].status === 'closed' }">
|
|
<circle cx="600" cy="100" r="15" :fill="devices[2].status === 'closed' ? '#10b981' : '#ef4444'" />
|
|
<text x="600" y="60" text-anchor="middle" font-size="12">馈线开关A</text>
|
|
<text x="600" y="80" text-anchor="middle" font-size="10"
|
|
:fill="devices[2].status === 'closed' ? '#10b981' : '#ef4444'">
|
|
{{ devices[2].statusText }}
|
|
</text>
|
|
</g>
|
|
|
|
<!-- 负载A -->
|
|
<circle cx="680" cy="100" r="20" fill="#3b82f6" stroke="#1e40af" stroke-width="2" />
|
|
<text x="680" y="105" text-anchor="middle" fill="white" font-size="12">负载A</text>
|
|
<text x="680" y="135" text-anchor="middle" font-size="10" fill="#10b981">已完成</text>
|
|
|
|
<!-- 馈线开关B -->
|
|
<g :class="{ 'switch-closed': devices[3].status === 'closed' }">
|
|
<circle cx="600" cy="300" r="15" :fill="devices[3].status === 'closed' ? '#10b981' : '#ef4444'" />
|
|
<text x="600" y="340" text-anchor="middle" font-size="12">馈线开关B</text>
|
|
<text x="600" y="360" text-anchor="middle" font-size="10"
|
|
:fill="devices[3].status === 'closed' ? '#10b981' : '#ef4444'">
|
|
{{ devices[3].statusText }}
|
|
</text>
|
|
</g>
|
|
|
|
<!-- 保护开关 -->
|
|
<g :class="{ 'switch-closed': devices[4].status === 'closed' }">
|
|
<circle cx="720" cy="300" r="15" :fill="devices[4].status === 'closed' ? '#10b981' : '#ef4444'" />
|
|
<text x="720" y="340" text-anchor="middle" font-size="12">保护开关</text>
|
|
<text x="720" y="360" text-anchor="middle" font-size="10"
|
|
:fill="devices[4].status === 'closed' ? '#10b981' : '#ef4444'">
|
|
{{ devices[4].statusText }}
|
|
</text>
|
|
</g>
|
|
</svg>
|
|
|
|
<!-- WebSocket 连接状态 -->
|
|
<div class="connection-status">
|
|
<span>WebSocket 连接状态:</span>
|
|
<span :class="wsConnected ? 'connected' : 'disconnected'">
|
|
{{ wsConnected ? '已连接' : '未连接' }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</el-card>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, onMounted, onUnmounted } from 'vue';
|
|
|
|
// 设备状态数据
|
|
const devices = ref([
|
|
{ id: 'main-switch', name: '主开关', status: 'closed', statusText: '已完成' },
|
|
{ id: 'bus-switch', name: '母线开关', status: 'closed', statusText: '已完成' },
|
|
{ id: 'feeder-a', name: '馈线开关A', status: 'closed', statusText: '已完成' },
|
|
{ id: 'feeder-b', name: '馈线开关B', status: 'open', statusText: '未完成' },
|
|
{ id: 'protection-switch', name: '保护开关', status: 'open', statusText: '未完成' }
|
|
]);
|
|
|
|
// WebSocket 连接状态
|
|
const wsConnected = ref(false);
|
|
let ws = null;
|
|
|
|
// 切换设备状态
|
|
const toggleDevice = (deviceId) => {
|
|
const device = devices.value.find(d => d.id === deviceId);
|
|
if (device) {
|
|
// 切换状态
|
|
device.status = device.status === 'closed' ? 'open' : 'closed';
|
|
device.statusText = device.status === 'closed' ? '已完成' : '未完成';
|
|
|
|
// 发送状态到服务器
|
|
if (ws && ws.readyState === WebSocket.OPEN) {
|
|
ws.send(JSON.stringify({
|
|
type: 'status-update',
|
|
deviceId,
|
|
status: device.status
|
|
}));
|
|
}
|
|
}
|
|
};
|
|
|
|
// 连接 WebSocket
|
|
const connectWebSocket = () => {
|
|
// 实际应用中替换为真实的 WebSocket 服务器地址
|
|
const wsUrl = 'ws://localhost:8080/ws/circuit';
|
|
|
|
// 关闭现有连接
|
|
if (ws) {
|
|
ws.close();
|
|
}
|
|
|
|
// 创建新连接
|
|
ws = new WebSocket(wsUrl);
|
|
|
|
ws.onopen = () => {
|
|
console.log('WebSocket 连接已建立');
|
|
wsConnected.value = true;
|
|
|
|
// 发送当前状态
|
|
ws.send(JSON.stringify({
|
|
type: 'initial-status',
|
|
status: devices.value.reduce((acc, device) => {
|
|
acc[device.id] = device.status;
|
|
return acc;
|
|
}, {})
|
|
}));
|
|
};
|
|
|
|
ws.onmessage = (event) => {
|
|
try {
|
|
const data = JSON.parse(event.data);
|
|
console.log('收到消息:', data);
|
|
|
|
// 处理状态更新
|
|
if (data.type === 'status-update' && data.deviceId && data.status) {
|
|
const device = devices.value.find(d => d.id === data.deviceId);
|
|
if (device) {
|
|
device.status = data.status;
|
|
device.statusText = data.status === 'closed' ? '已完成' : '未完成';
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('解析 WebSocket 消息失败:', error);
|
|
}
|
|
};
|
|
|
|
ws.onclose = () => {
|
|
console.log('WebSocket 连接已关闭');
|
|
wsConnected.value = false;
|
|
|
|
// 5秒后尝试重连
|
|
setTimeout(connectWebSocket, 5000);
|
|
};
|
|
|
|
ws.onerror = (error) => {
|
|
console.error('WebSocket 错误:', error);
|
|
};
|
|
};
|
|
|
|
// 组件挂载时连接 WebSocket
|
|
onMounted(() => {
|
|
connectWebSocket();
|
|
});
|
|
|
|
// 组件卸载时关闭 WebSocket 连接
|
|
onUnmounted(() => {
|
|
if (ws) {
|
|
ws.close();
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<style scoped>
|
|
.circuit-container {
|
|
font-family: Arial, sans-serif;
|
|
padding: 20px;
|
|
max-width: 1000px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.status-indicators {
|
|
display: flex;
|
|
gap: 20px;
|
|
margin-bottom: 15px;
|
|
padding: 10px;
|
|
background-color: #f9f9f9;
|
|
border-radius: 5px;
|
|
}
|
|
|
|
.status-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
}
|
|
|
|
.status-dot {
|
|
display: inline-block;
|
|
width: 12px;
|
|
height: 12px;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
.status-dot.closed {
|
|
background-color: #10b981;
|
|
}
|
|
|
|
.status-dot.open {
|
|
background-color: #ef4444;
|
|
}
|
|
|
|
.status-dot.running {
|
|
background-color: #eab308;
|
|
}
|
|
|
|
.control-buttons {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 10px;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.control-buttons button {
|
|
padding: 8px 16px;
|
|
background-color: #f0f0f0;
|
|
border: 1px solid #ddd;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.control-buttons button.btn-active {
|
|
background-color: #10b981;
|
|
color: white;
|
|
border-color: #059669;
|
|
}
|
|
|
|
.control-buttons button:hover {
|
|
background-color: #e0e0e0;
|
|
}
|
|
|
|
.control-buttons button.btn-active:hover {
|
|
background-color: #059669;
|
|
}
|
|
|
|
.circuit-svg {
|
|
width: 100%;
|
|
height: auto;
|
|
border: 1px solid #ddd;
|
|
border-radius: 5px;
|
|
background-color: white;
|
|
}
|
|
|
|
.connection-status {
|
|
margin-top: 15px;
|
|
padding: 10px;
|
|
background-color: #f9f9f9;
|
|
border-radius: 5px;
|
|
display: flex;
|
|
gap: 10px;
|
|
}
|
|
|
|
.connection-status .connected {
|
|
color: #10b981;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.connection-status .disconnected {
|
|
color: #ef4444;
|
|
font-weight: bold;
|
|
}
|
|
</style>
|