分享图
动画工坊
引擎就绪
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AI 智能视觉跑浆监测系统</title>
    <style>
        :root {
            --bg-base: #050810;
            --bg-panel: rgba(13, 17, 28, 0.85);
            --grid-color: rgba(43, 76, 126, 0.15);
            --ai-cyan: #00f3ff;
            --ai-cyan-glow: rgba(0, 243, 255, 0.6);
            --safe-green: #00ff66;
            --danger-red: #ff3333;
            --danger-orange: #ff9900;
            --metal-dark: #1a202c;
            --metal-light: #2d3748;
            --text-main: #e2e8f0;
            --text-muted: #718096;
            --font-mono: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace;
            --font-sans: system-ui, -apple-system, sans-serif;
        }

        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            background-color: var(--bg-base);
            font-family: var(--font-sans);
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
            color: var(--text-main);
        }

        .container {
            position: relative;
            width: 100%;
            height: 100%;
            max-width: 1600px;
            max-height: 900px;
            display: flex;
            justify-content: center;
            align-items: center;
            box-shadow: inset 0 0 100px rgba(0, 0, 0, 0.8);
        }

        svg {
            width: 100%;
            height: 100%;
            display: block;
        }

        /* Peripheral UI Elements - Strict placement rules applied */
        .hud-panel {
            position: absolute;
            background: var(--bg-panel);
            border: 1px solid rgba(0, 243, 255, 0.2);
            border-radius: 4px;
            padding: 12px;
            font-size: 11px;
            font-family: var(--font-mono);
            color: var(--text-muted);
            backdrop-filter: blur(4px);
            z-index: 10;
            pointer-events: none;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
        }

        .hud-panel::before {
            content: '';
            position: absolute;
            top: 0; left: 0; width: 6px; height: 6px;
            border-top: 1px solid var(--ai-cyan);
            border-left: 1px solid var(--ai-cyan);
        }
        .hud-panel::after {
            content: '';
            position: absolute;
            bottom: 0; right: 0; width: 6px; height: 6px;
            border-bottom: 1px solid var(--ai-cyan);
            border-right: 1px solid var(--ai-cyan);
        }

        .hud-title {
            color: var(--ai-cyan);
            font-size: 13px;
            font-weight: bold;
            margin-bottom: 8px;
            text-transform: uppercase;
            letter-spacing: 1px;
        }

        .hud-top-left { top: 20px; left: 20px; width: 220px; }
        .hud-top-right { top: 20px; right: 20px; width: 240px; }
        .hud-bottom-left { bottom: 20px; left: 20px; width: 260px; }
        .hud-bottom-right { bottom: 20px; right: 20px; width: 220px; }

        .data-row {
            display: flex;
            justify-content: space-between;
            margin-bottom: 4px;
            border-bottom: 1px solid rgba(255,255,255,0.05);
            padding-bottom: 2px;
        }
        
        .data-label { color: var(--text-muted); }
        .data-value { color: var(--text-main); font-weight: bold; }
        .val-cyan { color: var(--ai-cyan); }
        .val-green { color: var(--safe-green); }
        .val-red { color: var(--danger-red); }

        .log-container {
            height: 80px;
            overflow: hidden;
            display: flex;
            flex-direction: column;
            justify-content: flex-end;
        }
        .log-entry { margin-bottom: 2px; opacity: 0.8; }
        .log-time { color: var(--text-muted); margin-right: 6px; }

        /* SVG Animations */
        @keyframes scan-sweep {
            0% { transform: translateY(0) scaleY(1); opacity: 0.8; }
            50% { transform: translateY(180px) scaleY(0.2); opacity: 0.3; }
            100% { transform: translateY(0) scaleY(1); opacity: 0.8; }
        }
        .anim-scan {
            transform-origin: 600px 220px;
            animation: scan-sweep 3s ease-in-out infinite;
        }

        @keyframes flow-move {
            0% { stroke-dashoffset: 100; }
            100% { stroke-dashoffset: 0; }
        }
        .anim-flow {
            stroke-dasharray: 10 5;
            animation: flow-move 1.5s linear infinite;
        }

        @keyframes pulse-ring {
            0% { transform: scale(0.8); opacity: 0.8; }
            100% { transform: scale(2); opacity: 0; }
        }

        @keyframes data-stream {
            0% { stroke-dashoffset: 50; }
            100% { stroke-dashoffset: 0; }
        }
        .anim-data {
            stroke-dasharray: 4 6;
            animation: data-stream 0.8s linear infinite;
        }
        
        @keyframes box-flash {
            0%, 100% { opacity: 1; }
            50% { opacity: 0.4; }
        }
        .anim-flash {
            animation: box-flash 0.5s ease-in-out infinite;
        }
        
        @keyframes float-foam {
            0%, 100% { transform: translateY(0); }
            50% { transform: translateY(-3px); }
        }
    </style>
</head>
<body>

    <div class="container">
        <!-- Overlay UI Panels (Strictly constrained to corners) -->
        <div class="hud-panel hud-top-left">
            <div class="hud-title">System Status</div>
            <div class="data-row"><span class="data-label">MODE</span><span class="data-value val-cyan">AUTO_INFER</span></div>
            <div class="data-row"><span class="data-label">CAMERA_FPS</span><span class="data-value">60.00</span></div>
            <div class="data-row"><span class="data-label">RESOLUTION</span><span class="data-value">1920x1080</span></div>
            <div class="data-row"><span class="data-label">ILLUMINATION</span><span class="data-value">ADAPTIVE_ON</span></div>
        </div>

        <div class="hud-panel hud-top-right">
            <div class="hud-title">AI Edge Compute</div>
            <div class="data-row"><span class="data-label">MODEL</span><span class="data-value">DeepSeg_v4.2</span></div>
            <div class="data-row"><span class="data-label">INFERENCE_MS</span><span class="data-value val-green" id="infer-time">12.4ms</span></div>
            <div class="data-row"><span class="data-label">CONFIDENCE</span><span class="data-value val-cyan" id="avg-conf">0.96</span></div>
            <div class="data-row"><span class="data-label">RUN_OFF_PROB</span><span class="data-value" id="danger-prob">0.02</span></div>
        </div>

        <div class="hud-panel hud-bottom-left">
            <div class="hud-title">Semantic Analysis Log</div>
            <div class="log-container" id="terminal-log">
                <!-- Logs injected via JS -->
            </div>
        </div>

        <div class="hud-panel hud-bottom-right">
            <div class="hud-title">PLC Control Output</div>
            <div class="data-row"><span class="data-label">CONN_STATE</span><span class="data-value val-green">ESTABLISHED</span></div>
            <div class="data-row"><span class="data-label">SHAKER_FREQ</span><span class="data-value" id="plc-freq">45 Hz</span></div>
            <div class="data-row"><span class="data-label">SCREEN_ANGLE</span><span class="data-value" id="plc-angle">2.5°</span></div>
            <div class="data-row"><span class="data-label">LATEST_CMD</span><span class="data-value val-cyan" id="plc-cmd">KEEP_NORMAL</span></div>
        </div>

        <!-- Main Animation Area -->
        <svg viewBox="0 0 1200 800" preserveAspectRatio="xMidYMid meet" id="main-svg">
            <defs>
                <!-- Background Grid -->
                <pattern id="grid" width="40" height="40" patternUnits="userSpaceOnUse">
                    <path d="M 40 0 L 0 0 0 40" fill="none" stroke="var(--grid-color)" stroke-width="0.5"/>
                    <circle cx="40" cy="40" r="1" fill="var(--grid-color)"/>
                </pattern>

                <!-- Filters for Neon Glow -->
                <filter id="glow-cyan" x="-20%" y="-20%" width="140%" height="140%">
                    <feGaussianBlur stdDeviation="5" result="blur" />
                    <feComposite in="SourceGraphic" in2="blur" operator="over" />
                </filter>
                <filter id="glow-red" x="-20%" y="-20%" width="140%" height="140%">
                    <feGaussianBlur stdDeviation="8" result="blur" />
                    <feComposite in="SourceGraphic" in2="blur" operator="over" />
                </filter>
                <filter id="glow-green" x="-20%" y="-20%" width="140%" height="140%">
                    <feGaussianBlur stdDeviation="4" result="blur" />
                    <feComposite in="SourceGraphic" in2="blur" operator="over" />
                </filter>
                
                <!-- Gradients -->
                <linearGradient id="cone-gradient" x1="0%" y1="0%" x2="0%" y2="100%">
                    <stop offset="0%" stop-color="var(--ai-cyan)" stop-opacity="0.4" />
                    <stop offset="100%" stop-color="var(--ai-cyan)" stop-opacity="0.05" />
                </linearGradient>
                <linearGradient id="slurry-grad" x1="0%" y1="0%" x2="100%" y2="100%">
                    <stop offset="0%" stop-color="#3d4956" />
                    <stop offset="50%" stop-color="#2d3748" />
                    <stop offset="100%" stop-color="#1a202c" />
                </linearGradient>

                <!-- Screen Mesh Pattern -->
                <pattern id="mesh" width="8" height="8" patternUnits="userSpaceOnUse" patternTransform="rotate(15)">
                    <path d="M 8 0 L 0 0 0 8" fill="none" stroke="#4a5568" stroke-width="0.5"/>
                </pattern>
            </defs>

            <!-- 1. Background Layer -->
            <rect width="100%" height="100%" fill="url(#grid)" />
            
            <!-- Contextual Technical Lines -->
            <path d="M0,400 L1200,400 M600,0 L600,800" stroke="var(--grid-color)" stroke-width="1" stroke-dasharray="2 4"/>
            <circle cx="600" cy="400" r="300" fill="none" stroke="var(--grid-color)" stroke-width="0.5" />

            <!-- 2. Infrastructure Layer (Shaker & Hardware) -->
            <g id="hardware">
                <!-- PLC Node (Left) -->
                <g transform="translate(150, 550)">
                    <rect x="-60" y="-80" width="120" height="160" fill="var(--metal-dark)" stroke="#4a5568" stroke-width="2" rx="4"/>
                    <rect x="-50" y="-70" width="100" height="30" fill="#000" />
                    <text x="0" y="-50" font-family="var(--font-mono)" font-size="12" fill="var(--safe-green)" text-anchor="middle">PLC_NODE</text>
                    <!-- Indicators -->
                    <circle cx="-40" cy="-20" r="4" fill="var(--safe-green)" id="plc-led-1" filter="url(#glow-green)"/>
                    <circle cx="-20" cy="-20" r="4" fill="var(--ai-cyan)" id="plc-led-2" />
                    <circle cx="0" cy="-20" r="4" fill="#333" id="plc-led-3" />
                    <!-- Data Link to Shaker -->
                    <path d="M60,0 L180,0 L200,50" fill="none" stroke="#4a5568" stroke-width="2" />
                    <path d="M60,0 L180,0 L200,50" fill="none" stroke="var(--ai-cyan)" stroke-width="2" class="anim-data" id="link-plc-shaker" opacity="0.3"/>
                </g>

                <!-- Edge AI Box (Right) -->
                <g transform="translate(1050, 300)">
                    <rect x="-70" y="-50" width="140" height="100" fill="var(--metal-dark)" stroke="var(--ai-cyan)" stroke-width="2" rx="4"/>
                    <rect x="-60" y="-40" width="120" height="80" fill="#000" />
                    <text x="0" y="-20" font-family="var(--font-mono)" font-size="12" fill="var(--ai-cyan)" text-anchor="middle" font-weight="bold">AI EDGE CORE</text>
                    <path d="M-40,10 L40,10 M-40,20 L20,20" stroke="var(--ai-cyan)" stroke-width="2" opacity="0.5"/>
                    <circle cx="45" cy="20" r="3" fill="var(--safe-green)" filter="url(#glow-green)">
                        <animate attributeName="opacity" values="1;0;1" dur="1s" repeatCount="indefinite"/>
                    </circle>
                    <!-- Data Link to PLC -->
                    <path d="M-70,0 L-750,0 L-850,200 L-900,200" fill="none" stroke="#4a5568" stroke-width="1" stroke-dasharray="4 4"/>
                    <path d="M-70,0 L-750,0 L-850,200 L-900,200" fill="none" stroke="var(--safe-green)" stroke-width="2" class="anim-data" id="link-ai-plc" opacity="0"/>
                </g>

                <!-- Shaker Screen Assembly (Center, 2.5D projection) -->
                <g transform="translate(600, 500)">
                    <!-- Base frame -->
                    <polygon points="-250,150 250,150 280,100 -220,100" fill="var(--metal-dark)" stroke="#333" stroke-width="2"/>
                    <!-- Springs -->
                    <path d="M-200,125 Q-210,135 -200,145 Q-190,135 -200,125" fill="none" stroke="var(--metal-light)" stroke-width="4"/>
                    <path d="M200,125 Q190,135 200,145 Q210,135 200,125" fill="none" stroke="var(--metal-light)" stroke-width="4"/>
                    <!-- Screen Mesh Surface (Angled) -->
                    <polygon points="-200,100 200,100 280,-40 -120,-40" fill="url(#mesh)" stroke="#4a5568" stroke-width="2"/>
                    <polygon points="-200,100 200,100 280,-40 -120,-40" fill="rgba(0,0,0,0.4)"/> <!-- Depth shadow -->
                </g>
            </g>

            <!-- 3. Dynamic Material Layer (Slurry & Foam) -->
            <g transform="translate(600, 500)" id="material-group">
                <!-- Base slurry flow -->
                <path d="M-100,-30 C-40,-20 100,-35 200,0 C230,15 250,60 210,80 C100,100 -100,80 -180,60 C-200,40 -180,-10 -100,-30 Z" fill="url(#slurry-grad)" opacity="0.9"/>
                
                <!-- Flow animation lines to simulate movement -->
                <path d="M-80,-20 Q50,-10 180,20" fill="none" stroke="#4a5568" stroke-width="2" class="anim-flow"/>
                <path d="M-140,40 Q0,50 160,70" fill="none" stroke="#4a5568" stroke-width="2" class="anim-flow" style="animation-duration: 2s;"/>

                <!-- Foam clusters (Normal & Dangerous) -->
                <!-- Normal Foam -->
                <g id="foam-normal">
                    <circle cx="-50" cy="10" r="15" fill="#a0aec0" opacity="0.6"/>
                    <circle cx="-30" cy="5" r="20" fill="#a0aec0" opacity="0.7"/>
                    <circle cx="-60" cy="25" r="12" fill="#a0aec0" opacity="0.5"/>
                    <circle cx="50" cy="40" r="18" fill="#a0aec0" opacity="0.6"/>
                    <circle cx="70" cy="35" r="14" fill="#a0aec0" opacity="0.8"/>
                </g>

                <!-- Dangerous Foam (Hidden initially, shown by JS) -->
                <g id="foam-danger" opacity="0">
                    <circle cx="120" cy="10" r="25" fill="#f6ad55" opacity="0.8">
                        <animate attributeName="r" values="25;28;25" dur="1s" repeatCount="indefinite"/>
                    </circle>
                    <circle cx="150" cy="25" r="30" fill="#f6ad55" opacity="0.9">
                        <animate attributeName="r" values="30;35;30" dur="0.8s" repeatCount="indefinite"/>
                    </circle>
                    <circle cx="100" cy="30" r="18" fill="#f6ad55" opacity="0.7"/>
                    <!-- Overflow simulation -->
                    <path d="M160,50 Q180,80 200,100" fill="none" stroke="#f6ad55" stroke-width="4" opacity="0.8"/>
                </g>
            </g>

            <!-- 4. Top-Down Vision System (Camera & AI Scan) -->
            <g id="vision-system">
                <!-- Camera Body -->
                <g transform="translate(600, 100)">
                    <rect x="-25" y="-40" width="50" height="60" fill="var(--metal-dark)" stroke="var(--ai-cyan)" stroke-width="1" rx="5"/>
                    <rect x="-15" y="-30" width="30" height="40" fill="#000" rx="3"/>
                    <!-- Lens -->
                    <circle cx="0" cy="20" r="15" fill="var(--metal-light)" stroke="#111" stroke-width="2"/>
                    <circle cx="0" cy="20" r="10" fill="#000"/>
                    <circle cx="0" cy="20" r="4" fill="var(--ai-cyan)" filter="url(#glow-cyan)"/>
                    <!-- Mount -->
                    <path d="M0,-40 L0,-100 L200,-100" fill="none" stroke="var(--metal-light)" stroke-width="10" stroke-linejoin="round"/>
                    
                    <!-- Text Label -->
                    <text x="35" y="0" font-family="var(--font-mono)" font-size="10" fill="var(--ai-cyan)">EXP-CAM_01</text>
                    <text x="35" y="12" font-family="var(--font-mono)" font-size="8" fill="var(--text-muted)">60FPS/1080P</text>

                    <!-- Data link to AI -->
                    <path d="M0,-100 L450,-100 L450,200" fill="none" stroke="#4a5568" stroke-width="1" stroke-dasharray="4 4"/>
                    <path d="M0,-100 L450,-100 L450,200" fill="none" stroke="var(--ai-cyan)" stroke-width="2" class="anim-data"/>
                </g>

                <!-- Vision Cone & Scanning Effect -->
                <g id="scan-area">
                    <polygon points="600,135 380,560 820,560" fill="url(#cone-gradient)" />
                    <!-- Moving scan line -->
                    <path d="M 400,380 L 800,380" stroke="var(--ai-cyan)" stroke-width="3" filter="url(#glow-cyan)" class="anim-scan"/>
                </g>
            </g>

            <!-- 5. AI Semantic Segmentation Overlays (Controlled by JS) -->
            <!-- The TRIZ final ideal result: Direct identification without complex mechanical sensors -->
            <g id="ai-overlays" transform="translate(600, 500)">
                <!-- Bounding Box 1: Normal Slurry Area -->
                <g id="bbox-normal" opacity="0.8">
                    <rect x="-180" y="-20" width="120" height="90" fill="none" stroke="var(--safe-green)" stroke-width="1.5" stroke-dasharray="4 4" rx="2"/>
                    <rect x="-180" y="-36" width="90" height="16" fill="rgba(0, 255, 102, 0.2)" stroke="var(--safe-green)" stroke-width="1"/>
                    <text x="-176" y="-24" font-family="var(--font-mono)" font-size="10" fill="var(--safe-green)">SLURRY: 0.98</text>
                    <!-- Target crosshair -->
                    <path d="M-120,25 L-120,15 M-120,35 L-120,45 M-130,25 L-140,25 M-110,25 L-100,25" stroke="var(--safe-green)" stroke-width="1" opacity="0.5"/>
                </g>

                <!-- Bounding Box 2: Normal Foam -->
                <g id="bbox-foam" opacity="0.8">
                    <polygon points="-80,0 -20,-10 80,40 -20,60" fill="none" stroke="var(--ai-cyan)" stroke-width="1.5" stroke-linejoin="round"/>
                    <text x="-15" y="-15" font-family="var(--font-mono)" font-size="10" fill="var(--ai-cyan)">FOAM_NORM: 0.92</text>
                    <!-- Semantic mask points -->
                    <circle cx="-50" cy="10" r="1.5" fill="var(--ai-cyan)"/>
                    <circle cx="-30" cy="5" r="1.5" fill="var(--ai-cyan)"/>
                    <circle cx="50" cy="40" r="1.5" fill="var(--ai-cyan)"/>
                </g>

                <!-- Bounding Box 3: Dangerous Foam / Run-off (Initially hidden) -->
                <g id="bbox-danger" opacity="0">
                    <rect x="80" y="-10" width="110" height="80" fill="rgba(255, 51, 51, 0.1)" stroke="var(--danger-red)" stroke-width="2" rx="4" filter="url(#glow-red)" class="anim-flash"/>
                    <rect x="80" y="-28" width="110" height="18" fill="var(--danger-red)"/>
                    <text x="84" y="-15" font-family="var(--font-mono)" font-size="11" fill="#fff" font-weight="bold">! RUN_OFF_RISK</text>
                    <text x="84" y="60" font-family="var(--font-mono)" font-size="10" fill="var(--danger-red)">CONF: 0.99</text>
                    <text x="84" y="75" font-family="var(--font-mono)" font-size="10" fill="var(--danger-red)">VOL: +45%</text>
                    <!-- Crosshair tracking danger -->
                    <circle cx="135" cy="20" r="8" fill="none" stroke="var(--danger-red)" stroke-width="1"/>
                    <circle cx="135" cy="20" r="2" fill="var(--danger-red)"/>
                </g>
                
                <!-- Cross Validation Line (Virtual Level Gauge integration) -->
                <g id="cross-validation" opacity="0.6">
                     <path d="M-220,10 L250,10" stroke="var(--ai-cyan)" stroke-width="0.5" stroke-dasharray="2 4"/>
                     <text x="255" y="13" font-family="var(--font-mono)" font-size="8" fill="var(--ai-cyan)">LVL_BASE</text>
                     <path d="M-220,50 L250,50" stroke="var(--danger-red)" stroke-width="0.5" stroke-dasharray="2 4"/>
                     <text x="255" y="53" font-family="var(--font-mono)" font-size="8" fill="var(--danger-red)">LVL_CRIT</text>
                </g>
            </g>
        </svg>
    </div>

    <!-- Core Simulation Logic -->
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            // DOM Elements
            const bboxDanger = document.getElementById('bbox-danger');
            const foamDanger = document.getElementById('foam-danger');
            const bboxFoam = document.getElementById('bbox-foam');
            const linkAiPlc = document.getElementById('link-ai-plc');
            const linkPlcShaker = document.getElementById('link-plc-shaker');
            
            // HUD Elements
            const dangerProbText = document.getElementById('danger-prob');
            const avgConfText = document.getElementById('avg-conf');
            const inferTimeText = document.getElementById('infer-time');
            const plcCmdText = document.getElementById('plc-cmd');
            const plcFreqText = document.getElementById('plc-freq');
            const plcLed3 = document.getElementById('plc-led-3');
            const terminalLog = document.getElementById('terminal-log');

            // Utilities
            const getTimestamp = () => {
                const now = new Date();
                return `${now.getHours().toString().padStart(2,'0')}:${now.getMinutes().toString().padStart(2,'0')}:${now.getSeconds().toString().padStart(2,'0')}.${now.getMilliseconds().toString().padStart(3,'0')}`;
            };

            const addLog = (msg, isDanger = false) => {
                const p = document.createElement('div');
                p.className = 'log-entry';
                const color = isDanger ? 'var(--danger-red)' : 'var(--text-main)';
                p.innerHTML = `<span class="log-time">[${getTimestamp()}]</span> <span style="color:${color}">${msg}</span>`;
                terminalLog.appendChild(p);
                if (terminalLog.children.length > 5) {
                    terminalLog.removeChild(terminalLog.firstChild);
                }
            };

            // Simulation State Machine
            // TRIZ Focus: Displaying the transition from ideal normal state to automatic detection of anomaly
            // without physical contact sensors.
            let phase = 0;
            
            const runSimulationCycle = () => {
                
                // Randomize minor inference fluctuations to look alive
                inferTimeText.innerText = (12.0 + Math.random() * 1.5).toFixed(1) + 'ms';
                
                if (phase === 0) {
                    // Normal Operation Phase
                    bboxDanger.setAttribute('opacity', '0');
                    foamDanger.setAttribute('opacity', '0');
                    bboxFoam.setAttribute('opacity', '0.8');
                    linkAiPlc.setAttribute('opacity', '0');
                    linkPlcShaker.setAttribute('stroke', 'var(--ai-cyan)');
                    
                    dangerProbText.innerText = '0.0' + Math.floor(Math.random() * 5);
                    dangerProbText.className = 'data-value';
                    avgConfText.innerText = '0.9' + (4 + Math.floor(Math.random() * 5));
                    
                    plcCmdText.innerText = 'KEEP_NORMAL';
                    plcCmdText.className = 'data-value val-cyan';
                    plcFreqText.innerText = '45 Hz';
                    plcLed3.setAttribute('fill', '#333');
                    plcLed3.removeAttribute('filter');

                    if(Math.random() > 0.6) addLog('Frame infer: Slurry OK, Foam Norm.');

                    setTimeout(() => { phase = 1; }, 3000); // Stay normal for 3s
                } 
                else if (phase === 1) {
                    // Anomaly Emerging Phase (Pao Jiang starting)
                    addLog('WARN: Foam volume increasing...', true);
                    foamDanger.setAttribute('opacity', '0.5'); // Start showing physical danger
                    dangerProbText.innerText = '0.45';
                    dangerProbText.className = 'data-value val-orange';
                    
                    setTimeout(() => { phase = 2; }, 1500); // 1.5s build up
                }
                else if (phase === 2) {
                    // AI Detection & Alert Phase (The Innovation Point)
                    // High-speed semantic segmentation catches it instantly
                    addLog('CRITICAL: Run-off (Pao Jiang) detected!', true);
                    addLog('Semantic Mask conf: 0.99', true);
                    
                    foamDanger.setAttribute('opacity', '1');
                    bboxDanger.setAttribute('opacity', '1'); // Red box appears
                    bboxFoam.setAttribute('opacity', '0.3'); // Dim normal box
                    
                    dangerProbText.innerText = '0.99';
                    dangerProbText.className = 'data-value val-red';
                    
                    // Trigger data flow to PLC
                    linkAiPlc.setAttribute('opacity', '1');
                    linkAiPlc.setAttribute('stroke', 'var(--danger-red)');
                    
                    setTimeout(() => { phase = 3; }, 1500);
                }
                else if (phase === 3) {
                    // PLC Action Phase
                    addLog('Action: Sending control signal to PLC', false);
                    plcCmdText.innerText = 'REDUCE_FREQ';
                    plcCmdText.className = 'data-value val-red';
                    plcFreqText.innerText = '35 Hz';
                    
                    plcLed3.setAttribute('fill', 'var(--danger-red)');
                    plcLed3.setAttribute('filter', 'url(#glow-red)');
                    
                    linkPlcShaker.setAttribute('stroke', 'var(--danger-red)');

                    setTimeout(() => { phase = 4; }, 2000); // PLC acts for 2s
                }
                else if (phase === 4) {
                    // Resolution Phase (Returning to ideal state)
                    addLog('Status resolving. Foam level nominal.');
                    foamDanger.setAttribute('opacity', '0.2');
                    bboxDanger.setAttribute('opacity', '0');
                    linkAiPlc.setAttribute('opacity', '0');
                    
                    setTimeout(() => { phase = 0; }, 1000); // Restart loop
                }

                // Continuous loop
                setTimeout(runSimulationCycle, 100);
            };

            // Initial logs
            addLog('[SYSTEM] Booting AI Core...');
            addLog('[CAMERA] Exp-Cam 01 Stream Active');
            addLog('[MODEL] DeepSeg_v4.2 Loaded');
            
            // Start simulation loop after a slight delay
            setTimeout(runSimulationCycle, 1000);
        });
    </script>
</body>
</html>
积分规则:每轮对话扣10分