独立渲染引擎就绪引擎就绪
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>高可靠性冗余控制系统与自动泄放机制原理</title>
<style>
:root {
--bg-color: #0b0f19;
--grid-color: #1a233a;
--text-main: #e2e8f0;
--text-muted: #64748b;
/* Status Colors */
--color-normal: #00f0ff; /* Cyan - Active/Normal */
--color-standby: #fbbf24; /* Amber - Standby/Sync */
--color-safe: #10b981; /* Green - Safe State/Success */
--color-danger: #ef4444; /* Red - Failure/Alarm */
--color-hardwire: #f97316; /* Orange - Independent Hardwire */
--color-fluid: #3b82f6; /* Blue - Fluid */
--font-mono: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: var(--bg-color);
color: var(--text-main);
font-family: var(--font-mono);
overflow: hidden;
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-image:
linear-gradient(var(--grid-color) 1px, transparent 1px),
linear-gradient(90deg, var(--grid-color) 1px, transparent 1px);
background-size: 40px 40px;
background-position: center center;
transition: box-shadow 0.5s ease;
}
/* Screen Edge Vignette for Alarm State */
body.alarm-state {
box-shadow: inset 0 0 150px rgba(239, 68, 68, 0.2);
}
#animation-container {
width: 95%;
height: 95%;
max-width: 1400px;
max-height: 900px;
position: relative;
display: flex;
justify-content: center;
align-items: center;
}
svg {
width: 100%;
height: 100%;
filter: drop-shadow(0 0 20px rgba(0, 0, 0, 0.5));
}
/* HUD Panels - Strictly constrained to edges, small text */
.hud-panel {
position: absolute;
background: rgba(11, 15, 25, 0.85);
border: 1px solid rgba(100, 116, 139, 0.3);
backdrop-filter: blur(8px);
padding: 12px 16px;
border-radius: 4px;
pointer-events: none;
z-index: 10;
}
.hud-top-left {
top: 20px;
left: 20px;
border-left: 3px solid var(--color-normal);
transition: border-color 0.3s ease;
}
.hud-bottom-right {
bottom: 20px;
right: 20px;
text-align: right;
max-width: 320px;
}
.hud-title {
font-size: 14px;
font-weight: bold;
letter-spacing: 1px;
margin-bottom: 4px;
color: #fff;
}
.hud-text {
font-size: 12px;
color: var(--text-muted);
line-height: 1.5;
}
.status-indicator {
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
margin-right: 6px;
background-color: var(--color-normal);
box-shadow: 0 0 8px var(--color-normal);
}
/* SVG Element Styles */
.component-box {
fill: rgba(15, 23, 42, 0.9);
stroke: var(--text-muted);
stroke-width: 2;
rx: 6;
transition: stroke 0.3s, fill 0.3s;
}
.component-text {
fill: var(--text-main);
font-size: 14px;
font-family: var(--font-mono);
text-anchor: middle;
dominant-baseline: middle;
font-weight: bold;
}
.sub-text {
fill: var(--text-muted);
font-size: 10px;
text-anchor: middle;
}
.data-line {
fill: none;
stroke: var(--text-muted);
stroke-width: 2;
opacity: 0.3;
}
.flow-line {
fill: none;
stroke-width: 2.5;
stroke-dasharray: 8 8;
opacity: 0;
transition: opacity 0.3s;
}
/* Animations */
@keyframes flow {
to { stroke-dashoffset: -32; }
}
@keyframes pulse-alarm {
0%, 100% { stroke: var(--color-danger); filter: drop-shadow(0 0 8px var(--color-danger)); }
50% { stroke: #991b1b; filter: none; }
}
@keyframes pulse-sync {
0%, 100% { opacity: 0.4; }
50% { opacity: 1; }
}
/* State Classes */
/* 1. Normal State */
.state-normal .main-plc { stroke: var(--color-normal); }
.state-normal .standby-plc { stroke: var(--color-standby); }
.state-normal .flow-main { stroke: var(--color-normal); opacity: 1; animation: flow 1s linear infinite; }
.state-normal .flow-sync { stroke: var(--color-standby); opacity: 0.6; animation: flow 2s linear infinite, pulse-sync 2s infinite; }
.state-normal .hud-top-left { border-color: var(--color-normal); }
.state-normal #status-dot { background: var(--color-normal); box-shadow: 0 0 8px var(--color-normal); }
/* 2. Main PLC Fail State */
.state-plc-fail .main-plc { animation: pulse-alarm 1s infinite; }
.state-plc-fail .main-plc-text { fill: var(--color-danger); }
.state-plc-fail .standby-plc { stroke: var(--color-normal); filter: drop-shadow(0 0 8px var(--color-normal)); }
.state-plc-fail .flow-standby { stroke: var(--color-normal); opacity: 1; animation: flow 1s linear infinite; }
.state-plc-fail .hud-top-left { border-color: var(--color-standby); }
.state-plc-fail #status-dot { background: var(--color-standby); box-shadow: 0 0 8px var(--color-standby); }
/* 3. Total Fail & Hardwire State */
.state-total-fail .main-plc, .state-total-fail .standby-plc, .state-total-fail .sensor-box { animation: pulse-alarm 0.5s infinite; }
.state-total-fail .hardwire-box { stroke: var(--color-hardwire); filter: drop-shadow(0 0 12px var(--color-hardwire)); fill: rgba(249, 115, 22, 0.1); }
.state-total-fail .flow-hardwire { stroke: var(--color-hardwire); opacity: 1; stroke-dasharray: 12 6; animation: flow 0.5s linear infinite; }
.state-total-fail .valve-core { fill: var(--color-hardwire); transform: rotate(90deg); transform-origin: 500px 580px; transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1); }
.state-total-fail .hud-top-left { border-color: var(--color-danger); }
.state-total-fail #status-dot { background: var(--color-danger); box-shadow: 0 0 8px var(--color-danger); }
/* Independent Power */
.power-line { fill: none; stroke: var(--color-hardwire); stroke-width: 2; stroke-dasharray: 4 4; opacity: 0.5; }
.state-total-fail .power-line { opacity: 1; animation: flow 1s linear infinite; }
</style>
</head>
<body>
<!-- Top Left HUD: System Status -->
<div class="hud-panel hud-top-left" id="status-hud">
<div class="hud-title"><span class="status-indicator" id="status-dot"></span><span id="status-title">系统正常运行</span></div>
<div class="hud-text" id="status-desc">主控 PLC 掌握控制权,备用系统实时同步热备。</div>
</div>
<!-- Bottom Right HUD: Principle Explanation -->
<div class="hud-panel hud-bottom-right">
<div class="hud-title">最终理想解 (IFR) 架构</div>
<div class="hud-text">
极简冗余逻辑:<br>
1. 硬件双机热备 (切换时间 ≤ 0.5s)<br>
2. 独立供电硬接线回路 (规避系统性瘫痪)<br>
3. 极端工况下自动降级为物理泄放模式
</div>
</div>
<div id="animation-container" class="state-normal">
<svg viewBox="0 0 1000 700" preserveAspectRatio="xMidYMid meet">
<defs>
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="4" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<marker id="arrow-normal" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto">
<path d="M 0 0 L 10 5 L 0 10 z" fill="var(--color-normal)" />
</marker>
<marker id="arrow-hardwire" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto">
<path d="M 0 0 L 10 5 L 0 10 z" fill="var(--color-hardwire)" />
</marker>
<!-- Tank Pattern -->
<pattern id="tank-hatch" width="10" height="10" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse">
<line x1="0" y1="0" x2="0" y2="10" stroke="rgba(255,255,255,0.05)" stroke-width="2" />
</pattern>
</defs>
<!-- Background Context -->
<text x="500" y="40" fill="var(--text-muted)" font-size="12" text-anchor="middle" letter-spacing="4">DRILLING PLATFORM FLUID CONTROL SYSTEM</text>
<line x1="100" y1="650" x2="900" y2="650" stroke="var(--grid-color)" stroke-width="4" />
<!-- ================= HARDWARE COMPONENTS ================= -->
<!-- Central Tank -->
<g id="tank-group" transform="translate(400, 200)">
<!-- Tank Body Outline -->
<rect x="0" y="0" width="200" height="300" fill="url(#tank-hatch)" stroke="var(--text-muted)" stroke-width="3" rx="10" />
<!-- Fluid (Animated via JS) -->
<rect id="fluid-level" x="4" y="100" width="192" height="196" fill="var(--color-fluid)" opacity="0.6" rx="6" />
<path d="M 4 100 Q 50 90 100 100 T 196 100" fill="none" stroke="rgba(255,255,255,0.5)" stroke-width="2" id="fluid-surface"/>
<text x="100" y="40" fill="var(--text-muted)" font-size="14" text-anchor="middle" font-weight="bold">高压缓冲储罐</text>
</g>
<!-- Sensors -->
<g id="sensor-group" transform="translate(380, 250)">
<rect class="component-box sensor-box" x="-30" y="0" width="50" height="30" />
<text class="sub-text" x="-5" y="15">LVS-1</text>
<line x1="20" y1="15" x2="40" y2="15" stroke="var(--text-muted)" stroke-width="2" />
<rect class="component-box sensor-box" x="-30" y="100" width="50" height="30" />
<text class="sub-text" x="-5" y="115">PRS-2</text>
<line x1="20" y1="115" x2="40" y2="115" stroke="var(--text-muted)" stroke-width="2" />
</g>
<!-- Valve -->
<g id="valve-group" transform="translate(470, 520)">
<rect x="25" y="-20" width="10" height="20" fill="var(--text-muted)" /> <!-- Pipe connection -->
<path d="M 0 0 L 60 40 L 0 40 L 60 0 Z" fill="rgba(15,23,42,0.9)" stroke="var(--text-muted)" stroke-width="2" />
<circle class="valve-core" cx="30" cy="20" r="12" fill="var(--text-muted)" />
<rect class="valve-core" x="27" y="5" width="6" height="30" fill="#0b0f19" /> <!-- Indicator -->
<rect x="25" y="40" width="10" height="40" fill="var(--text-muted)" /> <!-- Outlet pipe -->
<!-- Fluid Drain Animation Particle Path -->
<path id="drain-flow" d="M 30 40 L 30 100" class="flow-line flow-hardwire" stroke-width="4" stroke="var(--color-fluid)" />
</g>
<!-- PLCs -->
<g id="plcs">
<!-- Main PLC -->
<rect class="component-box main-plc" x="100" y="100" width="160" height="80" />
<text class="component-text main-plc-text" x="180" y="135">主控 PLC (A机)</text>
<text class="sub-text" x="180" y="155">Master Control</text>
<!-- Standby PLC -->
<rect class="component-box standby-plc" x="740" y="100" width="160" height="80" />
<text class="component-text standby-plc-text" x="820" y="135">备用 PLC (B机)</text>
<text class="sub-text" x="820" y="155">Hot Standby</text>
</g>
<!-- Hardwired Safety Loop -->
<g id="hardwire-module" transform="translate(100, 480)">
<rect class="component-box hardwire-box" x="0" y="0" width="160" height="80" />
<text class="component-text" x="80" y="35">硬接线安全回路</text>
<text class="sub-text" x="80" y="55">独立继电器控制</text>
<!-- Independent Power Source -->
<circle cx="20" cy="110" r="12" fill="none" stroke="var(--color-hardwire)" stroke-width="2" />
<text x="20" y="114" fill="var(--color-hardwire)" font-size="12" text-anchor="middle">⚡</text>
<text class="sub-text" x="80" y="113" fill="var(--text-muted)">独立 UPS 供电</text>
<path d="M 35 110 L 80 110 L 80 80" class="power-line" />
</g>
<!-- ================= CONNECTIONS & DATA FLOWS ================= -->
<!-- Static Base Lines -->
<!-- Sensors to Main PLC -->
<path d="M 350 265 L 180 265 L 180 180" class="data-line" />
<path d="M 350 365 L 220 365 L 220 180" class="data-line" />
<!-- Sensors to Standby PLC -->
<path d="M 350 265 L 300 265 L 300 80 L 820 80 L 820 100" class="data-line" />
<!-- PLC Heartbeat -->
<path d="M 260 140 L 740 140" class="data-line" />
<!-- Main PLC to Valve -->
<path d="M 200 180 L 200 540 L 470 540" class="data-line" />
<!-- Standby PLC to Valve -->
<path d="M 800 180 L 800 540 L 530 540" class="data-line" />
<!-- Hardwire to Valve (Direct) -->
<path d="M 260 520 L 470 520" class="data-line" stroke="var(--color-hardwire)" stroke-dasharray="4 4" />
<!-- Animated Flow Lines (Overlays) -->
<!-- 1. Normal Flow (Main PLC active) -->
<g class="flow-main">
<path d="M 350 265 L 180 265 L 180 180" class="flow-line flow-main" />
<path d="M 350 365 L 220 365 L 220 180" class="flow-line flow-main" />
<path d="M 200 180 L 200 540 L 465 540" class="flow-line flow-main" marker-end="url(#arrow-normal)" />
</g>
<!-- Heartbeat Sync (Main to Standby) -->
<path d="M 260 140 L 735 140" class="flow-line flow-sync" marker-end="url(#arrow-normal)" />
<!-- 2. Standby Flow (Activated when Main fails) -->
<g class="flow-standby">
<path d="M 350 265 L 300 265 L 300 80 L 820 80 L 820 95" class="flow-line flow-standby" />
<path d="M 800 180 L 800 540 L 535 540" class="flow-line flow-standby" marker-end="url(#arrow-normal)" />
</g>
<!-- 3. Hardwire Flow (Activated on total digital failure) -->
<g class="flow-hardwire">
<!-- Direct command bypassing digital logic -->
<path d="M 260 520 L 465 520" class="flow-line flow-hardwire" marker-end="url(#arrow-hardwire)" filter="url(#glow)" />
</g>
</svg>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const container = document.getElementById('animation-container');
const body = document.body;
const titleEl = document.getElementById('status-title');
const descEl = document.getElementById('status-desc');
const fluidLevel = document.getElementById('fluid-level');
const fluidSurface = document.getElementById('fluid-surface');
// Animation States Configuration
const states = [
{
id: 'state-normal',
title: '系统正常运行',
desc: '主控 PLC (A机) 掌握控制权读取传感数据,备用 PLC (B机) 实时同步热备。',
duration: 4000,
alarm: false
},
{
id: 'state-plc-fail',
title: '主控 PLC 故障 - 无缝切换 (<0.5s)',
desc: 'A机通讯中断。冗余控制链激活,B机瞬间接管控制权,维持系统连续性。',
duration: 4000,
alarm: false
},
{
id: 'state-total-fail',
title: '极端通讯瘫痪 - 自动泄放模式',
desc: '传感器全部失效。硬接线安全回路利用独立电源强制打开蝶阀,执行物理防溢流保护 (IFR)。',
duration: 6000,
alarm: true
}
];
let currentStateIndex = 0;
let drainAnimationReq;
let fluidY = 100;
let fluidH = 196;
function updateState() {
const state = states[currentStateIndex];
// Update Classes
container.className = state.id;
if(state.alarm) {
body.classList.add('alarm-state');
} else {
body.classList.remove('alarm-state');
}
// Update HUD
titleEl.textContent = state.title;
descEl.innerHTML = state.desc;
// Handle specific SVG animations via JS for better control
cancelAnimationFrame(drainAnimationReq);
if (state.id === 'state-total-fail') {
// Animate fluid draining
const drain = () => {
if (fluidH > 20) {
fluidH -= 0.5;
fluidY += 0.5;
fluidLevel.setAttribute('height', fluidH);
fluidLevel.setAttribute('y', fluidY);
// Update surface curve y position
fluidSurface.setAttribute('d', `M 4 ${fluidY} Q 50 ${fluidY - 10} 100 ${fluidY} T 196 ${fluidY}`);
drainAnimationReq = requestAnimationFrame(drain);
}
};
drain();
} else {
// Reset fluid
fluidY = 100;
fluidH = 196;
fluidLevel.setAttribute('height', fluidH);
fluidLevel.setAttribute('y', fluidY);
fluidSurface.setAttribute('d', `M 4 100 Q 50 90 100 100 T 196 100`);
}
// Schedule next state
setTimeout(() => {
currentStateIndex = (currentStateIndex + 1) % states.length;
updateState();
}, state.duration);
}
// Start animation loop immediately
updateState();
});
</script>
</body>
</html>
积分规则:每轮对话扣10分
等待动画代码生成...
