分享图
动画工坊
引擎就绪
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>高保真绝缘机械手原理动画 - 最终理想解(IFR)</title>
    <style>
        :root {
            --bg-color: #050914;
            --grid-color: rgba(32, 178, 170, 0.1);
            --primary-cyan: #00F0FF;
            --accent-orange: #FF5E00;
            --success-green: #39FF14;
            --tech-gray: #4A5568;
            --text-main: #E2E8F0;
            --text-muted: #718096;
            
            /* Animation Timings */
            --total-duration: 12s;
        }

        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            background-color: var(--bg-color);
            background-image: 
                linear-gradient(var(--grid-color) 1px, transparent 1px),
                linear-gradient(90deg, var(--grid-color) 1px, transparent 1px);
            background-size: 40px 40px;
            font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
            color: var(--text-main);
        }

        /* ---------------- Layout & HUD ---------------- */
        .hud-container {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            pointer-events: none;
            z-index: 10;
        }

        .panel {
            position: absolute;
            background: rgba(5, 9, 20, 0.85);
            border: 1px solid rgba(0, 240, 255, 0.3);
            padding: 16px;
            backdrop-filter: blur(4px);
        }

        .panel-top-left { top: 24px; left: 24px; max-width: 300px; border-left: 3px solid var(--primary-cyan); }
        .panel-top-right { top: 24px; right: 24px; text-align: right; border-right: 3px solid var(--success-green); }
        .panel-bottom { bottom: 24px; left: 50%; transform: translateX(-50%); display: flex; gap: 24px; border-top: 1px solid var(--primary-cyan); padding: 12px 24px; }

        .title { font-size: 16px; font-weight: bold; color: var(--primary-cyan); margin-bottom: 8px; letter-spacing: 1px; }
        .desc { font-size: 12px; color: var(--text-muted); line-height: 1.5; }
        .highlight { color: var(--accent-orange); font-weight: bold; }
        
        .data-row { display: flex; justify-content: space-between; margin-bottom: 6px; font-size: 12px; }
        .data-label { color: var(--text-muted); margin-right: 16px; }
        .data-value { color: var(--success-green); font-family: monospace; }

        .status-step { font-size: 12px; color: var(--tech-gray); transition: color 0.3s; display: flex; align-items: center; gap: 6px; }
        .status-step::before { content: ''; display: block; width: 6px; height: 6px; border-radius: 50%; background: var(--tech-gray); }
        .status-step.active { color: var(--primary-cyan); }
        .status-step.active::before { background: var(--primary-cyan); box-shadow: 0 0 8px var(--primary-cyan); }

        /* ---------------- SVG Container ---------------- */
        .svg-container {
            width: 100%;
            max-width: 1200px;
            height: 100%;
            max-height: 900px;
        }

        svg {
            width: 100%;
            height: 100%;
            overflow: visible;
        }

        /* ---------------- Animations ---------------- */
        
        /* 1. 全局升降 (举升装置) */
        .anim-lift {
            animation: liftSequence var(--total-duration) ease-in-out infinite;
        }
        @keyframes liftSequence {
            0%, 5% { transform: translateY(200px); opacity: 0; }
            15%, 85% { transform: translateY(0); opacity: 1; }
            95%, 100% { transform: translateY(200px); opacity: 0; }
        }

        /* 2. 底座螺旋锁紧 */
        .anim-screw {
            transform-origin: center 540px;
            animation: screwLock var(--total-duration) ease-in-out infinite;
        }
        @keyframes screwLock {
            0%, 15% { transform: translateY(40px) rotate(0deg); }
            25%, 85% { transform: translateY(0) rotate(720deg); }
            95%, 100% { transform: translateY(40px) rotate(0deg); }
        }

        /* 3. 绝缘杆上推推压夹爪 */
        .anim-rod-push {
            animation: rodPush var(--total-duration) ease-in-out infinite;
        }
        @keyframes rodPush {
            0%, 25% { transform: translateY(80px); }
            35%, 85% { transform: translateY(0); }
            90%, 100% { transform: translateY(80px); }
        }

        /* 4. 导线自重下沉 */
        .anim-wire-sink {
            animation: wireSink var(--total-duration) ease-in-out infinite;
        }
        @keyframes wireSink {
            0%, 35% { transform: translateY(-30px); }
            45%, 85% { transform: translateY(5px); }
            95%, 100% { transform: translateY(-30px); }
        }

        /* 5. 楔形自锁 (IFR 核心) */
        .anim-wedge-left {
            animation: wedgeLeftLock var(--total-duration) ease-out infinite;
        }
        .anim-wedge-right {
            animation: wedgeRightLock var(--total-duration) ease-out infinite;
        }
        @keyframes wedgeLeftLock {
            0%, 40% { transform: translate(-10px, -20px); }
            48%, 85% { transform: translate(3px, 5px); } /* 向下向内移动 */
            95%, 100% { transform: translate(-10px, -20px); }
        }
        @keyframes wedgeRightLock {
            0%, 40% { transform: translate(10px, -20px); }
            48%, 85% { transform: translate(-3px, 5px); } /* 向下向内移动 */
            95%, 100% { transform: translate(10px, -20px); }
        }

        /* 6. 核心力流特效展示 (IFR视觉引导) */
        .anim-force-line {
            stroke-dasharray: 10 5;
            animation: forceFlow 1s linear infinite, forceFade var(--total-duration) infinite;
        }
        @keyframes forceFlow {
            to { stroke-dashoffset: -15; }
        }
        @keyframes forceFade {
            0%, 45% { opacity: 0; }
            50%, 80% { opacity: 1; }
            85%, 100% { opacity: 0; }
        }

        .anim-lock-glow {
            animation: lockGlowPulse var(--total-duration) infinite;
        }
        @keyframes lockGlowPulse {
            0%, 45% { filter: drop-shadow(0 0 0px transparent); stroke: var(--tech-gray); }
            50%, 80% { filter: drop-shadow(0 0 12px var(--success-green)); stroke: var(--success-green); }
            85%, 100% { filter: drop-shadow(0 0 0px transparent); stroke: var(--tech-gray); }
        }

    </style>
</head>
<body>

    <!-- HUD 层,使用绝对定位,避免遮挡中央核心区域 -->
    <div class="hud-container">
        <div class="panel panel-top-left">
            <div class="title">TRIZ - 最终理想解 (IFR)</div>
            <div class="desc">
                系统利用<span class="highlight">导线自身的重力</span>作为核心驱动资源。无需外部复杂机械结构,导线下沉迫使楔形夹爪沿斜面下滑,自动转化为巨大的侧向夹紧力。<br/><br/>
                <span style="color:var(--primary-cyan)">消除矛盾:</span> 在极少增加系统复杂度的前提下,实现了地面快速挂载与高强度自锁的统一。
            </div>
        </div>

        <div class="panel panel-top-right">
            <div class="title">关键参数监控</div>
            <div class="data-row">
                <span class="data-label">楔形夹爪夹紧力:</span>
                <span class="data-value" id="val-force">0 N</span>
            </div>
            <div class="data-row">
                <span class="data-label">主杆绝缘耐压:</span>
                <span class="data-value">> 20 kV</span>
            </div>
            <div class="data-row">
                <span class="data-label">系统状态:</span>
                <span class="data-value" style="color:var(--primary-cyan)" id="val-status">初始举升</span>
            </div>
        </div>

        <div class="panel panel-bottom">
            <div class="status-step" id="step-1">1. 举升装置</div>
            <div class="status-step" id="step-2">2. 底座卡入锁紧</div>
            <div class="status-step" id="step-3">3. 上推压入导线</div>
            <div class="status-step" id="step-4">4. 导线自重触发自锁</div>
        </div>
    </div>

    <!-- 核心 SVG 动画区域 -->
    <div class="svg-container">
        <svg viewBox="0 0 1000 800" preserveAspectRatio="xMidYMid meet">
            <defs>
                <!-- 滤镜与渐变 -->
                <filter id="neon-cyan" x="-20%" y="-20%" width="140%" height="140%">
                    <feGaussianBlur stdDeviation="4" result="blur" />
                    <feMerge>
                        <feMergeNode in="blur" />
                        <feMergeNode in="SourceGraphic" />
                    </feMerge>
                </filter>
                <filter id="glow-orange">
                    <feGaussianBlur stdDeviation="6" result="blur" />
                    <feMerge>
                        <feMergeNode in="blur" />
                        <feMergeNode in="SourceGraphic" />
                    </feMerge>
                </filter>
                <linearGradient id="rod-grad" x1="0%" y1="0%" x2="100%" y2="0%">
                    <stop offset="0%" stop-color="#2D3748" />
                    <stop offset="50%" stop-color="#4A5568" />
                    <stop offset="100%" stop-color="#2D3748" />
                </linearGradient>
                <pattern id="metal-texture" width="10" height="10" patternUnits="userSpaceOnUse">
                    <path d="M 0,10 l 10,-10 M -2,2 l 4,-4 M 8,12 l 4,-4" stroke="#718096" stroke-width="0.5" opacity="0.3"/>
                </pattern>
                
                <!-- 箭头标记 -->
                <marker id="arrow-down" viewBox="0 0 10 10" refX="5" refY="10" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
                    <path d="M 0 0 L 5 10 L 10 0 z" fill="#FF5E00" />
                </marker>
                <marker id="arrow-inward" viewBox="0 0 10 10" refX="5" refY="10" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
                    <path d="M 0 0 L 5 10 L 10 0 z" fill="#39FF14" />
                </marker>
            </defs>

            <!-- 场景静物:横担 -->
            <g transform="translate(500, 500)">
                <rect x="-150" y="-30" width="300" height="60" fill="url(#metal-texture)" stroke="#A0AEC0" stroke-width="2" rx="4"/>
                <line x1="-150" y1="-15" x2="150" y2="-15" stroke="#718096" stroke-width="1"/>
                <line x1="-150" y1="15" x2="150" y2="15" stroke="#718096" stroke-width="1"/>
                <text x="-140" y="-40" fill="#718096" font-size="14" font-family="monospace">CROSSARM_STRUCT</text>
            </g>

            <!-- 动态系统整体 (举升控制) -->
            <g class="anim-lift">
                
                <!-- 底部倒U型卡线器与螺旋机构 -->
                <g transform="translate(500, 480)">
                    <!-- U型卡座 -->
                    <path d="M -60,60 L -60,-40 C -60,-50 -50,-60 -40,-60 L 40,-60 C 50,-60 60,-50 60,-40 L 60,60 L 40,60 L 40,-40 L -40,-40 L -40,60 Z" fill="#2D3748" stroke="var(--primary-cyan)" stroke-width="2" filter="url(#neon-cyan)"/>
                    
                    <!-- 旋转锁紧底座组件 -->
                    <g class="anim-screw">
                        <!-- 螺杆 -->
                        <rect x="-10" y="20" width="20" height="60" fill="#A0AEC0" stroke="#4A5568"/>
                        <!-- 螺纹细节 -->
                        <path d="M -10,30 L 10,25 M -10,40 L 10,35 M -10,50 L 10,45 M -10,60 L 10,55 M -10,70 L 10,65" stroke="#2D3748" stroke-width="2"/>
                        <!-- 压板 -->
                        <rect x="-35" y="10" width="70" height="15" fill="#4A5568" stroke="var(--primary-cyan)" stroke-width="1" rx="2"/>
                        <!-- 底部绝缘杆连接头 -->
                        <rect x="-25" y="80" width="50" height="30" fill="url(#rod-grad)" rx="5"/>
                        <path d="M -15,80 L -15,110 M 15,80 L 15,110" stroke="#1A202C" stroke-width="1"/>
                    </g>
                </g>

                <!-- 绝缘主杆与顶部机构 (上推控制) -->
                <g class="anim-rod-push">
                    <!-- 环氧树脂绝缘主杆 -->
                    <rect x="485" y="240" width="30" height="180" fill="url(#rod-grad)" stroke="#2D3748" stroke-width="2"/>
                    <text x="525" y="340" fill="#718096" font-size="12" font-family="monospace" transform="rotate(-90 525 340)">EPOXY_RESIN_ROD > 20kV</text>

                    <!-- 顶部夹爪底座 -->
                    <g transform="translate(500, 240)">
                        <path d="M -40,0 L 40,0 L 25,-40 L -25,-40 Z" fill="#2D3748" stroke="var(--primary-cyan)" stroke-width="2"/>
                        
                        <!-- 楔形夹爪外壳 (V型槽) -->
                        <path d="M -25,-40 L -55,-120 L -35,-120 L -10,-40 Z" fill="#1A202C" stroke="var(--tech-gray)" stroke-width="2" class="anim-lock-glow"/>
                        <path d="M 25,-40 L 55,-120 L 35,-120 L 10,-40 Z" fill="#1A202C" stroke="var(--tech-gray)" stroke-width="2" class="anim-lock-glow"/>

                        <!-- 左侧楔形滑块 -->
                        <g class="anim-wedge-left">
                            <!-- 楔形块 -->
                            <path d="M -30,-110 L -45,-110 L -20,-50 L -10,-50 Z" fill="#4A5568" stroke="var(--primary-cyan)" stroke-width="1"/>
                            <!-- 橡胶防滑垫 -->
                            <path d="M -28,-110 L -26,-110 L -8,-50 L -10,-50 Z" fill="#2D3748" stroke="#000"/>
                        </g>

                        <!-- 右侧楔形滑块 -->
                        <g class="anim-wedge-right">
                            <path d="M 30,-110 L 45,-110 L 20,-50 L 10,-50 Z" fill="#4A5568" stroke="var(--primary-cyan)" stroke-width="1"/>
                            <path d="M 28,-110 L 26,-110 L 8,-50 L 10,-50 Z" fill="#2D3748" stroke="#000"/>
                        </g>

                        <!-- IFR 视觉引导力线 (仅在锁紧时显示) -->
                        <g class="anim-force-line">
                            <!-- 导线重力向下 -->
                            <line x1="0" y1="-130" x2="0" y2="-90" stroke="var(--accent-orange)" stroke-width="3" marker-end="url(#arrow-down)"/>
                            <!-- 左侧侧向夹紧力 -->
                            <line x1="-40" y1="-70" x2="-15" y2="-70" stroke="var(--success-green)" stroke-width="3" marker-end="url(#arrow-inward)"/>
                            <!-- 右侧侧向夹紧力 -->
                            <line x1="40" y1="-70" x2="15" y2="-70" stroke="var(--success-green)" stroke-width="3" marker-end="url(#arrow-inward)"/>
                        </g>
                    </g>
                </g>
            </g>

            <!-- 导线 (受重力下沉) -->
            <g transform="translate(500, 160)" class="anim-wire-sink">
                <!-- 导线光晕 -->
                <circle cx="0" cy="0" r="15" fill="none" stroke="var(--accent-orange)" stroke-width="4" filter="url(#glow-orange)" opacity="0.5"/>
                <!-- 导线实体 -->
                <circle cx="0" cy="0" r="12" fill="#E2E8F0" stroke="var(--accent-orange)" stroke-width="3"/>
                <!-- 导线纹理 -->
                <circle cx="0" cy="0" r="6" fill="none" stroke="#718096" stroke-width="1" stroke-dasharray="2 2"/>
                <text x="25" y="-15" fill="var(--accent-orange)" font-size="14" font-weight="bold">CONDUCTOR_WIRE</text>
            </g>

        </svg>
    </div>

    <!-- JavaScript 用于同步文本状态和数据展示,增强高保真体验 -->
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const valStatus = document.getElementById('val-status');
            const valForce = document.getElementById('val-force');
            const steps = [
                document.getElementById('step-1'),
                document.getElementById('step-2'),
                document.getElementById('step-3'),
                document.getElementById('step-4')
            ];

            const totalDuration = 12000; // 与 CSS 变量 --total-duration 保持一致

            function updateStatus() {
                const now = Date.now();
                // 使用取模获取当前动画周期内的进度
                const progress = (now % totalDuration) / totalDuration;

                // 重置所有步骤样式
                steps.forEach(s => s.classList.remove('active'));

                // 状态机映射 (与 CSS Keyframes 对应)
                // 0-15%: 举升装置 (step 1)
                // 15-35%: 底座锁紧 (step 2)
                // 35-48%: 上推入线 (step 3)
                // 48-85%: 自重锁紧 (step 4, IFR阶段)
                // 85-100%: 撤离/重置

                if (progress < 0.15) {
                    steps[0].classList.add('active');
                    valStatus.textContent = "举升就位中...";
                    valStatus.style.color = "var(--text-main)";
                    valForce.textContent = "0 N";
                } else if (progress < 0.35) {
                    steps[1].classList.add('active');
                    valStatus.textContent = "底座螺旋锁紧";
                    valStatus.style.color = "var(--primary-cyan)";
                    valForce.textContent = "0 N";
                } else if (progress < 0.48) {
                    steps[2].classList.add('active');
                    valStatus.textContent = "推压导线入槽";
                    valStatus.style.color = "var(--accent-orange)";
                    valForce.textContent = "120 N (接触力)";
                } else if (progress < 0.85) {
                    steps[3].classList.add('active');
                    valStatus.textContent = "自锁完成 (IFR触发)";
                    valStatus.style.color = "var(--success-green)";
                    
                    // 模拟力值快速上升并稳定
                    let force = 800;
                    if(progress < 0.55) {
                        const ratio = (progress - 0.48) / 0.07;
                        force = Math.floor(120 + ratio * 695); // 到达 815
                    } else {
                        // 稳定在 800N 以上,带有微小扰动以增加真实感
                        force = 812 + Math.floor(Math.random() * 15);
                    }
                    valForce.textContent = `≥ ${force} N`;
                } else {
                    valStatus.textContent = "系统复位";
                    valStatus.style.color = "var(--text-muted)";
                    valForce.textContent = "0 N";
                }

                requestAnimationFrame(updateStatus);
            }

            // 启动状态更新循环
            requestAnimationFrame(updateStatus);
        });
    </script>
</body>
</html>
<!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-base: #0a0a0f;
            --grid-line: rgba(77, 208, 225, 0.05);
            --hud-cyan: #4DD0E1;
            --hud-cyan-dim: rgba(77, 208, 225, 0.3);
            --alert-red: #FF3366;
            --alert-amber: #FFB300;
            --text-main: #E0F7FA;
            --text-muted: #809C9F;
            --font-mono: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
        }

        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }

        body, html {
            width: 100%;
            height: 100%;
            background-color: var(--bg-base);
            background-image: 
                linear-gradient(var(--grid-line) 1px, transparent 1px),
                linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
            background-size: 50px 50px;
            font-family: var(--font-mono);
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
            color: var(--text-main);
        }

        /* ---------------- HUD 层布局 (严格控制字号与边缘位置) ---------------- */
        .hud-layer {
            position: absolute;
            top: 0; left: 0; right: 0; bottom: 0;
            pointer-events: none;
            z-index: 10;
        }

        .panel {
            position: absolute;
            background: rgba(10, 10, 15, 0.8);
            border: 1px solid var(--hud-cyan-dim);
            padding: 12px 16px;
            backdrop-filter: blur(4px);
            font-size: 12px;
            box-shadow: 0 4px 16px rgba(0,0,0,0.5);
        }

        .panel-top-left {
            top: 20px; left: 20px;
            width: 240px;
            border-left: 3px solid var(--alert-amber);
        }

        .panel-top-right {
            top: 20px; right: 20px;
            width: 200px;
            text-align: right;
            border-right: 3px solid var(--hud-cyan);
        }

        .panel-bottom {
            bottom: 20px; left: 50%;
            transform: translateX(-50%);
            display: flex;
            gap: 20px;
            border-top: 2px solid var(--hud-cyan);
            align-items: center;
            padding: 8px 24px;
        }

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

        .panel-title.warning {
            color: var(--alert-amber);
        }

        .data-row {
            display: flex;
            justify-content: space-between;
            margin-bottom: 4px;
            line-height: 1.4;
        }

        .text-dim { color: var(--text-muted); }
        .text-red { color: var(--alert-red); font-weight: bold; text-shadow: 0 0 5px rgba(255,51,102,0.5); }
        .text-amber { color: var(--alert-amber); font-weight: bold; }
        .text-cyan { color: var(--hud-cyan); }

        /* ---------------- 中心动画容器 ---------------- */
        .hero-container {
            position: relative;
            width: 100vw;
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 1;
        }

        svg {
            width: 100%;
            height: 100%;
            max-width: 900px;
            max-height: 900px;
            overflow: visible;
        }

        /* ---------------- 动画类 ---------------- */
        .spin-slow {
            animation: spin 24s linear infinite;
            transform-origin: 400px 400px;
        }

        .spin-reverse {
            animation: spin-rev 16s linear infinite;
            transform-origin: 400px 400px;
        }

        @keyframes spin { 100% { transform: rotate(360deg); } }
        @keyframes spin-rev { 100% { transform: rotate(-360deg); } }

        .pulse-danger {
            animation: pulse-red 1s ease-in-out infinite alternate;
        }

        @keyframes pulse-red {
            0% { filter: drop-shadow(0 0 4px var(--alert-red)); opacity: 0.6; }
            100% { filter: drop-shadow(0 0 12px var(--alert-red)); opacity: 1; }
        }

        .warning-flash {
            animation: flash 0.5s infinite alternate;
        }
        @keyframes flash {
            0% { opacity: 0.2; }
            100% { opacity: 0.9; }
        }

        /* SVG 样式 */
        .step-text {
            font-family: var(--font-mono);
            font-size: 12px;
            fill: var(--text-muted);
            transition: all 0.3s ease;
        }
        .step-text.active {
            fill: var(--hud-cyan);
            font-size: 14px;
            font-weight: bold;
            filter: drop-shadow(0 0 5px var(--hud-cyan));
        }
        .step-text.danger {
            fill: var(--alert-red);
            font-weight: bold;
        }

        .step-line {
            stroke: var(--hud-cyan-dim);
            stroke-width: 2;
            transition: all 0.3s;
        }
        .step-line.active {
            stroke: var(--hud-cyan);
            stroke-width: 4;
            filter: drop-shadow(0 0 4px var(--hud-cyan));
        }
        .step-line.danger {
            stroke: var(--alert-red);
            stroke-width: 4;
            filter: drop-shadow(0 0 4px var(--alert-red));
        }

    </style>
</head>
<body>

    <!-- HUD 信息面板 (边缘分布,文字极简,避免遮挡中心) -->
    <div class="hud-layer">
        <div class="panel panel-top-left">
            <div class="panel-title warning">传统流程缺陷分析</div>
            <div class="text-dim" style="margin-bottom: 8px;">12节点人工作业痛点监控</div>
            <div class="data-row"><span class="text-dim">停电范围:</span><span class="text-red">大面积</span></div>
            <div class="data-row"><span class="text-dim">高坠触电:</span><span class="text-red">高风险</span></div>
            <div class="data-row"><span class="text-dim">工具状态:</span><span class="text-amber">不趁手</span></div>
            <div class="data-row"><span class="text-dim">预警手段:</span><span class="text-amber">缺失</span></div>
            <div class="data-row"><span class="text-dim">绑扎效率:</span><span class="text-red">耗时长</span></div>
        </div>

        <div class="panel panel-top-right">
            <div class="panel-title">实时状态遥测</div>
            <div class="data-row"><span class="text-dim">当前用时:</span><span id="hud-time" class="text-cyan">0 MIN</span></div>
            <div class="data-row"><span class="text-dim">系统状态:</span><span id="hud-sys" class="text-cyan">运行正常</span></div>
            <div class="data-row"><span class="text-dim">风险等级:</span><span id="hud-risk" class="text-cyan">LOW</span></div>
        </div>

        <div class="panel panel-bottom">
            <span class="text-dim">当前节点执行中:</span>
            <span id="hud-current-step" class="text-cyan" style="font-weight: bold; font-size: 14px; letter-spacing: 2px;">准备工作</span>
            <span id="hud-alert-msg" class="text-red" style="margin-left: 20px; display: none;"></span>
        </div>
    </div>

    <!-- 中心核心可视化区 -->
    <div class="hero-container">
        <svg viewBox="0 0 800 800" preserveAspectRatio="xMidYMid meet">
            <defs>
                <!-- 发光滤镜 -->
                <filter id="glow-cyan" x="-20%" y="-20%" width="140%" height="140%">
                    <feGaussianBlur stdDeviation="4" result="blur" />
                    <feMerge><feMergeNode in="blur" /><feMergeNode in="SourceGraphic" /></feMerge>
                </filter>
                <filter id="glow-red" x="-20%" y="-20%" width="140%" height="140%">
                    <feGaussianBlur stdDeviation="6" result="blur" />
                    <feMerge><feMergeNode in="blur" /><feMergeNode in="SourceGraphic" /></feMerge>
                </filter>
                <filter id="glow-amber">
                    <feGaussianBlur stdDeviation="3" result="blur" />
                    <feMerge><feMergeNode in="blur" /><feMergeNode in="SourceGraphic" /></feMerge>
                </filter>
                
                <!-- 雷达扫描渐变 -->
                <radialGradient id="radar-grad">
                    <stop offset="80%" stop-color="var(--hud-cyan)" stop-opacity="0"/>
                    <stop offset="100%" stop-color="var(--hud-cyan)" stop-opacity="0.2"/>
                </radialGradient>
            </defs>

            <!-- 背景装饰环 -->
            <g transform="translate(400, 400)">
                <circle cx="0" cy="0" r="320" fill="none" stroke="var(--hud-cyan-dim)" stroke-width="1" stroke-dasharray="4 8" class="spin-slow" />
                <circle cx="0" cy="0" r="300" fill="none" stroke="var(--hud-cyan-dim)" stroke-width="1" />
                <circle cx="0" cy="0" r="160" fill="none" stroke="var(--hud-cyan-dim)" stroke-width="0.5" stroke-dasharray="2 4" class="spin-reverse" />
            </g>

            <!-- 动态生成的 12 步进度刻度盘将插入此处 -->
            <g id="step-ring" transform="translate(400, 400)"></g>

            <!-- 中心被测物体 (电线杆与作业环境) -->
            <g transform="translate(400, 400)" id="center-pole">
                <!-- 地面线 -->
                <line x1="-80" y1="120" x2="80" y2="120" stroke="var(--hud-cyan)" stroke-width="2" filter="url(#glow-cyan)"/>
                <line x1="-40" y1="130" x2="40" y2="130" stroke="var(--hud-cyan-dim)" stroke-width="1"/>
                
                <!-- 主杆 -->
                <rect x="-8" y="-80" width="16" height="200" fill="none" stroke="var(--hud-cyan)" stroke-width="2" filter="url(#glow-cyan)" id="pole-body"/>
                <line x1="0" y1="-80" x2="0" y2="120" stroke="var(--hud-cyan)" stroke-width="1" stroke-dasharray="4 4" opacity="0.5"/>

                <!-- 横担 -->
                <rect x="-60" y="-60" width="120" height="10" fill="#0a0a0f" stroke="var(--hud-cyan)" stroke-width="2"/>
                <rect x="-70" y="-30" width="140" height="10" fill="#0a0a0f" stroke="var(--hud-cyan)" stroke-width="2"/>

                <!-- 绝缘子及绑扎点 -->
                <circle cx="-50" cy="-65" r="4" fill="var(--hud-cyan)" id="insulator-1"/>
                <circle cx="50" cy="-65" r="4" fill="var(--hud-cyan)" id="insulator-2"/>
                <circle cx="-60" cy="-35" r="4" fill="var(--hud-cyan)" id="insulator-3"/>
                <circle cx="60" cy="-35" r="4" fill="var(--hud-cyan)" id="insulator-4"/>

                <!-- 导线 -->
                <path d="M -150,-50 Q -50,-65 -50,-65 Q 0,-40 50,-65 Q 50,-65 150,-50" fill="none" stroke="var(--hud-cyan)" stroke-width="1.5" id="wire-1"/>
                <path d="M -150,-10 Q -60,-35 -60,-35 Q 0,-10 60,-35 Q 60,-35 150,-10" fill="none" stroke="var(--hud-cyan)" stroke-width="1.5" id="wire-2"/>

                <!-- 危险警告标记 (默认隐藏,JS控制显示) -->
                <g id="danger-overlay" style="display: none;">
                    <!-- 停电断开符号 -->
                    <path id="power-cut-icon" d="M -20,-10 L 10,-30 L 5,-15 L 25,-15 L -10,15 L -5,0 Z" fill="var(--alert-red)" filter="url(#glow-red)" style="display: none;"/>
                    
                    <!-- 坠落警告波纹 -->
                    <circle id="fall-wave" cx="0" cy="0" r="40" fill="none" stroke="var(--alert-red)" stroke-width="2" class="warning-flash" style="display: none;"/>
                    
                    <!-- 耗时沙漏图标 -->
                    <g id="time-warn-icon" transform="translate(0,-100)" fill="none" stroke="var(--alert-amber)" stroke-width="2" class="pulse-danger" style="display: none;">
                        <path d="M -15,-15 L 15,-15 L 0,0 L 15,15 L -15,15 L 0,0 Z"/>
                        <circle cx="0" cy="0" r="25" stroke-dasharray="4 4"/>
                    </g>
                </g>
            </g>

            <!-- 扫描雷达指针 -->
            <g transform="translate(400, 400)" id="radar-pointer">
                <line x1="0" y1="0" x2="0" y2="-280" stroke="var(--hud-cyan)" stroke-width="2" filter="url(#glow-cyan)"/>
                <path d="M 0,0 L 40,-280 A 280 280 0 0 0 0,-280 Z" fill="url(#radar-grad)"/>
            </g>
        </svg>
    </div>

    <script>
        // 工作流程 12 个节点及对应元数据
        const workflowSteps = [
            { name: "现场勘查", type: "normal", timeObj: 5, risk: "LOW" },
            { name: "开票", type: "normal", timeObj: 10, risk: "LOW" },
            { name: "工作许可", type: "normal", timeObj: 15, risk: "LOW" },
            { name: "停电", type: "danger", timeObj: 20, risk: "HIGH", alert: "大面积停电区域扩大", action: "cut-power" },
            { name: "转检修", type: "normal", timeObj: 30, risk: "MEDIUM" },
            { name: "登杆", type: "danger", timeObj: 45, risk: "CRITICAL", alert: "高空作业坠落/触电风险", action: "fall-risk" },
            { name: "更换绝缘子", type: "warning", timeObj: 60, risk: "HIGH", alert: "工具不趁手, 操作困难", action: "time-loss" },
            { name: "绑扎线缠绕", type: "danger", timeObj: 90, risk: "HIGH", alert: "手工缠绕耗时长且费力", action: "time-loss" },
            { name: "紧固", type: "warning", timeObj: 100, risk: "MEDIUM", alert: "依赖人工经验", action: "time-loss" },
            { name: "转运行", type: "normal", timeObj: 105, risk: "LOW" },
            { name: "恢复供电", type: "normal", timeObj: 115, risk: "LOW", action: "restore-power" },
            { name: "工作终结", type: "normal", timeObj: 120, risk: "LOW" }
        ];

        const totalSteps = workflowSteps.length;
        const ringRadius = 240;
        const textRadius = 280;
        const stepRingGroup = document.getElementById('step-ring');
        
        // 动态生成环形刻度和文字
        workflowSteps.forEach((step, index) => {
            const angle = (index * (360 / totalSteps)) - 90; // -90 使其从12点钟方向开始
            const rad = angle * Math.PI / 180;
            
            // 计算坐标
            const x1 = Math.cos(rad) * (ringRadius - 10);
            const y1 = Math.sin(rad) * (ringRadius - 10);
            const x2 = Math.cos(rad) * (ringRadius + 10);
            const y2 = Math.sin(rad) * (ringRadius + 10);
            
            const tx = Math.cos(rad) * textRadius;
            const ty = Math.sin(rad) * textRadius;

            // 绘制刻度线
            const line = document.createElementNS("http://www.w3.org/2000/svg", "line");
            line.setAttribute("x1", x1);
            line.setAttribute("y1", y1);
            line.setAttribute("x2", x2);
            line.setAttribute("y2", y2);
            line.setAttribute("class", "step-line");
            line.id = `line-${index}`;
            stepRingGroup.appendChild(line);

            // 绘制文字
            const text = document.createElementNS("http://www.w3.org/2000/svg", "text");
            text.setAttribute("x", tx);
            text.setAttribute("y", ty);
            text.setAttribute("text-anchor", "middle");
            text.setAttribute("dominant-baseline", "middle");
            text.setAttribute("class", "step-text");
            text.id = `text-${index}`;
            // 根据角度翻转文字以保证可读性
            let rotateAngle = angle + 90;
            if (angle > 90 && angle < 270) rotateAngle += 180;
            text.setAttribute("transform", `rotate(${rotateAngle}, ${tx}, ${ty})`);
            text.textContent = step.name;
            stepRingGroup.appendChild(text);
        });

        // 动画控制逻辑
        const DURATION_PER_STEP = 1500; // 每步 1.5 秒
        let startTime = null;

        const uiElements = {
            time: document.getElementById('hud-time'),
            sys: document.getElementById('hud-sys'),
            risk: document.getElementById('hud-risk'),
            curStep: document.getElementById('hud-current-step'),
            alertMsg: document.getElementById('hud-alert-msg'),
            radar: document.getElementById('radar-pointer'),
            poleBody: document.getElementById('pole-body'),
            wire1: document.getElementById('wire-1'),
            wire2: document.getElementById('wire-2'),
            dangerOverlay: document.getElementById('danger-overlay'),
            powerCutIcon: document.getElementById('power-cut-icon'),
            fallWave: document.getElementById('fall-wave'),
            timeWarnIcon: document.getElementById('time-warn-icon')
        };

        function resetCenterGraphic() {
            uiElements.poleBody.setAttribute("stroke", "var(--hud-cyan)");
            uiElements.poleBody.setAttribute("filter", "url(#glow-cyan)");
            uiElements.wire1.setAttribute("stroke", "var(--hud-cyan)");
            uiElements.wire2.setAttribute("stroke", "var(--hud-cyan)");
            uiElements.dangerOverlay.style.display = "none";
            uiElements.powerCutIcon.style.display = "none";
            uiElements.fallWave.style.display = "none";
            uiElements.timeWarnIcon.style.display = "none";
        }

        function triggerAction(action) {
            resetCenterGraphic();
            if (!action) return;
            
            uiElements.dangerOverlay.style.display = "block";
            
            if (action === "cut-power") {
                uiElements.poleBody.setAttribute("stroke", "var(--text-muted)");
                uiElements.poleBody.removeAttribute("filter");
                uiElements.wire1.setAttribute("stroke", "var(--alert-red)");
                uiElements.wire2.setAttribute("stroke", "var(--alert-red)");
                uiElements.powerCutIcon.style.display = "block";
            } else if (action === "fall-risk") {
                uiElements.fallWave.style.display = "block";
            } else if (action === "time-loss") {
                uiElements.poleBody.setAttribute("stroke", "var(--alert-amber)");
                uiElements.timeWarnIcon.style.display = "block";
            } else if (action === "restore-power") {
                resetCenterGraphic();
            }
        }

        function renderFrame(timestamp) {
            if (!startTime) startTime = timestamp;
            const elapsed = timestamp - startTime;
            
            // 总周期时间
            const totalDuration = DURATION_PER_STEP * totalSteps;
            const currentLoopTime = elapsed % totalDuration;
            
            // 计算当前所在的阶段 (0-11)
            const currentStepIndex = Math.floor(currentLoopTime / DURATION_PER_STEP);
            // 计算雷达指针平滑旋转角度 (0-360)
            const currentAngle = (currentLoopTime / totalDuration) * 360;
            
            // 旋转雷达
            uiElements.radar.setAttribute("transform", `rotate(${currentAngle})`);

            // 更新所有刻度和文字的样式
            workflowSteps.forEach((step, idx) => {
                const line = document.getElementById(`line-${idx}`);
                const text = document.getElementById(`text-${idx}`);
                
                // 重置类名
                line.setAttribute("class", "step-line");
                text.setAttribute("class", "step-text");

                if (idx === currentStepIndex) {
                    if (step.type === 'danger' || step.type === 'warning') {
                        line.setAttribute("class", "step-line danger");
                        text.setAttribute("class", "step-text danger");
                    } else {
                        line.setAttribute("class", "step-line active");
                        text.setAttribute("class", "step-text active");
                    }
                }
            });

            // 更新 HUD 数据 (仅在步骤切换时执行状态更新逻辑)
            const stepData = workflowSteps[currentStepIndex];
            
            // 平滑插值计算当前显示时间 (0 到当前步骤的 timeObj)
            const prevTime = currentStepIndex === 0 ? 0 : workflowSteps[currentStepIndex-1].timeObj;
            const stepProgress = (currentLoopTime % DURATION_PER_STEP) / DURATION_PER_STEP;
            const displayTime = Math.floor(prevTime + (stepData.timeObj - prevTime) * stepProgress);
            
            uiElements.time.textContent = `${displayTime} MIN`;
            uiElements.curStep.textContent = `${currentStepIndex + 1}. ${stepData.name}`;
            
            if (stepData.type === 'danger' || stepData.type === 'warning') {
                uiElements.sys.textContent = "异常痛点检出";
                uiElements.sys.className = "text-red";
                uiElements.risk.textContent = stepData.risk;
                uiElements.risk.className = stepData.risk === 'CRITICAL' ? "text-red warning-flash" : "text-amber";
                
                if (stepData.alert) {
                    uiElements.alertMsg.textContent = `[警告] ${stepData.alert}`;
                    uiElements.alertMsg.style.display = "inline";
                }
            } else {
                uiElements.sys.textContent = "运行正常";
                uiElements.sys.className = "text-cyan";
                uiElements.risk.textContent = stepData.risk;
                uiElements.risk.className = "text-cyan";
                uiElements.alertMsg.style.display = "none";
            }

            // 触发中心图形状态变化
            // 为了避免每一帧都重置,我们根据当前所处的 action 保持状态
            const currentAction = stepData.action;
            
            // 简单处理:如果是当前步骤第一帧左右,触发动作更新 (避免过度调用 DOM)
            if (!stepData._actionTriggered || stepData._lastIndex !== currentStepIndex) {
                triggerAction(currentAction);
                workflowSteps.forEach(s => s._lastIndex = currentStepIndex);
                stepData._actionTriggered = true;
            }

            requestAnimationFrame(renderFrame);
        }

        // 页面加载完成后自动启动动画
        document.addEventListener("DOMContentLoaded", () => {
            requestAnimationFrame(renderFrame);
        });

    </script>
</body>
</html>
<!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-base: #0a0a0f;
            --grid-line: rgba(43, 56, 78, 0.3);
            --color-normal: #00F0FF;     /* 正常运行:青色 */
            --color-warning: #FFB000;    /* 警告/人工作业:橙黄 */
            --color-danger: #FF2A2A;     /* 停电/危险:亮红 */
            --color-success: #00FF66;    /* 恢复:荧光绿 */
            --color-text-main: #E2E8F0;
            --color-text-dim: #64748B;
            --font-mono: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
            --font-sans: system-ui, -apple-system, sans-serif;
            
            /* 状态变量 (通过JS控制挂载在body上) */
            --theme-color: var(--color-normal);
        }

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

        /* 监控网格背景 */
        .grid-bg {
            position: absolute;
            top: 0; left: 0; right: 0; bottom: 0;
            background-image: 
                linear-gradient(var(--grid-line) 1px, transparent 1px),
                linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
            background-size: 50px 50px;
            background-position: center center;
            z-index: 0;
            opacity: 0.6;
        }

        /* 扫描线叠加层 */
        .scanlines {
            position: absolute;
            top: 0; left: 0; right: 0; bottom: 0;
            background: linear-gradient(
                to bottom,
                rgba(255,255,255,0),
                rgba(255,255,255,0) 50%,
                rgba(0,0,0,0.2) 50%,
                rgba(0,0,0,0.2)
            );
            background-size: 100% 4px;
            z-index: 100;
            pointer-events: none;
            opacity: 0.3;
        }

        /* ---------------- UI 面板布局 (边缘停靠,避免遮挡中央) ---------------- */
        .hud {
            position: absolute;
            z-index: 10;
            pointer-events: none;
        }

        .panel {
            background: rgba(10, 10, 15, 0.85);
            border: 1px solid rgba(100, 116, 139, 0.3);
            backdrop-filter: blur(8px);
            padding: 16px;
        }

        /* 左上:标题与痛点摘要 */
        .top-left {
            top: 24px; left: 24px;
            width: 280px;
            border-left: 3px solid var(--theme-color);
            transition: border-color 0.3s;
        }
        .title { font-family: var(--font-mono); font-size: 14px; font-weight: bold; color: var(--theme-color); margin-bottom: 8px; letter-spacing: 1px; transition: color 0.3s;}
        .desc { font-size: 12px; color: var(--color-text-dim); line-height: 1.6; }
        .highlight { color: var(--color-warning); font-weight: bold; }

        /* 右上:停电时长计时器 */
        .top-right {
            top: 24px; right: 24px;
            text-align: right;
            border-right: 3px solid var(--color-danger);
            display: flex;
            flex-direction: column;
            align-items: flex-end;
        }
        .timer-label { font-size: 12px; color: var(--color-text-dim); font-family: var(--font-mono); margin-bottom: 4px; }
        .timer-value { font-size: 32px; font-weight: bold; color: var(--color-danger); font-family: var(--font-mono); line-height: 1; }
        .timer-unit { font-size: 14px; color: var(--color-text-dim); }

        /* 左下:风险告警监控 */
        .bottom-left {
            bottom: 24px; left: 24px;
            width: 200px;
            border-left: 3px solid var(--color-warning);
        }
        .risk-item { display: flex; justify-content: space-between; font-size: 12px; font-family: var(--font-mono); margin-bottom: 6px; opacity: 0.4; transition: all 0.3s;}
        .risk-item.active { opacity: 1; color: var(--color-danger); text-shadow: 0 0 8px rgba(255,42,42,0.5); }
        .risk-indicator { width: 8px; height: 8px; border-radius: 50%; background: currentColor; box-shadow: 0 0 5px currentColor; }

        /* 底部中:12步流程时间轴 */
        .bottom-center {
            bottom: 24px; left: 50%;
            transform: translateX(-50%);
            width: 80%;
            max-width: 800px;
            display: flex;
            justify-content: space-between;
            padding: 12px 20px;
            border-top: 1px solid var(--theme-color);
            transition: border-color 0.3s;
        }
        .step {
            display: flex; flex-direction: column; align-items: center; gap: 6px;
            opacity: 0.3; transition: all 0.3s;
            position: relative;
        }
        .step.active { opacity: 1; transform: scale(1.1); }
        .step.done { opacity: 0.6; }
        .step-dot { width: 6px; height: 6px; background: var(--color-text-dim); border-radius: 50%; transition: all 0.3s; }
        .step.active .step-dot { background: var(--theme-color); box-shadow: 0 0 8px var(--theme-color); }
        .step.done .step-dot { background: var(--color-success); }
        .step-label { font-size: 10px; font-family: var(--font-mono); white-space: nowrap; color: var(--color-text-main); writing-mode: vertical-rl; transform: rotate(180deg); letter-spacing: 2px;}

        /* ---------------- 核心动画区域 ---------------- */
        .svg-container {
            width: 100vw;
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 5;
        }
        svg {
            width: 100%;
            height: 100%;
            max-width: 1000px;
            max-height: 800px;
            overflow: visible;
        }

        /* SVG 元素状态样式 */
        .power-line { stroke: var(--theme-color); transition: stroke 0.5s, filter 0.5s; }
        .energy-flow { stroke: #fff; stroke-dasharray: 10 20; animation: flow 1s linear infinite; opacity: 1; transition: opacity 0.3s; }
        @keyframes flow { to { stroke-dashoffset: -30; } }

        /* 故障/停电状态覆盖 */
        body[data-status="outage"] .power-line { stroke: var(--color-danger); filter: none; }
        body[data-status="outage"] .energy-flow { opacity: 0; animation: none; }
        body[data-status="outage"] { --theme-color: var(--color-danger); }

        /* 作业中状态覆盖 */
        body[data-status="working"] .power-line { stroke: var(--color-text-dim); filter: none; }
        body[data-status="working"] .energy-flow { opacity: 0; }
        body[data-status="working"] { --theme-color: var(--color-warning); }

        /* 人工攀爬节点 */
        #worker-node { transition: transform 0.5s ease-in-out, opacity 0.3s; opacity: 0; }
        #worker-node.visible { opacity: 1; }

        /* 危险区域光晕圈 */
        .danger-zone { opacity: 0; transform-origin: center; transition: opacity 0.3s; pointer-events: none; }
        .danger-zone.active { opacity: 1; animation: pulseDanger 2s ease-out infinite; }
        @keyframes pulseDanger {
            0% { transform: scale(0.5); opacity: 0.8; stroke-width: 4px; }
            100% { transform: scale(2.5); opacity: 0; stroke-width: 1px; }
        }

        /* 工具不趁手/费时动画指示器 */
        .tool-indicator { opacity: 0; transition: opacity 0.3s; }
        .tool-indicator.active { opacity: 1; animation: rotateTool 3s linear infinite; }
        @keyframes rotateTool {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }

    </style>
</head>
<body>
    <div class="grid-bg"></div>
    <div class="scanlines"></div>

    <!-- UI 层 -->
    <div class="hud panel top-left">
        <div class="title" id="ui-title">传统电工作业监控</div>
        <div class="desc">
            全流程共 <span class="highlight">12个环节</span>,高度依赖人工。<br>
            暴露三大核心痛点:<br>
            1. <span style="color:var(--color-danger)">停电范围大</span>,严重影响供电可靠性。<br>
            2. <span style="color:var(--color-warning)">人工作业耗时长</span>,工具不趁手。<br>
            3. 存在极高 <span style="color:var(--color-danger)">高坠与触电危险</span>。
        </div>
    </div>

    <div class="hud panel top-right">
        <div class="timer-label">单次故障平均停电时长</div>
        <div>
            <span class="timer-value" id="ui-timer">000</span>
            <span class="timer-unit">MIN</span>
        </div>
    </div>

    <div class="hud panel bottom-left">
        <div class="title" style="color: var(--color-warning); border:none; margin-bottom:12px;">风险实时监测</div>
        <div class="risk-item" id="risk-outage">
            <span>大规模停电</span><div class="risk-indicator"></div>
        </div>
        <div class="risk-item" id="risk-fall">
            <span>高空坠落风险</span><div class="risk-indicator"></div>
        </div>
        <div class="risk-item" id="risk-shock">
            <span>感应电触电风险</span><div class="risk-indicator"></div>
        </div>
        <div class="risk-item" id="risk-time">
            <span>绑扎耗时过长</span><div class="risk-indicator"></div>
        </div>
    </div>

    <div class="hud panel bottom-center" id="step-container">
        <!-- 步骤通过 JS 动态生成 -->
    </div>

    <!-- SVG 动画层 -->
    <div class="svg-container">
        <svg viewBox="0 0 1000 800" preserveAspectRatio="xMidYMid meet">
            <defs>
                <filter id="neon-glow" x="-50%" y="-50%" width="200%" height="200%">
                    <feGaussianBlur stdDeviation="6" result="coloredBlur"/>
                    <feMerge>
                        <feMergeNode in="coloredBlur"/>
                        <feMergeNode in="SourceGraphic"/>
                    </feMerge>
                </filter>
                <filter id="danger-glow" x="-50%" y="-50%" width="200%" height="200%">
                    <feGaussianBlur stdDeviation="8" result="coloredBlur"/>
                    <feMerge>
                        <feMergeNode in="coloredBlur"/>
                        <feMergeNode in="SourceGraphic"/>
                    </feMerge>
                </filter>
            </defs>

            <!-- 远景电网线条 (背景修饰) -->
            <path d="M 0 500 Q 250 550 500 500 T 1000 500" fill="none" stroke="rgba(100, 116, 139, 0.2)" stroke-width="2"/>
            <path d="M 0 520 Q 250 570 500 520 T 1000 520" fill="none" stroke="rgba(100, 116, 139, 0.2)" stroke-width="2"/>

            <!-- 中心电线杆主体 -->
            <g transform="translate(500, 750)">
                <!-- 杆体 -->
                <polygon points="-15,0 15,0 8,-450 -8,-450" fill="#1E293B" stroke="#334155" stroke-width="2"/>
                <line x1="-8" y1="-450" x2="-15" y2="0" stroke="#0F172A" stroke-width="2"/>
                
                <!-- 横担 1 -->
                <rect x="-120" y="-380" width="240" height="15" fill="#334155" rx="2"/>
                <path d="M -100,-380 L -80,-365 M -60,-380 L -40,-365 M 100,-380 L 80,-365 M 60,-380 L 40,-365" stroke="#1E293B" stroke-width="2"/>
                
                <!-- 横担 2 (顶部主作业区) -->
                <rect x="-180" y="-440" width="360" height="15" fill="#334155" rx="2"/>
                <path d="M -160,-440 L -140,-425 M 160,-440 L 140,-425" stroke="#1E293B" stroke-width="2"/>

                <!-- 绝缘子 -->
                <g class="insulator" transform="translate(-160, -460)">
                    <rect x="-10" y="0" width="20" height="20" fill="#94A3B8" rx="2"/>
                    <path d="M -15,5 L 15,5 M -15,10 L 15,10 M -15,15 L 15,15" stroke="#475569" stroke-width="2"/>
                </g>
                <g class="insulator" transform="translate(160, -460)">
                    <rect x="-10" y="0" width="20" height="20" fill="#94A3B8" rx="2"/>
                    <path d="M -15,5 L 15,5 M -15,10 L 15,10 M -15,15 L 15,15" stroke="#475569" stroke-width="2"/>
                </g>
                <!-- 中间作业绝缘子 (重点关注) -->
                <g class="insulator" id="target-insulator" transform="translate(0, -460)">
                    <rect x="-12" y="-5" width="24" height="25" fill="#CBD5E1" rx="2"/>
                    <path d="M -18,2 L 18,2 M -18,8 L 18,8 M -18,14 L 18,14" stroke="#64748B" stroke-width="3"/>
                </g>
            </g>

            <!-- 输电线 (受状态控制) -->
            <!-- 左侧线 -->
            <path class="power-line" d="M -100 400 Q 200 450 340 290" fill="none" stroke-width="4" filter="url(#neon-glow)"/>
            <path class="energy-flow" d="M -100 400 Q 200 450 340 290" fill="none" stroke-width="2"/>
            <!-- 右侧线 -->
            <path class="power-line" d="M 660 290 Q 800 450 1100 400" fill="none" stroke-width="4" filter="url(#neon-glow)"/>
            <path class="energy-flow" d="M 660 290 Q 800 450 1100 400" fill="none" stroke-width="2"/>
            
            <!-- 危险光晕圈 (登杆作业时触发) -->
            <g transform="translate(500, 290)">
                <circle class="danger-zone" cx="0" cy="0" r="40" fill="none" stroke="var(--color-danger)" stroke-width="2"/>
                <circle class="danger-zone" cx="0" cy="0" r="40" fill="none" stroke="var(--color-warning)" stroke-width="2" style="animation-delay: 1s;"/>
            </g>

            <!-- 抽象作业人员节点 (带安全带的标识) -->
            <g id="worker-node" transform="translate(500, 750)">
                <!-- 身体 -->
                <circle cx="0" cy="0" r="14" fill="var(--color-warning)" filter="url(#danger-glow)"/>
                <!-- 安全绳示意 -->
                <path d="M -14,0 Q -30,20 -10,40" fill="none" stroke="var(--color-text-main)" stroke-width="2" stroke-dasharray="4 2"/>
                <!-- 内部标识 -->
                <text x="0" y="4" font-size="12" fill="#000" font-family="var(--font-mono)" text-anchor="middle" font-weight="bold">W</text>
                
                <!-- 耗时操作/工具不趁手标识 -->
                <g class="tool-indicator">
                    <circle cx="0" cy="0" r="24" fill="none" stroke="var(--color-warning)" stroke-width="2" stroke-dasharray="10 10"/>
                    <path d="M 18,-18 L 26,-26 M -18,18 L -26,26" stroke="var(--color-warning)" stroke-width="3"/>
                </g>
            </g>

            <!-- 全局红色警戒线 (停电时显示) -->
            <g id="outage-overlay" style="opacity: 0; transition: opacity 0.5s; pointer-events:none;">
                <rect x="0" y="0" width="100%" height="100%" fill="rgba(255, 42, 42, 0.05)"/>
                <text x="500" y="150" font-size="24" fill="rgba(255, 42, 42, 0.4)" font-family="var(--font-mono)" text-anchor="middle" font-weight="bold" letter-spacing="10px">SYSTEM OUTAGE / AREA OF EFFECT</text>
            </g>
        </svg>
    </div>

    <!-- 控制脚本 -->
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            // 定义 12 个步骤
            const STEPS = [
                { name: "现场勘查", type: "prep", duration: 1000 },
                { name: "开票", type: "prep", duration: 1000 },
                { name: "工作许可", type: "prep", duration: 1000 },
                { name: "停电", type: "outage", duration: 1000 },
                { name: "转检修", type: "outage", duration: 1000 },
                { name: "登杆", type: "work-climb", duration: 2000 },
                { name: "更换绝缘子", type: "work-heavy", duration: 3000 },
                { name: "绑扎线缠绕", type: "work-heavy", duration: 3000 },
                { name: "紧固", type: "work-heavy", duration: 1500 },
                { name: "转运行", type: "restore", duration: 1000 },
                { name: "恢复供电", type: "restore", duration: 1000 },
                { name: "工作终结", type: "end", duration: 1500 }
            ];

            const totalDuration = STEPS.reduce((sum, step) => sum + step.duration, 0);
            
            // DOM 元素引用
            const stepContainer = document.getElementById('step-container');
            const timerEl = document.getElementById('ui-timer');
            const workerNode = document.getElementById('worker-node');
            const dangerZones = document.querySelectorAll('.danger-zone');
            const toolIndicator = document.querySelector('.tool-indicator');
            const outageOverlay = document.getElementById('outage-overlay');
            const uiTitle = document.getElementById('ui-title');
            
            // 风险指示器
            const riskOutage = document.getElementById('risk-outage');
            const riskFall = document.getElementById('risk-fall');
            const riskShock = document.getElementById('risk-shock');
            const riskTime = document.getElementById('risk-time');

            // 渲染底部步骤条
            STEPS.forEach((step, idx) => {
                const el = document.createElement('div');
                el.className = 'step';
                el.id = `step-${idx}`;
                el.innerHTML = `
                    <div class="step-dot"></div>
                    <div class="step-label">${idx + 1}.${step.name}</div>
                `;
                stepContainer.appendChild(el);
            });

            const stepEls = document.querySelectorAll('.step');

            // 动画状态管理
            let startTime = null;

            function updateAnimation(timestamp) {
                if (!startTime) startTime = timestamp;
                
                // 计算循环进度
                const elapsed = (timestamp - startTime) % (totalDuration + 2000); // 留2秒休息期
                
                // 重置状态
                let currentStepIdx = -1;
                let timeAccumulator = 0;

                // 查找当前处于哪个步骤
                for (let i = 0; i < STEPS.length; i++) {
                    if (elapsed >= timeAccumulator && elapsed < timeAccumulator + STEPS[i].duration) {
                        currentStepIdx = i;
                        break;
                    }
                    timeAccumulator += STEPS[i].duration;
                }

                // 如果在休息期,视为已结束
                if (currentStepIdx === -1) {
                    currentStepIdx = STEPS.length - 1;
                    if(elapsed > totalDuration) {
                        resetVisuals();
                        requestAnimationFrame(updateAnimation);
                        return;
                    }
                }

                const currentStep = STEPS[currentStepIdx];
                const stepProgress = (elapsed - timeAccumulator) / currentStep.duration;

                // 更新UI步骤条
                stepEls.forEach((el, idx) => {
                    el.className = 'step';
                    if (idx < currentStepIdx) el.classList.add('done');
                    if (idx === currentStepIdx) el.classList.add('active');
                });

                // 更新计时器 (模拟停电 120 分钟)
                // 停电从第4步开始,到第11步结束
                let displayTime = 0;
                if (currentStepIdx >= 3 && currentStepIdx <= 10) {
                    // 计算在这段期间的整体进度
                    const outageStart = STEPS.slice(0, 3).reduce((s, x) => s + x.duration, 0);
                    const outageEnd = STEPS.slice(0, 11).reduce((s, x) => s + x.duration, 0);
                    const outageElapsed = Math.max(0, elapsed - outageStart);
                    const outageRatio = Math.min(1, outageElapsed / (outageEnd - outageStart));
                    displayTime = Math.floor(outageRatio * 120);
                } else if (currentStepIdx > 10) {
                    displayTime = 120;
                }
                timerEl.textContent = displayTime.toString().padStart(3, '0');

                // 核心状态机及视觉调度
                applyVisualState(currentStep.type, stepProgress, currentStepIdx);

                requestAnimationFrame(updateAnimation);
            }

            function applyVisualState(type, progress, idx) {
                const body = document.body;
                
                // 默认复位所有风险
                riskOutage.classList.remove('active');
                riskFall.classList.remove('active');
                riskShock.classList.remove('active');
                riskTime.classList.remove('active');

                switch(type) {
                    case 'prep':
                        body.setAttribute('data-status', 'normal');
                        workerNode.classList.remove('visible');
                        workerNode.style.transform = `translate(500px, 750px)`; // 在地面
                        outageOverlay.style.opacity = "0";
                        uiTitle.textContent = "准备阶段:现场勘察与开票";
                        break;

                    case 'outage':
                        body.setAttribute('data-status', 'outage');
                        riskOutage.classList.add('active');
                        outageOverlay.style.opacity = "1";
                        uiTitle.textContent = "停电转检修:大面积停电开始";
                        break;

                    case 'work-climb':
                        body.setAttribute('data-status', 'working');
                        riskOutage.classList.add('active');
                        riskFall.classList.add('active');
                        workerNode.classList.add('visible');
                        outageOverlay.style.opacity = "0.5";
                        
                        // 攀爬动画:从底 (y=750) 爬到顶 (y=290)
                        const currentY = 750 - (progress * 460);
                        workerNode.style.transform = `translate(500px, ${currentY}px)`;
                        uiTitle.textContent = "高危作业:人工登杆";
                        
                        dangerZones.forEach(z => z.classList.remove('active'));
                        toolIndicator.classList.remove('active');
                        break;

                    case 'work-heavy':
                        body.setAttribute('data-status', 'working');
                        riskOutage.classList.add('active');
                        riskFall.classList.add('active');
                        riskShock.classList.add('active');
                        riskTime.classList.add('active');
                        
                        workerNode.classList.add('visible');
                        workerNode.style.transform = `translate(500px, 290px)`; // 固定在顶部
                        
                        dangerZones.forEach(z => z.classList.add('active'));
                        toolIndicator.classList.add('active');
                        
                        const opName = STEPS[idx].name;
                        uiTitle.textContent = `痛点阶段:${opName}耗时极长`;
                        break;

                    case 'restore':
                        body.setAttribute('data-status', 'normal');
                        outageOverlay.style.opacity = "0";
                        dangerZones.forEach(z => z.classList.remove('active'));
                        toolIndicator.classList.remove('active');
                        
                        // 下降并消失
                        if (progress < 0.5) {
                            const descY = 290 + (progress * 2 * 460);
                            workerNode.style.transform = `translate(500px, ${descY}px)`;
                        } else {
                            workerNode.classList.remove('visible');
                        }
                        
                        uiTitle.textContent = "操作终结:恢复供电";
                        break;

                    case 'end':
                        body.setAttribute('data-status', 'normal');
                        workerNode.classList.remove('visible');
                        uiTitle.textContent = "全流程结束 (单次故障耗时120分)";
                        break;
                }
            }

            function resetVisuals() {
                document.body.setAttribute('data-status', 'normal');
                workerNode.classList.remove('visible');
                dangerZones.forEach(z => z.classList.remove('active'));
                toolIndicator.classList.remove('active');
                outageOverlay.style.opacity = "0";
                timerEl.textContent = "000";
                stepEls.forEach(el => el.className = 'step');
            }

            // 启动动画循环
            requestAnimationFrame(updateAnimation);
        });
    </script>
</body>
</html>
<!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-dark: #050508;
            --grid-color: rgba(64, 75, 95, 0.15);
            --ui-cyan: #00E5FF;
            --ui-amber: #FFB300;
            --ui-red: #FF3366;
            --ui-gray: #4A5568;
            --ui-text: #E2E8F0;
            --ui-text-dim: #94A3B8;
            --font-mono: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
            --font-sans: system-ui, -apple-system, sans-serif;
        }

        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            background-color: var(--bg-dark);
            background-image: 
                linear-gradient(var(--grid-color) 1px, transparent 1px),
                linear-gradient(90deg, var(--grid-color) 1px, transparent 1px);
            background-size: 40px 40px;
            font-family: var(--font-sans);
            overflow: hidden;
            color: var(--ui-text);
        }

        /* ================= HUD UI 布局 (严格边缘分布) ================= */
        .hud-layer {
            position: absolute;
            inset: 0;
            pointer-events: none;
            z-index: 100;
            display: flex;
            flex-direction: column;
            justify-content: space-between;
        }

        .panel {
            background: rgba(5, 5, 8, 0.85);
            border: 1px solid rgba(148, 163, 184, 0.2);
            backdrop-filter: blur(8px);
            padding: 16px 20px;
        }

        .hud-top {
            display: flex;
            justify-content: space-between;
            padding: 24px;
        }

        .panel-left {
            width: 320px;
            border-left: 3px solid var(--ui-red);
        }

        .panel-right {
            width: 240px;
            text-align: right;
            border-right: 3px solid var(--ui-amber);
            display: flex;
            flex-direction: column;
            align-items: flex-end;
        }

        .hud-bottom {
            padding: 24px;
            display: flex;
            justify-content: center;
        }

        .panel-timeline {
            width: 80%;
            max-width: 900px;
            display: flex;
            justify-content: space-between;
            border-top: 1px solid var(--ui-cyan);
            padding-top: 12px;
        }

        .title { font-family: var(--font-mono); font-size: 14px; font-weight: bold; color: var(--ui-red); margin-bottom: 8px; letter-spacing: 1px; }
        .desc { font-size: 12px; color: var(--ui-text-dim); line-height: 1.6; }
        .highlight-red { color: var(--ui-red); font-weight: bold; }
        .highlight-amber { color: var(--ui-amber); font-weight: bold; }

        .stat-label { font-size: 12px; color: var(--ui-text-dim); font-family: var(--font-mono); margin-bottom: 4px; }
        .stat-value { font-size: 36px; font-weight: bold; font-family: var(--font-mono); line-height: 1; transition: color 0.3s; }
        .stat-unit { font-size: 14px; color: var(--ui-text-dim); }

        .timeline-step {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 8px;
            opacity: 0.3;
            transition: all 0.3s;
        }
        .timeline-step.active { opacity: 1; transform: scale(1.1); }
        .timeline-step.done { opacity: 0.6; }
        .step-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--ui-text-dim); }
        .timeline-step.active .step-dot { background: var(--ui-cyan); box-shadow: 0 0 10px var(--ui-cyan); }
        .timeline-step.active.danger .step-dot { background: var(--ui-red); box-shadow: 0 0 10px var(--ui-red); }
        .step-text { font-family: var(--font-mono); font-size: 10px; writing-mode: vertical-rl; transform: rotate(180deg); color: var(--ui-text); letter-spacing: 1px; }

        .risk-alert {
            position: absolute;
            top: 140px;
            left: 24px;
            background: rgba(255, 51, 102, 0.1);
            border: 1px solid var(--ui-red);
            padding: 8px 12px;
            font-size: 12px;
            font-family: var(--font-mono);
            color: var(--ui-red);
            opacity: 0;
            transition: opacity 0.3s;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        .risk-alert.show { opacity: 1; animation: blinkAlert 1s infinite alternate; }
        @keyframes blinkAlert { from { box-shadow: 0 0 0px transparent; } to { box-shadow: 0 0 15px rgba(255, 51, 102, 0.4); } }

        /* ================= 核心 SVG 动画区 ================= */
        .svg-canvas {
            position: absolute;
            inset: 0;
            width: 100%;
            height: 100%;
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 10;
        }

        svg {
            width: 100%;
            height: 100%;
            max-width: 1200px;
            max-height: 900px;
            overflow: visible;
        }

        /* 状态与滤镜 */
        .glow-cyan { filter: drop-shadow(0 0 8px var(--ui-cyan)); }
        .glow-red { filter: drop-shadow(0 0 12px var(--ui-red)); }
        
        .power-line { stroke: var(--ui-cyan); transition: stroke 0.5s; }
        .power-line.outage { stroke: var(--ui-gray); opacity: 0.5; filter: none; }
        
        .energy-flow { stroke-dasharray: 10 20; animation: dashFlow 1s linear infinite; }
        .energy-flow.outage { opacity: 0; animation: none; }
        @keyframes dashFlow { to { stroke-dashoffset: -30; } }

        /* ================= 人物动画系统 (CSS 控制) ================= */
        #worker-group {
            transform: translate(380px, 700px); /* 初始地面位置 */
            transition: transform 0s linear;
        }
        
        /* 躯干摆动 */
        #worker-body { transform-origin: center bottom; }
        /* 四肢关节 */
        .limb { transform-origin: top center; }
        
        /* 攀爬动画 */
        .is-climbing #worker-group { animation: climbTranslate 4s linear forwards; }
        .is-climbing .arm-left { animation: climbArmL 0.8s infinite alternate; }
        .is-climbing .arm-right { animation: climbArmR 0.8s infinite alternate; }
        .is-climbing .leg-left { animation: climbLegL 0.8s infinite alternate; }
        .is-climbing .leg-right { animation: climbLegR 0.8s infinite alternate; }
        
        @keyframes climbTranslate {
            0% { transform: translate(380px, 700px); }
            100% { transform: translate(380px, 260px); }
        }
        @keyframes climbArmL { 0% { transform: rotate(-30deg); } 100% { transform: rotate(10deg); } }
        @keyframes climbArmR { 0% { transform: rotate(10deg); } 100% { transform: rotate(-30deg); } }
        @keyframes climbLegL { 0% { transform: rotate(-10deg) translateY(0); } 100% { transform: rotate(30deg) translateY(-10px); } }
        @keyframes climbLegR { 0% { transform: rotate(30deg) translateY(-10px); } 100% { transform: rotate(-10deg) translateY(0); } }

        /* 顶部高危作业动画 (挣扎、费时) */
        .is-working #worker-group { transform: translate(380px, 260px); }
        .is-working #worker-body { animation: bodyStruggle 1s infinite alternate ease-in-out; }
        .is-working .arm-left { animation: workArmL 0.5s infinite alternate; }
        .is-working .arm-right { transform: rotate(-45deg); animation: workArmR 0.3s infinite alternate; }
        .is-working .leg-left { transform: rotate(10deg); }
        .is-working .leg-right { transform: rotate(-10deg); }
        
        @keyframes bodyStruggle { 0% { transform: rotate(-5deg); } 100% { transform: rotate(5deg); } }
        @keyframes workArmL { 0% { transform: rotate(-80deg); } 100% { transform: rotate(-60deg); } }
        @keyframes workArmR { 0% { transform: rotate(-120deg); } 100% { transform: rotate(-20deg); } } /* 幅度大,表示耗力缠绕 */

        /* 下降动画 */
        .is-descending #worker-group { animation: descendTranslate 2s linear forwards; }
        .is-descending .arm-left { animation: climbArmL 0.5s infinite alternate reverse; }
        .is-descending .arm-right { animation: climbArmR 0.5s infinite alternate reverse; }
        .is-descending .leg-left { animation: climbLegL 0.5s infinite alternate reverse; }
        .is-descending .leg-right { animation: climbLegR 0.5s infinite alternate reverse; }
        
        @keyframes descendTranslate {
            0% { transform: translate(380px, 260px); }
            100% { transform: translate(380px, 700px); }
        }

        /* 危险特效 */
        .hazard-ring { opacity: 0; transform-origin: 380px 240px; pointer-events: none; }
        .is-working .hazard-ring { animation: pulseDanger 2s infinite cubic-bezier(0.2, 0.8, 0.2, 1); }
        @keyframes pulseDanger {
            0% { transform: scale(0.2); opacity: 1; stroke-width: 4px; }
            100% { transform: scale(2.5); opacity: 0; stroke-width: 1px; }
        }

        .arc-flash { opacity: 0; pointer-events: none; }
        .is-working .arc-flash { animation: flashArc 3s infinite; }
        @keyframes flashArc {
            0%, 90%, 100% { opacity: 0; }
            92%, 96% { opacity: 1; filter: drop-shadow(0 0 10px var(--ui-cyan)); }
            94%, 98% { opacity: 0.2; }
        }

    </style>
</head>
<body>
    <!-- 边缘分布的 UI 信息层 -->
    <div class="hud-layer">
        <div class="hud-top">
            <div class="panel panel-left">
                <div class="title">传统作业痛点仿真分析</div>
                <div class="desc">
                    正在执行 <span style="color:var(--ui-cyan)">12节点</span> 人工作业流程:<br>
                    1. <span class="highlight-red">停电范围大</span>,严重影响供电可靠性。<br>
                    2. <span class="highlight-amber">高坠/触电风险高</span>,人工登杆缺乏预警。<br>
                    3. 工具不趁手,<span class="highlight-red">绑扎缠绕耗时长</span>,劳动强度极大。
                </div>
            </div>

            <div class="panel panel-right">
                <div class="stat-label">单次故障平均停电</div>
                <div>
                    <span class="stat-value" id="ui-timer" style="color: var(--ui-cyan);">0</span>
                    <span class="stat-unit">MIN</span>
                </div>
                <div class="stat-label" style="margin-top: 12px;">当前阶段状态</div>
                <div class="stat-label" id="ui-status" style="color: var(--ui-cyan); font-weight: bold; font-size: 14px;">准备中</div>
            </div>
        </div>

        <div class="risk-alert" id="risk-alert">
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path><line x1="12" y1="9" x2="12" y2="13"></line><line x1="12" y1="17" x2="12.01" y2="17"></line></svg>
            <span id="risk-text">高空作业/触电警告</span>
        </div>

        <div class="hud-bottom">
            <div class="panel-timeline" id="timeline">
                <!-- JS 动态生成 12 步 -->
            </div>
        </div>
    </div>

    <!-- 居中核心 SVG 动画区 -->
    <div class="svg-canvas">
        <svg viewBox="0 0 800 800" preserveAspectRatio="xMidYMid meet" id="main-svg">
            <!-- 场景背景与基建 -->
            <g id="environment">
                <!-- 地平线 -->
                <line x1="100" y1="700" x2="700" y2="700" stroke="#334155" stroke-width="2"/>
                <!-- 电线杆 -->
                <polygon points="385,700 415,700 408,150 392,150" fill="#1E293B" stroke="#0F172A" stroke-width="2"/>
                <line x1="392" y1="150" x2="385" y2="700" stroke="#0F172A" stroke-width="1"/>
                
                <!-- 横担及支架 -->
                <rect x="250" y="200" width="300" height="16" fill="#334155" rx="2" stroke="#0F172A"/>
                <line x1="280" y1="216" x2="400" y2="280" stroke="#334155" stroke-width="8"/>
                <line x1="520" y1="216" x2="400" y2="280" stroke="#334155" stroke-width="8"/>
                
                <!-- 绝缘子 -->
                <path d="M270,170 L290,170 L285,200 L275,200 Z" fill="#94A3B8"/>
                <path d="M390,170 L410,170 L405,200 L395,200 Z" fill="#94A3B8"/>
                <path d="M510,170 L530,170 L525,200 L515,200 Z" fill="#94A3B8"/>
            </g>

            <!-- 输电线 -->
            <g id="power-lines">
                <!-- 左侧导线 -->
                <path id="wire-l" class="power-line glow-cyan" d="M -50,160 Q 150,220 280,170" fill="none" stroke-width="4"/>
                <path id="flow-l" class="energy-flow glow-cyan" d="M -50,160 Q 150,220 280,170" fill="none" stroke="#fff" stroke-width="2"/>
                
                <!-- 中央导线 -->
                <path id="wire-c" class="power-line glow-cyan" d="M 280,170 Q 340,190 400,170" fill="none" stroke-width="4"/>
                
                <!-- 右侧导线 -->
                <path id="wire-r" class="power-line glow-cyan" d="M 400,170 Q 650,220 850,160" fill="none" stroke-width="4"/>
                <path id="flow-r" class="energy-flow glow-cyan" d="M 400,170 Q 650,220 850,160" fill="none" stroke="#fff" stroke-width="2"/>
            </g>

            <!-- 危险光晕圈 (登杆作业时显示) -->
            <circle class="hazard-ring" cx="380" cy="240" r="100" fill="none" stroke="var(--ui-red)"/>
            <circle class="hazard-ring" cx="380" cy="240" r="100" fill="none" stroke="var(--ui-amber)" style="animation-delay: 1s;"/>

            <!-- 感应电弧 (触电风险) -->
            <path class="arc-flash" d="M 380,170 L 370,200 L 390,210 L 375,240" fill="none" stroke="#FFF" stroke-width="3" filter="drop-shadow(0 0 5px var(--ui-cyan))"/>
            <path class="arc-flash" d="M 410,170 L 420,190 L 405,210 L 415,230" fill="none" stroke="#FFF" stroke-width="2" style="animation-delay: 0.5s;"/>

            <!-- 人物角色 (动态绑定 CSS 类) -->
            <g id="worker-group">
                <g id="worker-body">
                    <!-- 安全带连结杆 -->
                    <path d="M 0,10 Q 20,20 30,0" fill="none" stroke="#94A3B8" stroke-width="2" stroke-dasharray="4 2"/>
                    
                    <!-- 身体与装备 -->
                    <rect x="-8" y="0" width="16" height="30" fill="#FF9F0A" rx="4"/> <!-- 工作服 -->
                    <rect x="-10" y="15" width="20" height="5" fill="#334155"/> <!-- 安全腰带 -->
                    
                    <!-- 左腿 -->
                    <g transform="translate(-4, 30)">
                        <line class="limb leg-left" x1="0" y1="0" x2="-5" y2="25" stroke="#FF9F0A" stroke-width="6" stroke-linecap="round"/>
                    </g>
                    <!-- 右腿 -->
                    <g transform="translate(4, 30)">
                        <line class="limb leg-right" x1="0" y1="0" x2="5" y2="25" stroke="#FF9F0A" stroke-width="6" stroke-linecap="round"/>
                    </g>

                    <!-- 左臂 -->
                    <g transform="translate(-8, 5)">
                        <line class="limb arm-left" x1="0" y1="0" x2="-15" y2="20" stroke="#FF9F0A" stroke-width="5" stroke-linecap="round"/>
                    </g>
                    <!-- 右臂 (持手持工具) -->
                    <g transform="translate(8, 5)">
                        <g class="limb arm-right">
                            <line x1="0" y1="0" x2="15" y2="20" stroke="#FF9F0A" stroke-width="5" stroke-linecap="round"/>
                            <!-- 钳子/工具 -->
                            <path d="M 15,20 L 25,25 M 15,20 L 22,28" stroke="#E2E8F0" stroke-width="2"/>
                        </g>
                    </g>

                    <!-- 头部与安全帽 -->
                    <circle cx="0" cy="-8" r="8" fill="#FCD34D"/> <!-- 脸 -->
                    <path d="M -12,-10 Q 0,-25 12,-10 Z" fill="#F59E0B"/> <!-- 安全帽 -->
                    <line x1="-12" y1="-10" x2="12" y2="-10" stroke="#D97706" stroke-width="2"/>
                </g>
            </g>

        </svg>
    </div>

    <!-- 逻辑控制脚本 -->
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            // 定义 12 个操作步骤及时间分配 (总计模拟一整个完整循环)
            // 痛点集中在 6-9 步,重点分配时间占比以突出 "耗时长"
            const STEPS = [
                { name: "现场勘查", type: "prep", duration: 1500 },
                { name: "开票", type: "prep", duration: 1500 },
                { name: "工作许可", type: "prep", duration: 1500 },
                { name: "停电", type: "outage", duration: 1500 },
                { name: "转检修", type: "outage", duration: 1500 },
                { name: "登杆", type: "climb", duration: 4000 },
                { name: "更换绝缘子", type: "work", duration: 4000 },
                { name: "绑扎线缠绕", type: "work", duration: 5000 },
                { name: "紧固", type: "work", duration: 3000 },
                { name: "转运行", type: "descend", duration: 2500 },
                { name: "恢复供电", type: "restore", duration: 1500 },
                { name: "工作终结", type: "done", duration: 2000 }
            ];

            const timelineEl = document.getElementById('timeline');
            const uiTimer = document.getElementById('ui-timer');
            const uiStatus = document.getElementById('ui-status');
            const riskAlert = document.getElementById('risk-alert');
            const riskText = document.getElementById('risk-text');
            
            const workerGroup = document.getElementById('main-svg');
            const powerLines = document.querySelectorAll('.power-line, .energy-flow');

            // 渲染底部时间轴
            STEPS.forEach((step, idx) => {
                const el = document.createElement('div');
                el.className = 'timeline-step';
                el.id = `step-${idx}`;
                el.innerHTML = `
                    <div class="step-dot"></div>
                    <div class="step-text">${idx + 1}.${step.name}</div>
                `;
                timelineEl.appendChild(el);
            });

            const stepEls = document.querySelectorAll('.timeline-step');
            const totalCycleTime = STEPS.reduce((a, b) => a + b.duration, 0) + 1000; // 留白1秒

            let startTime = null;
            let currentStepIdx = -1;

            function animate(timestamp) {
                if (!startTime) startTime = timestamp;
                
                // 计算循环时间
                const elapsed = (timestamp - startTime) % totalCycleTime;
                
                // 查找当前阶段
                let accTime = 0;
                let newStepIdx = STEPS.length - 1;
                
                for (let i = 0; i < STEPS.length; i++) {
                    if (elapsed >= accTime && elapsed < accTime + STEPS[i].duration) {
                        newStepIdx = i;
                        break;
                    }
                    accTime += STEPS[i].duration;
                }

                // 如果处于重置期
                if (elapsed > totalCycleTime - 1000) {
                    newStepIdx = -1;
                }

                // 阶段发生变化时,触发状态更新
                if (newStepIdx !== currentStepIdx && newStepIdx >= 0) {
                    currentStepIdx = newStepIdx;
                    const step = STEPS[currentStepIdx];
                    updateVisuals(currentStepIdx, step);
                }

                // 计算停电计时器显示 (映射 120 分钟)
                // 停电从第4步(idx 3)开始,第11步(idx 10)恢复
                let simTime = 0;
                if (currentStepIdx >= 3 && currentStepIdx < 11) {
                    const outageStart = STEPS.slice(0, 3).reduce((a,b)=>a+b.duration, 0);
                    const outageEnd = STEPS.slice(0, 11).reduce((a,b)=>a+b.duration, 0);
                    const outageElapsed = elapsed - outageStart;
                    const ratio = Math.min(1, Math.max(0, outageElapsed / (outageEnd - outageStart)));
                    
                    // 在 "绑扎线缠绕" 阶段让时间走得飞快,突出痛点
                    if(step.type === 'work') {
                         simTime = Math.floor(ratio * 120); 
                    } else {
                         simTime = Math.floor(ratio * 120);
                    }
                    
                    uiTimer.textContent = simTime;
                    uiTimer.style.color = simTime > 80 ? 'var(--ui-red)' : 'var(--ui-amber)';
                } else if (currentStepIdx >= 11) {
                    uiTimer.textContent = 120;
                    uiTimer.style.color = 'var(--ui-text)';
                } else {
                    uiTimer.textContent = 0;
                    uiTimer.style.color = 'var(--ui-cyan)';
                }

                requestAnimationFrame(animate);
            }

            function updateVisuals(idx, step) {
                // 更新 UI 步骤条
                stepEls.forEach((el, i) => {
                    el.className = 'timeline-step';
                    if (i < idx) el.classList.add('done');
                    if (i === idx) {
                        el.classList.add('active');
                        if (step.type === 'outage' || step.type === 'climb' || step.type === 'work') {
                            el.classList.add('danger');
                        }
                    }
                });

                uiStatus.textContent = `${idx + 1}. ${step.name}`;

                // 核心状态机逻辑 - 通过挂载 className 到 SVG root 来控制内部元素的 CSS 动画
                workerGroup.className.baseVal = '';
                riskAlert.classList.remove('show');
                
                switch(step.type) {
                    case 'prep':
                        uiStatus.style.color = 'var(--ui-cyan)';
                        powerLines.forEach(l => l.classList.remove('outage'));
                        break;
                    case 'outage':
                        uiStatus.style.color = 'var(--ui-red)';
                        powerLines.forEach(l => l.classList.add('outage'));
                        riskAlert.classList.add('show');
                        riskText.textContent = "停电转检修:大面积停电发生";
                        break;
                    case 'climb':
                        uiStatus.style.color = 'var(--ui-amber)';
                        workerGroup.className.baseVal = 'is-climbing';
                        riskAlert.classList.add('show');
                        riskText.textContent = "高危作业:人工登杆 存在高坠风险";
                        break;
                    case 'work':
                        uiStatus.style.color = 'var(--ui-red)';
                        workerGroup.className.baseVal = 'is-working';
                        riskAlert.classList.add('show');
                        riskText.textContent = "痛点:绑扎耗时长,工具不趁手,触电风险高";
                        break;
                    case 'descend':
                        uiStatus.style.color = 'var(--ui-amber)';
                        workerGroup.className.baseVal = 'is-descending';
                        break;
                    case 'restore':
                    case 'done':
                        uiStatus.style.color = 'var(--ui-cyan)';
                        powerLines.forEach(l => l.classList.remove('outage'));
                        break;
                }
            }

            // 启动引擎
            requestAnimationFrame(animate);
        });
    </script>
</body>
</html>
<!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: #0b1120;
            --panel-bg: rgba(15, 23, 42, 0.95);
            --grid-line: rgba(51, 65, 85, 0.3);
            
            /* 状态色彩 */
            --color-safe: #10B981;     /* 运行正常:翠绿 */
            --color-warn: #F59E0B;     /* 警告/攀爬:明黄 */
            --color-danger: #EF4444;   /* 停电/高危:鲜红 */
            --color-accent: #3B82F6;   /* UI高亮:亮蓝 */
            
            /* 字体色彩 (确保极高可读性) */
            --text-main: #F8FAFC;      /* 主文本:纯白偏蓝 */
            --text-muted: #94A3B8;     /* 次文本:浅灰 */
            
            /* 字体设置 - 选用最易读的无衬线黑体 */
            --font-family: 'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', Arial, sans-serif;
            --font-mono: 'SFMono-Regular', Consolas, Monaco, monospace;
        }

        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            background-color: var(--bg-color);
            background-image: 
                linear-gradient(var(--grid-line) 1px, transparent 1px),
                linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
            background-size: 50px 50px;
            font-family: var(--font-family);
            color: var(--text-main);
            overflow: hidden;
        }

        /* ==================== 布局与面板 (HUD) ==================== */
        .hud-container {
            position: absolute;
            inset: 0;
            pointer-events: none; /* 让鼠标事件穿透到动画区 */
            z-index: 100;
            display: flex;
            flex-direction: column;
            justify-content: space-between;
        }

        .panel {
            background: var(--panel-bg);
            border: 1px solid rgba(148, 163, 184, 0.2);
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
            backdrop-filter: blur(8px);
            border-radius: 8px;
            pointer-events: auto;
        }

        /* 顶部区域 */
        .hud-top {
            display: flex;
            justify-content: space-between;
            padding: 24px;
            align-items: flex-start;
        }

        /* 左上:痛点分析面板 */
        .panel-left {
            width: 360px;
            padding: 24px;
            border-left: 6px solid var(--color-danger);
        }

        .panel-title {
            font-size: 22px;
            font-weight: bold;
            color: var(--text-main);
            margin-bottom: 16px;
            display: flex;
            align-items: center;
            gap: 10px;
        }

        .panel-title::before {
            content: '';
            display: block;
            width: 12px;
            height: 12px;
            background: var(--color-danger);
            border-radius: 50%;
            box-shadow: 0 0 10px var(--color-danger);
        }

        .pain-points {
            list-style: none;
            padding: 0;
            margin: 0;
            display: flex;
            flex-direction: column;
            gap: 12px;
        }

        .pain-points li {
            font-size: 15px;
            line-height: 1.6;
            color: var(--text-muted);
            background: rgba(255,255,255,0.03);
            padding: 10px 14px;
            border-radius: 6px;
            border-left: 3px solid transparent;
        }
        
        .pain-points li.highlight-danger {
            border-left-color: var(--color-danger);
            color: var(--text-main);
        }
        .pain-points li.highlight-warn {
            border-left-color: var(--color-warn);
            color: var(--text-main);
        }
        
        .keyword-red { color: #FFA3A3; font-weight: bold; }
        .keyword-yellow { color: #FDE047; font-weight: bold; }

        /* 右上:停电计时器面板 */
        .panel-right {
            width: 280px;
            padding: 20px 24px;
            text-align: right;
            border-right: 6px solid var(--color-warn);
            display: flex;
            flex-direction: column;
            align-items: flex-end;
        }

        .timer-label {
            font-size: 16px;
            color: var(--text-muted);
            margin-bottom: 8px;
            font-weight: 500;
        }

        .timer-display {
            display: flex;
            align-items: baseline;
            gap: 8px;
        }

        .timer-value {
            font-size: 64px;
            font-weight: bold;
            font-family: var(--font-mono);
            color: var(--color-safe);
            line-height: 1;
            text-shadow: 0 0 20px rgba(16, 185, 129, 0.4);
            transition: color 0.3s, text-shadow 0.3s;
        }
        
        .timer-value.outage {
            color: var(--color-danger);
            text-shadow: 0 0 20px rgba(239, 68, 68, 0.6);
        }

        .timer-unit {
            font-size: 20px;
            color: var(--text-muted);
            font-weight: bold;
        }

        /* 底部:进度与流程监控 */
        .hud-bottom {
            padding: 24px;
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 16px;
        }

        .current-action-display {
            background: rgba(15, 23, 42, 0.9);
            border: 2px solid var(--color-accent);
            padding: 12px 32px;
            border-radius: 30px;
            font-size: 24px;
            font-weight: bold;
            color: var(--color-accent);
            box-shadow: 0 0 20px rgba(59, 130, 246, 0.3);
            transition: all 0.3s;
        }

        .timeline {
            display: flex;
            width: 90%;
            max-width: 1200px;
            background: var(--panel-bg);
            padding: 16px 24px;
            border-radius: 12px;
            justify-content: space-between;
            align-items: center;
            border: 1px solid rgba(148, 163, 184, 0.2);
            position: relative;
        }

        /* 进度条背景线 */
        .timeline::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 40px;
            right: 40px;
            height: 4px;
            background: rgba(148, 163, 184, 0.2);
            z-index: 0;
            transform: translateY(-50%);
        }

        .step-item {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 8px;
            z-index: 1;
            opacity: 0.4;
            transition: opacity 0.3s, transform 0.3s;
        }

        .step-item.active {
            opacity: 1;
            transform: scale(1.15);
        }
        
        .step-item.done {
            opacity: 0.8;
        }

        .step-dot {
            width: 16px;
            height: 16px;
            border-radius: 50%;
            background: #334155;
            border: 3px solid var(--panel-bg);
            transition: all 0.3s;
        }

        .step-item.active .step-dot {
            background: var(--color-accent);
            box-shadow: 0 0 15px var(--color-accent);
        }
        .step-item.active.danger-step .step-dot {
            background: var(--color-danger);
            box-shadow: 0 0 15px var(--color-danger);
        }

        .step-text {
            font-size: 14px;
            font-weight: bold;
            color: var(--text-main);
            white-space: nowrap;
        }

        /* 悬浮警报框 (杆上作业时显示) */
        .floating-alert {
            position: absolute;
            top: 150px;
            left: 50%;
            transform: translateX(-50%);
            background: rgba(239, 68, 68, 0.15);
            border: 2px solid var(--color-danger);
            padding: 12px 24px;
            border-radius: 8px;
            display: flex;
            align-items: center;
            gap: 12px;
            opacity: 0;
            transition: opacity 0.3s;
        }

        .floating-alert.show {
            opacity: 1;
            animation: alertPulse 1.5s infinite alternate;
        }

        .alert-icon {
            font-size: 24px;
        }

        .alert-text {
            font-size: 18px;
            font-weight: bold;
            color: #FFA3A3;
        }

        @keyframes alertPulse {
            0% { box-shadow: 0 0 10px rgba(239, 68, 68, 0.4); }
            100% { box-shadow: 0 0 30px rgba(239, 68, 68, 0.8); }
        }


        /* ==================== SVG 动画核心区 ==================== */
        .svg-container {
            position: absolute;
            inset: 0;
            width: 100%;
            height: 100%;
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 10;
        }

        svg {
            width: 100%;
            height: 100%;
            max-width: 1400px;
            max-height: 1000px;
            overflow: visible;
        }

        /* 环境与电网 */
        .env-ground { stroke: #334155; stroke-width: 3; }
        .pole-base { fill: #1E293B; stroke: #0F172A; stroke-width: 2; }
        .crossarm { fill: #334155; stroke: #0F172A; stroke-width: 2; }
        .insulator { fill: #94A3B8; stroke: #475569; stroke-width: 2; }
        
        /* 输电线 (动态颜色) */
        .power-line {
            stroke: var(--color-safe);
            stroke-width: 5;
            fill: none;
            transition: stroke 0.5s;
            filter: drop-shadow(0 0 8px var(--color-safe));
        }
        
        /* 电流动画 */
        .energy-flow {
            stroke: #FFF;
            stroke-width: 2;
            stroke-dasharray: 15 30;
            fill: none;
            animation: flowAnim 1s linear infinite;
        }

        @keyframes flowAnim {
            to { stroke-dashoffset: -45; }
        }

        /* 停电状态 */
        body[data-status="outage"] .power-line {
            stroke: #475569;
            filter: none;
        }
        body[data-status="outage"] .energy-flow {
            display: none;
        }

        /* 人员动作 (CSS Keyframes) */
        #worker {
            transform: translate(500px, 750px); /* 默认地面位置 */
            transition: transform 0.5s;
        }

        .worker-body { fill: var(--color-warn); }
        .worker-belt { fill: #334155; stroke: #0F172A; stroke-width: 1.5; }
        .worker-head { fill: #FDE047; }
        .worker-limb { stroke: var(--color-warn); stroke-width: 8; stroke-linecap: round; }
        
        /* 设置关节变换中心 */
        #arm-l, #arm-r { transform-origin: top center; }
        #leg-l, #leg-r { transform-origin: top center; }
        #worker-torso { transform-origin: center bottom; }

        /* 动作类:攀爬中 */
        .anim-climbing #worker { animation: climbMove 3s linear forwards; }
        .anim-climbing #arm-l { animation: climbArmL 0.6s infinite alternate; }
        .anim-climbing #arm-r { animation: climbArmR 0.6s infinite alternate; }
        .anim-climbing #leg-l { animation: climbLegL 0.6s infinite alternate; }
        .anim-climbing #leg-r { animation: climbLegR 0.6s infinite alternate; }

        @keyframes climbMove {
            0% { transform: translate(500px, 750px); }
            100% { transform: translate(500px, 320px); } /* 爬到横担下方 */
        }
        @keyframes climbArmL { 0% { transform: rotate(-40deg); } 100% { transform: rotate(10deg); } }
        @keyframes climbArmR { 0% { transform: rotate(10deg); } 100% { transform: rotate(-40deg); } }
        @keyframes climbLegL { 0% { transform: rotate(-15deg); } 100% { transform: rotate(30deg); } }
        @keyframes climbLegR { 0% { transform: rotate(30deg); } 100% { transform: rotate(-15deg); } }

        /* 动作类:杆上作业 (费力、耗时) */
        .anim-working #worker { transform: translate(500px, 320px); }
        .anim-working #worker-torso { animation: workStruggle 1.5s infinite alternate ease-in-out; }
        .anim-working #arm-l { transform: rotate(-70deg); animation: workToolL 0.4s infinite alternate; }
        .anim-working #arm-r { transform: rotate(-110deg); animation: workToolR 0.3s infinite alternate; }
        .anim-working #leg-l { transform: rotate(20deg); }
        .anim-working #leg-r { transform: rotate(-10deg); }

        @keyframes workStruggle { 0% { transform: rotate(-5deg); } 100% { transform: rotate(8deg); } }
        @keyframes workToolL { 0% { transform: rotate(-70deg); } 100% { transform: rotate(-50deg); } }
        @keyframes workToolR { 0% { transform: rotate(-110deg); } 100% { transform: rotate(-80deg); } } /* 幅度大,体现工具不趁手 */

        /* 动作类:下降 */
        .anim-descending #worker { animation: descendMove 2s linear forwards; }
        .anim-descending #arm-l { animation: climbArmL 0.5s infinite alternate reverse; }
        .anim-descending #arm-r { animation: climbArmR 0.5s infinite alternate reverse; }
        .anim-descending #leg-l { animation: climbLegL 0.5s infinite alternate reverse; }
        .anim-descending #leg-r { animation: climbLegR 0.5s infinite alternate reverse; }

        @keyframes descendMove {
            0% { transform: translate(500px, 320px); }
            100% { transform: translate(500px, 750px); }
        }

        /* 危险特效:高空坠落与触电红圈 */
        .danger-ring {
            opacity: 0;
            transform-origin: 500px 300px;
            pointer-events: none;
            fill: none;
            stroke-width: 4;
        }
        
        body[data-status="danger"] .danger-ring.ring-red {
            stroke: var(--color-danger);
            animation: ringExpand 2s infinite cubic-bezier(0.1, 0.8, 0.3, 1);
        }
        body[data-status="danger"] .danger-ring.ring-warn {
            stroke: var(--color-warn);
            animation: ringExpand 2s infinite cubic-bezier(0.1, 0.8, 0.3, 1);
            animation-delay: 1s;
        }

        @keyframes ringExpand {
            0% { transform: scale(0.2); opacity: 1; stroke-width: 8; }
            100% { transform: scale(3.5); opacity: 0; stroke-width: 1; }
        }

        /* 工具费时指示器 (沙漏或旋转图标) */
        .tool-spinner {
            opacity: 0;
            transform-origin: 500px 220px;
            transition: opacity 0.3s;
        }
        body[data-status="working-heavy"] .tool-spinner {
            opacity: 1;
            animation: spin 3s linear infinite;
        }
        @keyframes spin { 100% { transform: rotate(360deg); } }

    </style>
</head>
<body data-status="normal">

    <!-- ==================== UI 覆盖层 ==================== -->
    <div class="hud-container">
        <!-- 顶部左右面板 -->
        <div class="hud-top">
            <!-- 痛点面板 -->
            <div class="panel panel-left">
                <div class="panel-title">传统作业痛点诊断</div>
                <ul class="pain-points">
                    <li id="pain-1">作业依赖拉闸断电,<span class="keyword-red">停电范围大</span>,严重影响供电可靠性。</li>
                    <li id="pain-2">人工登杆与高空操作,存在极高<span class="keyword-red">高坠与触电风险</span>,缺乏实时预警。</li>
                    <li id="pain-3">手工绑扎线缠绕,<span class="keyword-yellow">工具不趁手</span>且<span class="keyword-red">耗时长</span>,劳动强度极大。</li>
                </ul>
            </div>

            <!-- 计时面板 -->
            <div class="panel panel-right">
                <div class="timer-label">单次故障平均停电</div>
                <div class="timer-display">
                    <div class="timer-value" id="ui-timer">000</div>
                    <div class="timer-unit">分钟</div>
                </div>
                <div style="font-size: 14px; color: var(--text-muted); margin-top: 12px; font-weight: bold;">12 节点全流程仿真进行中...</div>
            </div>
        </div>

        <!-- 居中高危警报 (仅在杆上作业显示) -->
        <div class="floating-alert" id="hazard-alert">
            <span class="alert-icon">⚠️</span>
            <span class="alert-text">高坠 / 触电高危区域!人工绑扎耗时激增!</span>
        </div>

        <!-- 底部流程控制 -->
        <div class="hud-bottom">
            <div class="current-action-display" id="ui-current-action">1. 现场勘查</div>
            
            <div class="timeline" id="timeline-container">
                <!-- 12个步骤将由 JS 动态生成 -->
            </div>
        </div>
    </div>

    <!-- ==================== SVG 核心动画 ==================== -->
    <div class="svg-container">
        <svg viewBox="0 0 1000 900" preserveAspectRatio="xMidYMid meet" id="main-scene">
            <!-- 场景背景网格与地平线 -->
            <line class="env-ground" x1="100" y1="750" x2="900" y2="750" />
            
            <!-- 电线杆主体 -->
            <g id="pole-structure">
                <!-- 杆体 -->
                <polygon class="pole-base" points="485,750 515,750 508,180 492,180" />
                <line x1="500" y1="180" x2="500" y2="750" stroke="#0F172A" stroke-width="2" stroke-dasharray="10 10"/>
                
                <!-- 主横担 -->
                <rect class="crossarm" x="300" y="240" width="400" height="24" rx="4" />
                
                <!-- 支撑架 -->
                <line x1="340" y1="264" x2="500" y2="350" stroke="#334155" stroke-width="12" />
                <line x1="660" y1="264" x2="500" y2="350" stroke="#334155" stroke-width="12" />
                
                <!-- 绝缘子 -->
                <path class="insulator" d="M 330,190 L 370,190 L 360,240 L 340,240 Z" />
                <path class="insulator" d="M 480,190 L 520,190 L 510,240 L 490,240 Z" />
                <path class="insulator" d="M 630,190 L 670,190 L 660,240 L 640,240 Z" />
            </g>

            <!-- 输电线路 (动态受控) -->
            <g id="power-lines">
                <!-- 左线 -->
                <path class="power-line" d="M -50,180 Q 200,280 350,190" />
                <path class="energy-flow" d="M -50,180 Q 200,280 350,190" />
                
                <!-- 中线 -->
                <path class="power-line" d="M 350,190 Q 425,220 500,190" />
                
                <!-- 右线 -->
                <path class="power-line" d="M 500,190 Q 750,280 1050,180" />
                <path class="energy-flow" d="M 500,190 Q 750,280 1050,180" />
            </g>

            <!-- 危险光晕圈 (高空作业时触发) -->
            <circle class="danger-ring ring-red" cx="500" cy="240" r="80" />
            <circle class="danger-ring ring-warn" cx="500" cy="240" r="80" />

            <!-- 耗时工具指示器 -->
            <g class="tool-spinner">
                <circle cx="500" cy="220" r="60" fill="none" stroke="var(--color-warn)" stroke-width="4" stroke-dasharray="20 15" />
                <path d="M 490,170 L 510,170 L 500,190 Z" fill="var(--color-warn)"/>
                <path d="M 490,270 L 510,270 L 500,250 Z" fill="var(--color-warn)"/>
                <text x="500" y="150" fill="var(--color-warn)" font-size="20" font-weight="bold" text-anchor="middle" font-family="var(--font-family)">费时费力</text>
            </g>

            <!-- 作业人员 (通过 className 切换动作) -->
            <g id="worker" class="anim-idle">
                <g transform="translate(0, -60)"> <!-- 调整人物整体重心 -->
                    <!-- 安全带绑扎点 -->
                    <path d="M 0,40 Q 30,50 45,-10" fill="none" stroke="#94A3B8" stroke-width="3" stroke-dasharray="6 4"/>
                    
                    <!-- 身体躯干 -->
                    <g id="worker-torso">
                        <rect class="worker-body" x="-14" y="0" width="28" height="50" rx="8"/>
                        <rect class="worker-belt" x="-16" y="25" width="32" height="10" rx="2"/> <!-- 安全腰带 -->
                        
                        <!-- 左臂 -->
                        <g transform="translate(-14, 10)">
                            <line id="arm-l" class="worker-limb" x1="0" y1="0" x2="-20" y2="30" />
                        </g>
                        <!-- 右臂 -->
                        <g transform="translate(14, 10)">
                            <line id="arm-r" class="worker-limb" x1="0" y1="0" x2="20" y2="30" />
                        </g>
                        
                        <!-- 左腿 -->
                        <g transform="translate(-8, 50)">
                            <line id="leg-l" class="worker-limb" x1="0" y1="0" x2="-10" y2="40" />
                        </g>
                        <!-- 右腿 -->
                        <g transform="translate(8, 50)">
                            <line id="leg-r" class="worker-limb" x1="0" y1="0" x2="10" y2="40" />
                        </g>

                        <!-- 头部与安全帽 -->
                        <circle cx="0" cy="-12" r="14" fill="#FCD34D" /> <!-- 面部 -->
                        <path d="M -18,-15 Q 0,-40 18,-15 Z" class="worker-head" /> <!-- 头盔 -->
                        <line x1="-20" y1="-15" x2="20" y2="-15" stroke="#CA8A04" stroke-width="3" stroke-linecap="round"/>
                    </g>
                </g>
            </g>
            
        </svg>
    </div>

    <!-- ==================== 逻辑控制脚本 ==================== -->
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            // 定义 12 个操作步骤及时间分配 (毫秒)
            // 为了凸显痛点,将第6,7,8步的时间拉长
            const STEPS = [
                { id: 1, name: "现场勘查", type: "prep", duration: 1500 },
                { id: 2, name: "开票", type: "prep", duration: 1000 },
                { id: 3, name: "工作许可", type: "prep", duration: 1000 },
                { id: 4, name: "停电", type: "outage", duration: 1500 },
                { id: 5, name: "转检修", type: "outage", duration: 1000 },
                { id: 6, name: "登杆", type: "climb", duration: 3500 },
                { id: 7, name: "更换绝缘子", type: "work", duration: 3000 },
                { id: 8, name: "绑扎线缠绕", type: "work-heavy", duration: 4500 },
                { id: 9, name: "紧固", type: "work", duration: 2000 },
                { id: 10, name: "转运行", type: "descend", duration: 2500 },
                { id: 11, name: "恢复供电", type: "restore", duration: 1500 },
                { id: 12, name: "工作终结", type: "done", duration: 2000 }
            ];

            const totalDuration = STEPS.reduce((sum, step) => sum + step.duration, 0) + 1500; // 留白1.5秒

            // DOM 元素引用
            const timelineContainer = document.getElementById('timeline-container');
            const uiTimer = document.getElementById('ui-timer');
            const uiCurrentAction = document.getElementById('ui-current-action');
            const hazardAlert = document.getElementById('hazard-alert');
            const workerEl = document.getElementById('worker');
            
            const painItems = [
                document.getElementById('pain-1'),
                document.getElementById('pain-2'),
                document.getElementById('pain-3')
            ];

            // 1. 初始化底部 12 步时间轴 (确保字体大而清晰)
            STEPS.forEach((step, index) => {
                const stepEl = document.createElement('div');
                stepEl.className = 'step-item';
                stepEl.id = `step-node-${index}`;
                
                // 判断是否是高危/痛点步骤来给不同的颜色标记
                let isDanger = ['outage', 'climb', 'work', 'work-heavy'].includes(step.type);
                if (isDanger) stepEl.classList.add('danger-step');

                stepEl.innerHTML = `
                    <div class="step-dot"></div>
                    <div class="step-text">${step.id}</div>
                `;
                timelineContainer.appendChild(stepEl);
            });

            const stepNodes = document.querySelectorAll('.step-item');

            // 2. 动画引擎
            let startTime = null;
            let currentStepIdx = -1;

            function renderLoop(timestamp) {
                if (!startTime) startTime = timestamp;
                const elapsed = (timestamp - startTime) % totalDuration;
                
                // 确定当前处于哪个阶段
                let accTime = 0;
                let newStepIdx = STEPS.length - 1;
                
                for (let i = 0; i < STEPS.length; i++) {
                    if (elapsed >= accTime && elapsed < accTime + STEPS[i].duration) {
                        newStepIdx = i;
                        break;
                    }
                    accTime += STEPS[i].duration;
                }
                
                if (elapsed > totalDuration - 1500) {
                    newStepIdx = -1; // 休息重置期
                }

                // 阶段切换时更新 UI 状态
                if (newStepIdx !== currentStepIdx && newStepIdx >= 0) {
                    currentStepIdx = newStepIdx;
                    const step = STEPS[currentStepIdx];
                    updateSystemState(currentStepIdx, step);
                }

                // 计算 "120分钟" 停电倒计时映射
                // 停电始于步骤4(idx 3),终于步骤11(idx 10)
                let displayTime = 0;
                if (currentStepIdx >= 3 && currentStepIdx < 11) {
                    const outageStart = STEPS.slice(0, 3).reduce((s, st) => s + st.duration, 0);
                    const outageEnd = STEPS.slice(0, 11).reduce((s, st) => s + st.duration, 0);
                    const timeInOutage = elapsed - outageStart;
                    
                    // 制造一种在线路绑扎阶段时间飞逝的焦灼感
                    const progressRatio = timeInOutage / (outageEnd - outageStart);
                    // 使用缓动函数让绑扎阶段时间飙升
                    const easedRatio = Math.pow(progressRatio, 1.2); 
                    
                    displayTime = Math.min(120, Math.floor(easedRatio * 120));
                    uiTimer.classList.add('outage');
                } else if (currentStepIdx >= 11) {
                    displayTime = 120;
                    uiTimer.classList.remove('outage');
                } else {
                    displayTime = 0;
                    uiTimer.classList.remove('outage');
                }
                uiTimer.textContent = displayTime.toString().padStart(3, '0');

                requestAnimationFrame(renderLoop);
            }

            function updateSystemState(idx, step) {
                // 更新主标题栏
                uiCurrentAction.textContent = `${step.id}. ${step.name}`;

                // 节点点亮逻辑
                stepNodes.forEach((node, i) => {
                    node.className = 'step-item';
                    if (['outage', 'climb', 'work', 'work-heavy'].includes(STEPS[i].type)) {
                        node.classList.add('danger-step');
                    }
                    if (i < idx) node.classList.add('done');
                    if (i === idx) node.classList.add('active');
                });

                // 重置所有痛点高亮
                painItems.forEach(p => { p.classList.remove('highlight-danger'); p.classList.remove('highlight-warn'); });

                const body = document.body;
                workerEl.className.baseVal = '';
                hazardAlert.classList.remove('show');

                // 状态机处理
                switch(step.type) {
                    case 'prep':
                        body.setAttribute('data-status', 'normal');
                        uiCurrentAction.style.borderColor = "var(--color-safe)";
                        uiCurrentAction.style.color = "var(--color-safe)";
                        uiCurrentAction.style.boxShadow = "0 0 20px rgba(16, 185, 129, 0.3)";
                        break;
                        
                    case 'outage':
                        body.setAttribute('data-status', 'outage');
                        uiCurrentAction.style.borderColor = "var(--color-danger)";
                        uiCurrentAction.style.color = "var(--color-danger)";
                        uiCurrentAction.style.boxShadow = "0 0 20px rgba(239, 68, 68, 0.3)";
                        painItems[0].classList.add('highlight-danger');
                        break;
                        
                    case 'climb':
                        body.setAttribute('data-status', 'danger');
                        workerEl.className.baseVal = 'anim-climbing';
                        uiCurrentAction.style.borderColor = "var(--color-warn)";
                        uiCurrentAction.style.color = "var(--color-warn)";
                        uiCurrentAction.style.boxShadow = "0 0 20px rgba(245, 158, 11, 0.3)";
                        painItems[1].classList.add('highlight-warn');
                        hazardAlert.classList.add('show');
                        hazardAlert.querySelector('.alert-text').textContent = "正在登杆:存在高处坠落危险!";
                        break;
                        
                    case 'work':
                    case 'work-heavy':
                        // 如果是绑扎阶段,特别强调耗时和工具不趁手
                        if(step.type === 'work-heavy') {
                            body.setAttribute('data-status', 'working-heavy');
                            painItems[2].classList.add('highlight-danger');
                            hazardAlert.querySelector('.alert-text').textContent = "痛点爆发:手工绑扎极度耗时,工具不趁手!";
                        } else {
                            body.setAttribute('data-status', 'danger');
                            painItems[1].classList.add('highlight-danger');
                            hazardAlert.querySelector('.alert-text').textContent = "杆上作业:存在感应电触电高危风险!";
                        }
                        
                        workerEl.className.baseVal = 'anim-working';
                        uiCurrentAction.style.borderColor = "var(--color-danger)";
                        uiCurrentAction.style.color = "var(--color-danger)";
                        uiCurrentAction.style.boxShadow = "0 0 20px rgba(239, 68, 68, 0.5)";
                        hazardAlert.classList.add('show');
                        break;
                        
                    case 'descend':
                        body.setAttribute('data-status', 'outage');
                        workerEl.className.baseVal = 'anim-descending';
                        uiCurrentAction.style.borderColor = "var(--color-warn)";
                        uiCurrentAction.style.color = "var(--color-warn)";
                        uiCurrentAction.style.boxShadow = "0 0 20px rgba(245, 158, 11, 0.3)";
                        break;
                        
                    case 'restore':
                    case 'done':
                        body.setAttribute('data-status', 'normal');
                        workerEl.className.baseVal = 'anim-idle';
                        uiCurrentAction.style.borderColor = "var(--color-safe)";
                        uiCurrentAction.style.color = "var(--color-safe)";
                        uiCurrentAction.style.boxShadow = "0 0 20px rgba(16, 185, 129, 0.3)";
                        break;
                }
            }

            // 启动自动播放引擎
            requestAnimationFrame(renderLoop);
        });
    </script>
</body>
</html>
<!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: #080A0F;
            --grid-color: rgba(45, 55, 72, 0.2);
            --text-main: #FFFFFF;
            --text-muted: #94A3B8;
            --color-safe: #00F0FF;
            --color-warning: #FFAB00;
            --color-danger: #FF2A2A;
            --color-power: #39FF14;
            --panel-bg: rgba(12, 16, 25, 0.85);
            
            font-family: 'PingFang SC', 'Microsoft YaHei', system-ui, sans-serif;
        }

        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            background-color: var(--bg-color);
            background-image: 
                linear-gradient(var(--grid-color) 1px, transparent 1px),
                linear-gradient(90deg, var(--grid-color) 1px, transparent 1px);
            background-size: 40px 40px;
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
            color: var(--text-main);
        }

        /* ================= 边缘 HUD 面板 (确保高对比度与高清晰度,绝对不遮挡中心) ================= */
        .hud-layer {
            position: absolute;
            inset: 0;
            pointer-events: none;
            z-index: 100;
        }

        .panel {
            position: absolute;
            background: var(--panel-bg);
            border: 1px solid rgba(255, 255, 255, 0.1);
            backdrop-filter: blur(10px);
            padding: 16px;
            border-radius: 6px;
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
        }

        /* 字体清晰度保障:使用 14px,字重适中,极高对比度 */
        .panel-text {
            font-size: 14px;
            line-height: 1.6;
            color: var(--text-main);
            text-shadow: 0 1px 2px rgba(0,0,0,0.8);
        }

        .panel-title {
            font-size: 14px;
            font-weight: bold;
            color: var(--color-danger);
            margin-bottom: 8px;
            border-bottom: 1px solid rgba(255,42,42,0.3);
            padding-bottom: 4px;
            letter-spacing: 1px;
        }

        .top-left {
            top: 24px;
            left: 24px;
            width: 280px;
            border-left: 4px solid var(--color-danger);
        }

        .top-right {
            top: 24px;
            right: 24px;
            text-align: right;
            border-right: 4px solid var(--color-warning);
            min-width: 200px;
        }

        /* 动态时间显示 */
        .timer-display {
            font-family: 'Courier New', Courier, monospace;
            font-size: 36px;
            font-weight: bold;
            color: var(--color-danger);
            text-shadow: 0 0 10px rgba(255, 42, 42, 0.5);
            display: flex;
            align-items: baseline;
            justify-content: flex-end;
            gap: 4px;
        }
        .timer-unit {
            font-size: 14px;
            color: var(--text-muted);
        }

        .bottom-center {
            bottom: 24px;
            left: 50%;
            transform: translateX(-50%);
            width: 90%;
            max-width: 1000px;
            display: flex;
            justify-content: space-between;
            padding: 12px 24px;
            background: linear-gradient(180deg, rgba(12,16,25,0.6) 0%, rgba(12,16,25,0.95) 100%);
            border-top: 2px solid var(--color-safe);
        }

        /* 进度条指示器 */
        .step-item {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 8px;
            opacity: 0.4;
            transition: all 0.3s ease;
        }
        .step-item.active {
            opacity: 1;
            transform: translateY(-5px);
        }
        .step-item.done {
            opacity: 0.7;
        }
        .step-dot {
            width: 10px;
            height: 10px;
            border-radius: 50%;
            background: var(--text-muted);
            transition: all 0.3s ease;
        }
        .step-item.active .step-dot {
            background: var(--color-warning);
            box-shadow: 0 0 12px var(--color-warning);
        }
        .step-item.active.danger-step .step-dot {
            background: var(--color-danger);
            box-shadow: 0 0 12px var(--color-danger);
        }
        .step-name {
            font-size: 12px;
            font-weight: bold;
            writing-mode: vertical-rl;
            letter-spacing: 2px;
            color: var(--text-main);
        }

        /* 风险警告横幅 */
        .alert-banner {
            position: absolute;
            top: 100px;
            left: 50%;
            transform: translateX(-50%);
            background: rgba(255, 42, 42, 0.15);
            border: 1px solid var(--color-danger);
            color: var(--color-danger);
            padding: 8px 24px;
            font-size: 14px;
            font-weight: bold;
            border-radius: 20px;
            opacity: 0;
            transition: opacity 0.3s;
            backdrop-filter: blur(4px);
            display: flex;
            align-items: center;
            gap: 8px;
        }
        .alert-banner.show {
            opacity: 1;
            animation: pulseBanner 1s infinite alternate;
        }
        @keyframes pulseBanner {
            from { box-shadow: 0 0 5px rgba(255,42,42,0.2); }
            to { box-shadow: 0 0 20px rgba(255,42,42,0.6); }
        }

        /* ================= 核心 SVG 动画区域 ================= */
        .svg-container {
            width: 100vw;
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 10;
        }
        svg {
            width: 100%;
            height: 100%;
            max-width: 1200px;
            max-height: 900px;
            overflow: visible;
        }

        /* SVG 元素样式 */
        .line-power { stroke: var(--color-power); transition: stroke 0.5s; }
        .line-power.outage { stroke: var(--text-muted); opacity: 0.3; }
        
        .energy-dash { stroke-dasharray: 8 16; animation: flow 1s linear infinite; }
        .energy-dash.outage { opacity: 0; animation: none; }
        @keyframes flow { to { stroke-dashoffset: -24; } }

        /* ================= 人工作业动画控制 ================= */
        #worker {
            transform: translate(520px, 700px); /* 初始在地面 */
            transition: transform 0s linear;
        }

        /* 各个关节的变换原点 */
        #body-group { transform-origin: center bottom; }
        .arm-l { transform-origin: top right; }
        .arm-r { transform-origin: top left; }
        .leg-l, .leg-r { transform-origin: top center; }

        /* 状态 1: 登杆 (平移 + 四肢交替) */
        .state-climb #worker { animation: climbMove 3s linear forwards; }
        .state-climb .arm-l { animation: climbArmL 0.6s infinite alternate; }
        .state-climb .arm-r { animation: climbArmR 0.6s infinite alternate; }
        .state-climb .leg-l { animation: climbLegL 0.6s infinite alternate; }
        .state-climb .leg-r { animation: climbLegR 0.6s infinite alternate; }

        @keyframes climbMove {
            0% { transform: translate(520px, 700px); }
            100% { transform: translate(520px, 250px); }
        }
        @keyframes climbArmL { 0% { transform: rotate(-40deg); } 100% { transform: rotate(10deg); } }
        @keyframes climbArmR { 0% { transform: rotate(10deg); } 100% { transform: rotate(-40deg); } }
        @keyframes climbLegL { 0% { transform: rotate(-20deg) translateY(0); } 100% { transform: rotate(30deg) translateY(-15px); } }
        @keyframes climbLegR { 0% { transform: rotate(30deg) translateY(-15px); } 100% { transform: rotate(-20deg) translateY(0); } }

        /* 状态 2: 杆上作业 (剧烈手部动作表示绑扎耗时/工具不趁手) */
        .state-work #worker { transform: translate(520px, 250px); }
        .state-work #body-group { animation: workBody 0.8s infinite alternate ease-in-out; }
        .state-work .arm-l { animation: workArmL 0.3s infinite alternate; }
        .state-work .arm-r { animation: workArmR 0.4s infinite alternate; }
        .state-work .leg-l { transform: rotate(15deg); }
        .state-work .leg-r { transform: rotate(-15deg); }

        @keyframes workBody { 0% { transform: rotate(-3deg); } 100% { transform: rotate(3deg); } }
        @keyframes workArmL { 0% { transform: rotate(-90deg); } 100% { transform: rotate(-45deg); } }
        @keyframes workArmR { 0% { transform: rotate(-135deg); } 100% { transform: rotate(-30deg); } }

        /* 状态 3: 下降 */
        .state-descend #worker { animation: descendMove 2s linear forwards; }
        .state-descend .arm-l { animation: climbArmL 0.5s infinite alternate reverse; }
        .state-descend .arm-r { animation: climbArmR 0.5s infinite alternate reverse; }
        .state-descend .leg-l { animation: climbLegL 0.5s infinite alternate reverse; }
        .state-descend .leg-r { animation: climbLegR 0.5s infinite alternate reverse; }

        @keyframes descendMove {
            0% { transform: translate(520px, 250px); }
            100% { transform: translate(520px, 700px); }
        }

        /* 危险特效:坠落光圈与触电电弧 */
        .hazard-fall {
            opacity: 0;
            pointer-events: none;
            transform-origin: 500px 230px;
        }
        .state-work .hazard-fall, .state-climb .hazard-fall {
            animation: expandDanger 1.5s infinite ease-out;
        }
        @keyframes expandDanger {
            0% { transform: scale(0.5); opacity: 1; stroke-width: 4px; }
            100% { transform: scale(3); opacity: 0; stroke-width: 1px; }
        }

        .hazard-shock { opacity: 0; pointer-events: none; }
        .state-work .hazard-shock { animation: flashShock 2.5s infinite; }
        @keyframes flashShock {
            0%, 90%, 100% { opacity: 0; }
            92%, 96% { opacity: 1; filter: drop-shadow(0 0 12px var(--color-safe)); }
            94%, 98% { opacity: 0.3; }
        }

        /* 时间流逝特效 (作业时沙漏) */
        .time-loss { opacity: 0; transform-origin: 560px 200px; }
        .state-work .time-loss { animation: spinTime 3s linear infinite, fadeTime 0.5s forwards; }
        @keyframes spinTime { 100% { transform: rotate(360deg); } }
        @keyframes fadeTime { to { opacity: 1; } }

    </style>
</head>
<body>

    <!-- HUD 信息层 -->
    <div class="hud-layer">
        <!-- 左侧:痛点分析 -->
        <div class="panel top-left">
            <div class="panel-title">12节点传统作业痛点诊断</div>
            <div class="panel-text">
                当前作业依赖人工与大面积停电:<br>
                1. <span style="color:var(--color-danger); font-weight:bold;">停电影响大:</span>用户感知极差。<br>
                2. <span style="color:var(--color-warning); font-weight:bold;">高坠/触电风险:</span>杆上作业缺乏防护与预警。<br>
                3. <span style="color:var(--color-danger); font-weight:bold;">绑扎耗时长:</span>工具不趁手,纯手工缠绕极度费时。
            </div>
        </div>

        <!-- 右侧:动态时间监控 -->
        <div class="panel top-right">
            <div class="panel-title" style="border-bottom: 1px solid rgba(255,171,0,0.3); color: var(--color-warning);">单次故障平均停电</div>
            <div class="timer-display">
                <span id="ui-time">0</span>
                <span class="timer-unit">MIN</span>
            </div>
            <div class="panel-text" style="color:var(--text-muted); font-size:12px; margin-top:4px;">
                当前状态: <span id="ui-status" style="color:var(--color-safe); font-weight:bold;">正常运行</span>
            </div>
        </div>

        <!-- 顶部居中:高危告警 -->
        <div class="alert-banner" id="alert-banner">
            ⚠️ <span id="alert-text">警告:高危作业进行中</span>
        </div>

        <!-- 底部:12步时间轴 -->
        <div class="panel bottom-center" id="timeline">
            <!-- 由 JS 渲染 -->
        </div>
    </div>

    <!-- 核心动画画布 -->
    <div class="svg-container">
        <svg viewBox="0 0 1000 800" preserveAspectRatio="xMidYMid meet" id="svg-canvas">
            <!-- 背景环境 -->
            <g id="env">
                <!-- 地面 -->
                <line x1="100" y1="700" x2="900" y2="700" stroke="#1E293B" stroke-width="4"/>
                <line x1="200" y1="720" x2="800" y2="720" stroke="#0F172A" stroke-width="2"/>
                
                <!-- 主电线杆 -->
                <polygon points="485,700 515,700 508,120 492,120" fill="#1E293B" stroke="#0F172A" stroke-width="2"/>
                
                <!-- 顶部横担 -->
                <rect x="350" y="160" width="300" height="20" fill="#334155" rx="3" stroke="#0F172A"/>
                <path d="M 380,180 L 500,280 M 620,180 L 500,280" stroke="#334155" stroke-width="8" stroke-linecap="round"/>
                
                <!-- 绝缘子 -->
                <!-- 左 -->
                <rect x="370" y="120" width="20" height="40" fill="#94A3B8" rx="4"/>
                <path d="M 360,130 L 400,130 M 360,145 L 400,145" stroke="#475569" stroke-width="4" stroke-linecap="round"/>
                <!-- 中 -->
                <rect x="490" y="120" width="20" height="40" fill="#94A3B8" rx="4"/>
                <path d="M 480,130 L 520,130 M 480,145 L 520,145" stroke="#475569" stroke-width="4" stroke-linecap="round"/>
                <!-- 右 -->
                <rect x="610" y="120" width="20" height="40" fill="#94A3B8" rx="4"/>
                <path d="M 600,130 L 640,130 M 600,145 L 640,145" stroke="#475569" stroke-width="4" stroke-linecap="round"/>
            </g>

            <!-- 输电线路 -->
            <g id="wires">
                <!-- 左相 -->
                <path class="line-power wire-l" d="M -50,120 Q 200,180 380,120" fill="none" stroke-width="5"/>
                <path class="energy-dash wire-l" d="M -50,120 Q 200,180 380,120" fill="none" stroke="#FFF" stroke-width="2"/>
                
                <!-- 中相 (跨接) -->
                <path class="line-power wire-c" d="M 380,120 Q 500,140 620,120" fill="none" stroke-width="5"/>
                
                <!-- 右相 -->
                <path class="line-power wire-r" d="M 620,120 Q 800,180 1050,120" fill="none" stroke-width="5"/>
                <path class="energy-dash wire-r" d="M 620,120 Q 800,180 1050,120" fill="none" stroke="#FFF" stroke-width="2"/>
            </g>

            <!-- 危险指示特效 -->
            <!-- 坠落红圈 -->
            <circle class="hazard-fall" cx="500" cy="230" r="60" fill="none" stroke="var(--color-danger)"/>
            <circle class="hazard-fall" cx="500" cy="230" r="60" fill="none" stroke="var(--color-warning)" style="animation-delay: 0.75s;"/>
            <!-- 触电电弧 -->
            <path class="hazard-shock" d="M 490,120 L 470,160 L 510,180 L 490,220" fill="none" stroke="#FFF" stroke-width="4"/>
            <path class="hazard-shock" d="M 510,120 L 530,150 L 490,170 L 520,210" fill="none" stroke="#FFF" stroke-width="3" style="animation-delay: 0.3s;"/>
            
            <!-- 耗时沙漏图标 -->
            <g class="time-loss" stroke="var(--color-warning)" stroke-width="2" fill="none">
                <path d="M 550,180 L 570,180 L 560,195 Z" fill="rgba(255,171,0,0.5)"/>
                <path d="M 550,210 L 570,210 L 560,195 Z"/>
                <path d="M 545,180 L 575,180 M 545,210 L 575,210"/>
                <text x="580" y="200" fill="var(--color-warning)" font-size="12" font-family="monospace" stroke="none">TIME LOSS</text>
            </g>

            <!-- 作业人员骨骼与外观 -->
            <g id="worker">
                <g id="body-group">
                    <!-- 安全带连线 (虚拟展示) -->
                    <path d="M -15,10 Q -40,15 -15,40" fill="none" stroke="#64748B" stroke-width="2" stroke-dasharray="4 4"/>
                    
                    <!-- 躯干 -->
                    <rect x="-12" y="0" width="24" height="40" fill="#FF5722" rx="6"/>
                    <rect x="-14" y="20" width="28" height="6" fill="#1E293B"/> <!-- 安全腰带 -->

                    <!-- 头部 -->
                    <circle cx="0" cy="-10" r="10" fill="#FDE047"/>
                    <path d="M -15,-12 Q 0,-30 15,-12 Z" fill="#EAB308"/> <!-- 安全帽 -->
                    <line x1="-15" y1="-12" x2="15" y2="-12" stroke="#CA8A04" stroke-width="2"/>

                    <!-- 左臂 -->
                    <g transform="translate(-12, 6)">
                        <line class="arm-l" x1="0" y1="0" x2="-20" y2="25" stroke="#FF5722" stroke-width="8" stroke-linecap="round"/>
                    </g>
                    <!-- 右臂 (拿着扳手/绑扎线) -->
                    <g transform="translate(12, 6)">
                        <g class="arm-r">
                            <line x1="0" y1="0" x2="20" y2="25" stroke="#FF5722" stroke-width="8" stroke-linecap="round"/>
                            <path d="M 20,25 L 30,30 M 20,25 L 25,35" stroke="#E2E8F0" stroke-width="3"/> <!-- 工具 -->
                        </g>
                    </g>

                    <!-- 左腿 -->
                    <g transform="translate(-6, 40)">
                        <line class="leg-l" x1="0" y1="0" x2="-10" y2="35" stroke="#FF5722" stroke-width="9" stroke-linecap="round"/>
                    </g>
                    <!-- 右腿 -->
                    <g transform="translate(6, 40)">
                        <line class="leg-r" x1="0" y1="0" x2="10" y2="35" stroke="#FF5722" stroke-width="9" stroke-linecap="round"/>
                    </g>
                </g>
            </g>
        </svg>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', () => {
            // 定义 12 个操作步骤及动画持续时间 (为了演示,将 120 分钟映射到约 20 秒循环)
            // 重点痛点:步骤 7, 8, 9 分配更长时间
            const STEPS = [
                { name: "现场勘查", type: "ground", duration: 1500 },
                { name: "开票", type: "ground", duration: 1000 },
                { name: "工作许可", type: "ground", duration: 1000 },
                { name: "停电", type: "outage", duration: 1500, alert: "大面积停电区域扩大" },
                { name: "转检修", type: "outage", duration: 1000 },
                { name: "登杆", type: "climb", duration: 3000, alert: "高处作业:坠落风险" },
                { name: "更换绝缘子", type: "work", duration: 2500, alert: "触电风险 / 作业困难" },
                { name: "绑扎线缠绕", type: "work", duration: 4500, alert: "痛点:纯手工缠绕极度耗时" },
                { name: "紧固", type: "work", duration: 2000, alert: "工具不趁手" },
                { name: "转运行", type: "descend", duration: 2000 },
                { name: "恢复供电", type: "power-on", duration: 1500 },
                { name: "工作终结", type: "ground", duration: 1500 }
            ];

            const timelineEl = document.getElementById('timeline');
            const uiTime = document.getElementById('ui-time');
            const uiStatus = document.getElementById('ui-status');
            const svgCanvas = document.getElementById('svg-canvas');
            const wires = document.querySelectorAll('.line-power, .energy-dash');
            const alertBanner = document.getElementById('alert-banner');
            const alertText = document.getElementById('alert-text');

            // 渲染时间轴
            STEPS.forEach((step, index) => {
                const el = document.createElement('div');
                el.className = 'step-item';
                el.id = `step-ui-${index}`;
                el.innerHTML = `
                    <div class="step-dot"></div>
                    <div class="step-name">${index + 1}.${step.name}</div>
                `;
                timelineEl.appendChild(el);
            });
            const stepEls = document.querySelectorAll('.step-item');
            
            const TOTAL_LOOP_TIME = STEPS.reduce((a, b) => a + b.duration, 0) + 1500; // 留白1.5秒
            
            // 动画核心引擎
            let startTimestamp = null;
            let lastStepIdx = -1;
            let currentDisplayTime = 0; // 用于模拟 120 分钟

            function render(timestamp) {
                if (!startTimestamp) startTimestamp = timestamp;
                const elapsed = (timestamp - startTimestamp) % TOTAL_LOOP_TIME;

                // 查找当前步骤
                let accTime = 0;
                let currentIdx = -1;
                for (let i = 0; i < STEPS.length; i++) {
                    if (elapsed >= accTime && elapsed < accTime + STEPS[i].duration) {
                        currentIdx = i;
                        break;
                    }
                    accTime += STEPS[i].duration;
                }

                if (elapsed >= accTime) {
                    currentIdx = STEPS.length - 1; // 保持在最后一步直到循环
                }

                // 计算模拟的时间进度 (仅在停电步骤 3 到 10 期间累加到 120)
                // 使时间在 "绑扎线缠绕" (idx 7) 时飞速增加,表现出耗时长
                let targetTime = 0;
                if (currentIdx >= 3 && currentIdx <= 10) {
                    const outageStart = STEPS.slice(0, 3).reduce((a, b) => a + b.duration, 0);
                    const outageEnd = STEPS.slice(0, 11).reduce((a, b) => a + b.duration, 0);
                    const outageElapsed = Math.max(0, elapsed - outageStart);
                    
                    // 非线性时间映射
                    const rawRatio = outageElapsed / (outageEnd - outageStart);
                    // 添加一个 ease-in-out 曲线或者直接使用简单的分段逻辑
                    let timeRatio = rawRatio;
                    if (currentIdx === 7) { // 绑扎期间时间激增
                        timeRatio = rawRatio * 1.2; 
                    }
                    targetTime = Math.min(120, Math.max(0, timeRatio * 120));
                } else if (currentIdx > 10) {
                    targetTime = 120;
                }

                // 平滑过渡显示时间
                currentDisplayTime += (targetTime - currentDisplayTime) * 0.1;
                uiTime.textContent = Math.round(currentDisplayTime).toString().padStart(3, '0');
                
                // 颜色警告:时间越长越红
                if (currentDisplayTime > 90) {
                    uiTime.style.color = 'var(--color-danger)';
                } else if (currentDisplayTime > 45) {
                    uiTime.style.color = 'var(--color-warning)';
                } else {
                    uiTime.style.color = 'var(--color-safe)';
                }

                // 阶段切换触发视觉更新
                if (currentIdx !== lastStepIdx && currentIdx >= 0) {
                    lastStepIdx = currentIdx;
                    const step = STEPS[currentIdx];
                    
                    // 更新时间轴 UI
                    stepEls.forEach((el, i) => {
                        el.className = 'step-item';
                        if (i < currentIdx) el.classList.add('done');
                        if (i === currentIdx) {
                            el.classList.add('active');
                            if (step.type === 'outage' || step.type === 'work' || step.type === 'climb') {
                                el.classList.add('danger-step');
                            }
                        }
                    });

                    uiStatus.textContent = `${currentIdx + 1}. ${step.name}`;

                    // 清除旧状态
                    svgCanvas.className.baseVal = '';
                    alertBanner.classList.remove('show');
                    
                    // 状态机处理
                    if (step.type === 'outage' || step.type === 'climb' || step.type === 'work' || step.type === 'descend') {
                        wires.forEach(w => w.classList.add('outage'));
                        uiStatus.style.color = 'var(--color-danger)';
                    } else {
                        wires.forEach(w => w.classList.remove('outage'));
                        uiStatus.style.color = 'var(--color-safe)';
                    }

                    // 绑定对应 CSS 动画类名到 SVG 根元素
                    if (step.type === 'climb') {
                        svgCanvas.className.baseVal = 'state-climb';
                    } else if (step.type === 'work') {
                        svgCanvas.className.baseVal = 'state-work';
                    } else if (step.type === 'descend') {
                        svgCanvas.className.baseVal = 'state-descend';
                    }

                    // 警告横幅
                    if (step.alert) {
                        alertText.textContent = `警告: ${step.alert}`;
                        alertBanner.classList.add('show');
                    }
                }

                // 循环结束重置
                if (elapsed > TOTAL_LOOP_TIME - 100) {
                    lastStepIdx = -1;
                    currentDisplayTime = 0;
                }

                requestAnimationFrame(render);
            }

            // 启动动画
            requestAnimationFrame(render);
        });
    </script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>TRIZ 技术系统功能模型与痛点分析</title>
    <style>
        :root {
            /* 深度工业诊断色板 */
            --bg-base: #060913;
            --grid-color: rgba(30, 58, 138, 0.2);
            --hud-border: rgba(56, 189, 248, 0.3);
            --hud-bg: rgba(6, 9, 19, 0.85);
            
            /* 状态语义色 */
            --func-useful: #10B981;    /* 正常有用 - 翠绿 */
            --func-insufficient: #F59E0B; /* 不足功能 - 警告黄 */
            --func-harmful: #EF4444;   /* 有害功能 - 警报红 */
            --node-target: #3B82F6;    /* 作用对象 - 亮蓝 */
            --node-system: #6366F1;    /* 系统组件 - 靛蓝 */
            --node-super: #8B5CF6;     /* 超系统 - 紫色 */
            
            --text-main: #F8FAFC;
            --text-dim: #94A3B8;
            --font-mono: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
            --font-sans: 'PingFang SC', 'Microsoft YaHei', system-ui, sans-serif;
        }

        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            background-color: var(--bg-base);
            background-image: 
                radial-gradient(circle at 50% 50%, rgba(30,58,138,0.1) 0%, transparent 60%),
                linear-gradient(var(--grid-color) 1px, transparent 1px),
                linear-gradient(90deg, var(--grid-color) 1px, transparent 1px);
            background-size: 100% 100%, 40px 40px, 40px 40px;
            font-family: var(--font-sans);
            color: var(--text-main);
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        /* ==================== 边缘 HUD 布局 (严控字号与位置,防止遮挡) ==================== */
        .hud-layer {
            position: absolute;
            inset: 0;
            pointer-events: none;
            z-index: 100;
        }

        .panel {
            position: absolute;
            background: var(--hud-bg);
            border: 1px solid var(--hud-border);
            backdrop-filter: blur(8px);
            padding: 16px;
            border-radius: 4px;
            box-shadow: 0 4px 20px rgba(0,0,0,0.5);
            font-size: 12px;
            line-height: 1.5;
        }

        .panel-title {
            font-size: 13px;
            font-weight: bold;
            color: var(--node-target);
            margin-bottom: 10px;
            border-bottom: 1px solid rgba(56,189,248,0.3);
            padding-bottom: 4px;
            letter-spacing: 1px;
            text-transform: uppercase;
        }

        .top-left { top: 20px; left: 20px; width: 260px; border-left: 3px solid var(--node-target); }
        .top-right { top: 20px; right: 20px; width: 300px; border-right: 3px solid var(--func-harmful); }
        .bottom-left { bottom: 20px; left: 20px; width: 220px; }
        .bottom-right { bottom: 20px; right: 20px; text-align: right; }

        .data-row { display: flex; justify-content: space-between; margin-bottom: 6px; }
        .text-dim { color: var(--text-dim); }
        .text-harmful { color: var(--func-harmful); font-weight: bold; }
        .text-insufficient { color: var(--func-insufficient); font-weight: bold; }
        .text-useful { color: var(--func-useful); }

        /* 图例样式 */
        .legend-item { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; font-family: var(--font-mono); font-size: 11px;}
        .legend-line { width: 20px; height: 2px; }
        .legend-node { width: 10px; height: 10px; border-radius: 50%; }

        /* 核心痛点高亮列表 */
        .core-problem-list { margin: 0; padding-left: 16px; color: var(--func-harmful); }
        .core-problem-list li { margin-bottom: 6px; opacity: 0.4; transition: opacity 0.3s; }
        .core-problem-list li.active { opacity: 1; text-shadow: 0 0 8px rgba(239, 68, 68, 0.6); }

        /* 系统状态打字机 */
        .sys-status { font-family: var(--font-mono); font-size: 14px; color: var(--node-target); }
        .blink-cursor { animation: blink 1s step-end infinite; }
        @keyframes blink { 50% { opacity: 0; } }

        /* ==================== 核心 SVG 动画区 ==================== */
        .svg-container {
            width: 100vw;
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 10;
        }

        svg {
            width: 100%;
            height: 100%;
            max-width: 1200px;
            max-height: 900px;
            overflow: visible;
        }

        /* SVG 节点基础样式 */
        .node-circle { transition: all 0.5s; stroke-width: 2; }
        .node-text { font-family: var(--font-sans); font-size: 14px; fill: var(--text-main); text-anchor: middle; font-weight: bold; pointer-events: none; text-shadow: 0 2px 4px rgba(0,0,0,0.8); }
        .node-sub { font-size: 10px; fill: var(--text-dim); text-anchor: middle; pointer-events: none; }

        /* SVG 连线基础样式 */
        .link-path { fill: none; stroke-width: 2; transition: all 0.5s; opacity: 0.2; }
        .link-label { font-size: 12px; font-family: var(--font-sans); fill: var(--text-dim); text-anchor: middle; opacity: 0; transition: opacity 0.5s; }
        
        /* 动画粒子流 */
        .link-flow { fill: none; stroke-width: 2; stroke-dasharray: 6 12; opacity: 0; pointer-events: none; }

        /* ---------------- 阶段状态:功能模型分析扫描 ---------------- */
        
        /* 正常有用功能 */
        .state-analysis .link-useful { stroke: var(--func-useful); opacity: 0.6; }
        .state-analysis .link-useful + .link-flow { stroke: var(--func-useful); opacity: 1; animation: flowAnim 1s linear infinite; }
        .state-analysis .label-useful { opacity: 1; fill: var(--func-useful); }

        /* 不足功能 (警告黄) */
        .state-analysis .link-insufficient { stroke: var(--func-insufficient); stroke-dasharray: 4 4; opacity: 0.8; }
        .state-analysis .link-insufficient + .link-flow { stroke: var(--func-insufficient); opacity: 1; animation: flowAnim 2s linear infinite reverse; } /* 慢速反馈 */
        .state-analysis .label-insufficient { opacity: 1; fill: var(--func-insufficient); }
        
        /* 有害功能 (危险红) */
        .state-analysis .link-harmful { stroke: var(--func-harmful); opacity: 0.8; }
        .state-analysis .link-harmful + .link-flow { stroke: var(--func-harmful); opacity: 1; animation: flowAnim 0.5s linear infinite; stroke-width: 3;}
        .state-analysis .label-harmful { opacity: 1; fill: var(--func-harmful); font-weight: bold; }

        /* ---------------- 阶段状态:痛点爆发 (红色警报) ---------------- */
        .state-alert .link-harmful { stroke: var(--func-harmful); stroke-width: 4; filter: drop-shadow(0 0 8px var(--func-harmful)); }
        .state-alert .link-insufficient { stroke: var(--func-insufficient); stroke-width: 3; filter: drop-shadow(0 0 6px var(--func-insufficient)); }
        
        .state-alert .node-worker, .state-alert .node-wire { 
            animation: nodePulseRed 1.5s infinite alternate; 
        }

        /* 脉冲与流动动画 */
        @keyframes flowAnim { to { stroke-dashoffset: -36; } }
        @keyframes nodePulseRed {
            0% { filter: drop-shadow(0 0 5px var(--func-harmful)); stroke: var(--func-harmful); }
            100% { filter: drop-shadow(0 0 20px var(--func-harmful)); stroke: var(--func-harmful); }
        }
        @keyframes nodePulseAmber {
            0% { filter: drop-shadow(0 0 5px var(--func-insufficient)); stroke: var(--func-insufficient); }
            100% { filter: drop-shadow(0 0 20px var(--func-insufficient)); stroke: var(--func-insufficient); }
        }
        
        /* 错误波纹涟漪 */
        .error-ripple { fill: none; stroke: var(--func-harmful); stroke-width: 2; opacity: 0; transform-origin: center; pointer-events: none;}
        .state-alert .error-ripple.active { animation: rippleEffect 2s infinite ease-out; }
        @keyframes rippleEffect {
            0% { transform: scale(1); opacity: 0.8; }
            100% { transform: scale(3.5); opacity: 0; }
        }

    </style>
</head>
<body>

    <!-- HUD 边缘信息层 -->
    <div class="hud-layer">
        
        <!-- 左上:技术系统定义 -->
        <div class="panel top-left">
            <div class="panel-title">技术系统定义</div>
            <div class="data-row"><span class="text-dim">系统名称</span></div>
            <div style="font-weight: bold; margin-bottom: 10px; color: var(--text-main);">传统停电检修绑扎作业系统</div>
            
            <div class="data-row"><span class="text-dim">总功能</span></div>
            <div style="margin-bottom: 10px; color: var(--node-target);">固定导线 (防松脱)</div>
            
            <div class="data-row"><span class="text-dim">唯一作用对象</span></div>
            <div style="font-family: var(--font-mono); color: var(--node-target); font-size: 14px; font-weight:bold;">导线 [TARGET]</div>
        </div>

        <!-- 左下:图例 -->
        <div class="panel bottom-left">
            <div class="panel-title">功能模型图例</div>
            <div class="legend-item"><div class="legend-node" style="background: var(--node-target);"></div> 作用对象</div>
            <div class="legend-item"><div class="legend-node" style="background: var(--node-system);"></div> 系统组件</div>
            <div class="legend-item"><div class="legend-node" style="background: var(--node-super);"></div> 超系统组件</div>
            <div style="height: 1px; background: rgba(255,255,255,0.1); margin: 6px 0;"></div>
            <div class="legend-item"><div class="legend-line" style="background: var(--func-useful);"></div> 正常有用功能</div>
            <div class="legend-item"><div class="legend-line" style="border-top: 2px dashed var(--func-insufficient);"></div> 不足功能</div>
            <div class="legend-item"><div class="legend-line" style="background: var(--func-harmful);"></div> 有害功能</div>
        </div>

        <!-- 右上:核心痛点监控 (TRIZ 矛盾提取) -->
        <div class="panel top-right">
            <div class="panel-title" style="border-color: var(--func-harmful); color: var(--func-harmful);">核心问题与矛盾总结</div>
            <ul class="core-problem-list" id="problem-list">
                <li id="prob-1">【不足】绑扎线固定导线可靠性差</li>
                <li id="prob-2">【有害】作业人员登高存在高坠风险</li>
                <li id="prob-3">【有害】接近高压导线存在触电风险</li>
                <li id="prob-4">【有害】断路器切断电源导致负荷停电</li>
            </ul>
        </div>

        <!-- 右下:动态分析状态 -->
        <div class="panel bottom-right" style="background: transparent; border: none; box-shadow: none;">
            <div class="text-dim" style="font-size: 10px; margin-bottom: 4px;">ANALYSIS STATUS</div>
            <div class="sys-status" id="sys-status">INITIALIZING SYSTEM<span class="blink-cursor">_</span></div>
        </div>
    </div>

    <!-- 核心功能模型动画区 -->
    <div class="svg-container">
        <svg viewBox="0 0 1000 700" preserveAspectRatio="xMidYMid meet" id="triz-svg">
            <defs>
                <!-- 滤镜定义 -->
                <filter id="glow-useful"><feGaussianBlur stdDeviation="3" result="blur" /><feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
                <filter id="glow-harmful"><feGaussianBlur stdDeviation="5" result="blur" /><feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
                <filter id="glow-insufficient"><feGaussianBlur stdDeviation="4" result="blur" /><feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
                
                <!-- 箭头标记定义 -->
                <marker id="arrow-useful" viewBox="0 0 10 10" refX="28" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
                    <path d="M 0 0 L 10 5 L 0 10 z" fill="var(--func-useful)" />
                </marker>
                <marker id="arrow-harmful" viewBox="0 0 10 10" refX="28" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
                    <path d="M 0 0 L 10 5 L 0 10 z" fill="var(--func-harmful)" />
                </marker>
                <marker id="arrow-insufficient" viewBox="0 0 10 10" refX="28" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
                    <path d="M 0 0 L 10 5 L 0 10 z" fill="var(--func-insufficient)" />
                </marker>
            </defs>

            <!-- ================== 连线层 (功能作用流) ================== -->
            <g id="links">
                <!-- 1. 作业人员 -> 登高 -> 杆塔 (有害) -->
                <path d="M 250 400 Q 300 550 450 550" class="link-path link-harmful" marker-end="url(#arrow-harmful)"/>
                <path d="M 250 400 Q 300 550 450 550" class="link-flow"/>
                <text x="320" y="520" class="link-label label-harmful">产生高坠风险</text>

                <!-- 2. 作业人员 -> 接近 -> 高压导线 (有害) -->
                <path d="M 250 400 Q 350 350 460 350" class="link-path link-harmful" marker-end="url(#arrow-harmful)"/>
                <path d="M 250 400 Q 350 350 460 350" class="link-flow"/>
                <text x="350" y="365" class="link-label label-harmful">产生触电风险</text>

                <!-- 3. 作业人员 -> 缠绕 -> 绑扎线 (有用) -->
                <path d="M 250 400 Q 500 450 710 400" class="link-path link-useful" marker-end="url(#arrow-useful)"/>
                <path d="M 250 400 Q 500 450 710 400" class="link-flow"/>
                <text x="500" y="440" class="link-label label-useful">缠绕操作</text>

                <!-- 4. 绑扎线 -> 固定 -> 导线 (不足) -->
                <path d="M 750 400 Q 650 350 540 350" class="link-path link-insufficient" marker-end="url(#arrow-insufficient)"/>
                <path d="M 750 400 Q 650 350 540 350" class="link-flow"/>
                <text x="650" y="375" class="link-label label-insufficient">易松动脱落</text>

                <!-- 5. 绝缘操作杆 -> 传递力 -> 绑扎线 (不足) -->
                <path d="M 750 550 Q 750 475 750 440" class="link-path link-insufficient" marker-end="url(#arrow-insufficient)"/>
                <path d="M 750 550 Q 750 475 750 440" class="link-flow"/>
                <text x="800" y="500" class="link-label label-insufficient">反馈差/精度低</text>

                <!-- 6. 安全工器具 -> 防护 -> 作业人员 (不足) -->
                <path d="M 250 250 Q 250 325 250 360" class="link-path link-insufficient" marker-end="url(#arrow-insufficient)"/>
                <path d="M 250 250 Q 250 325 250 360" class="link-flow"/>
                <text x="180" y="310" class="link-label label-insufficient">防护繁琐</text>

                <!-- 7. 接地线 -> 释放 -> 导线感应电 (有用) -->
                <path d="M 500 200 Q 500 275 500 310" class="link-path link-useful" marker-end="url(#arrow-useful)"/>
                <path d="M 500 200 Q 500 275 500 310" class="link-flow"/>
                <text x="540" y="260" class="link-label label-useful">释放感应电</text>

                <!-- 8. 断路器 -> 切断 -> 电源 (有害/损失) -->
                <path d="M 850 200 Q 750 200 640 200" class="link-path link-harmful" marker-end="url(#arrow-harmful)"/>
                <path d="M 850 200 Q 750 200 640 200" class="link-flow"/>
                <text x="750" y="190" class="link-label label-harmful">导致停电损失</text>
                
                <!-- 关联:电源 -> 负荷 -->
                <path d="M 560 200 L 440 200" class="link-path link-useful" marker-end="url(#arrow-useful)"/>
                <text x="500" y="190" class="link-label label-useful">供电</text>
            </g>

            <!-- ================== 节点层 ================== -->
            <g id="nodes">
                <!-- 核心:导线 (唯一作用对象) -->
                <g transform="translate(500, 350)">
                    <!-- 错误波纹爆发位置 -->
                    <circle class="error-ripple" cx="0" cy="0" r="30" id="ripple-wire"/>
                    <circle cx="0" cy="0" r="35" fill="rgba(59, 130, 246, 0.2)" stroke="var(--node-target)" class="node-circle node-wire"/>
                    <circle cx="0" cy="0" r="25" fill="var(--node-target)" />
                    <text y="5" class="node-text" style="fill:#fff;">导线</text>
                    <text y="55" class="node-sub">作用对象</text>
                </g>

                <!-- 系统组件 -->
                <!-- 作业人员 -->
                <g transform="translate(250, 400)">
                    <circle class="error-ripple" cx="0" cy="0" r="30" id="ripple-worker"/>
                    <circle cx="0" cy="0" r="35" fill="rgba(99, 102, 241, 0.2)" stroke="var(--node-system)" class="node-circle node-worker"/>
                    <text y="5" class="node-text">作业人员</text>
                    <text y="55" class="node-sub">系统组件</text>
                </g>

                <!-- 绑扎线 -->
                <g transform="translate(750, 400)">
                    <circle class="error-ripple" cx="0" cy="0" r="30" id="ripple-binding"/>
                    <circle cx="0" cy="0" r="35" fill="rgba(99, 102, 241, 0.2)" stroke="var(--node-system)" class="node-circle"/>
                    <text y="5" class="node-text">绑扎线</text>
                    <text y="55" class="node-sub">系统组件</text>
                </g>

                <!-- 绝缘操作杆 -->
                <g transform="translate(750, 550)">
                    <circle cx="0" cy="0" r="30" fill="rgba(99, 102, 241, 0.1)" stroke="var(--node-system)" class="node-circle"/>
                    <text y="5" class="node-text">绝缘操作杆</text>
                </g>

                <!-- 安全工器具 -->
                <g transform="translate(250, 250)">
                    <circle cx="0" cy="0" r="30" fill="rgba(99, 102, 241, 0.1)" stroke="var(--node-system)" class="node-circle"/>
                    <text y="5" class="node-text">安全工器具</text>
                </g>

                <!-- 接地线 -->
                <g transform="translate(500, 200)">
                    <circle cx="0" cy="0" r="30" fill="rgba(99, 102, 241, 0.1)" stroke="var(--node-system)" class="node-circle"/>
                    <text y="5" class="node-text">接地线</text>
                </g>

                <!-- 超系统组件 -->
                <!-- 杆塔/绝缘子 -->
                <g transform="translate(500, 550)">
                    <circle cx="0" cy="0" r="35" fill="rgba(139, 92, 246, 0.2)" stroke="var(--node-super)" class="node-circle"/>
                    <text y="-5" class="node-text">杆塔 /</text>
                    <text y="15" class="node-text">绝缘子</text>
                    <text y="55" class="node-sub">超系统</text>
                </g>

                <!-- 高压电源 -->
                <g transform="translate(600, 200)">
                    <circle cx="0" cy="0" r="35" fill="rgba(139, 92, 246, 0.2)" stroke="var(--node-super)" class="node-circle"/>
                    <text y="5" class="node-text">高压电源</text>
                    <text y="-45" class="node-sub">超系统</text>
                </g>

                <!-- 断路器 -->
                <g transform="translate(850, 200)">
                    <circle class="error-ripple" cx="0" cy="0" r="30" id="ripple-breaker"/>
                    <circle cx="0" cy="0" r="35" fill="rgba(139, 92, 246, 0.2)" stroke="var(--node-super)" class="node-circle"/>
                    <text y="5" class="node-text">断路器</text>
                    <text y="-45" class="node-sub">超系统</text>
                </g>

                <!-- 供电负荷 -->
                <g transform="translate(400, 200)">
                    <circle cx="0" cy="0" r="35" fill="rgba(139, 92, 246, 0.2)" stroke="var(--node-super)" class="node-circle"/>
                    <text y="5" class="node-text">供电负荷</text>
                    <text y="-45" class="node-sub">超系统</text>
                </g>

            </g>
        </svg>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const svgContainer = document.getElementById('triz-svg');
            const statusText = document.getElementById('sys-status');
            const probItems = [
                document.getElementById('prob-1'),
                document.getElementById('prob-2'),
                document.getElementById('prob-3'),
                document.getElementById('prob-4')
            ];
            const ripples = [
                document.getElementById('ripple-binding'), // 绑扎线不足
                document.getElementById('ripple-worker'),  // 高坠
                document.getElementById('ripple-wire'),    // 触电
                document.getElementById('ripple-breaker')  // 断路器停电
            ];

            // 动画状态机配置 (毫秒)
            const STATES = [
                { class: '', msg: 'SYSTEM STANDBY...', duration: 2000 },
                { class: 'state-analysis', msg: 'MAPPING FUNCTIONAL INTERACTIONS...', duration: 5000 },
                { class: 'state-analysis state-alert', msg: 'DETECTING HARMFUL CONTRADICTIONS!', duration: 6000 }
            ];

            let currentState = 0;
            let lastTime = 0;

            function animate(timestamp) {
                if (!lastTime) lastTime = timestamp;
                const elapsed = timestamp - lastTime;
                
                const stateDef = STATES[currentState];

                if (elapsed > stateDef.duration) {
                    // 切换到下一个状态
                    currentState = (currentState + 1) % STATES.length;
                    lastTime = timestamp;
                    
                    const nextStateDef = STATES[currentState];
                    svgContainer.setAttribute('class', nextStateDef.class);
                    statusText.innerHTML = `${nextStateDef.msg}<span class="blink-cursor">_</span>`;
                    
                    // 根据状态控制告警涟漪和右侧痛点列表的高亮
                    if (nextStateDef.class.includes('state-alert')) {
                        statusText.style.color = "var(--func-harmful)";
                        
                        // 错开高亮显示四大核心痛点
                        probItems.forEach((item, i) => {
                            setTimeout(() => {
                                item.classList.add('active');
                                if(ripples[i]) ripples[i].classList.add('active');
                            }, i * 800);
                        });
                    } else {
                        statusText.style.color = "var(--node-target)";
                        probItems.forEach(item => item.classList.remove('active'));
                        ripples.forEach(r => r.classList.remove('active'));
                    }
                }

                requestAnimationFrame(animate);
            }

            // 初始化触发
            svgContainer.setAttribute('class', STATES[0].class);
            requestAnimationFrame(animate);
        });
    </script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>传统停电绑扎作业系统 - TRIZ 核心矛盾与痛点动画</title>
    <style>
        :root {
            /* 工业科技风配色 */
            --bg-dark: #030712;
            --grid-line: rgba(30, 58, 138, 0.3);
            
            /* TRIZ 功能状态色 */
            --color-useful: #10B981;    /* 正常有用:翠绿 */
            --color-insufficient: #F59E0B; /* 不足功能:明黄 */
            --color-harmful: #EF4444;   /* 有害功能:亮红 */
            --color-target: #06B6D4;    /* 作用对象:青色 */
            --color-system: #6366F1;    /* 系统组件:靛蓝 */
            
            --text-main: #F8FAFC;
            --text-dim: #94A3B8;
            --font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
            --font-mono: 'SFMono-Regular', Consolas, monospace;
        }

        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            background-color: var(--bg-dark);
            background-image: 
                radial-gradient(circle at center, rgba(30,58,138,0.15) 0%, transparent 70%),
                linear-gradient(var(--grid-line) 1px, transparent 1px),
                linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
            background-size: 100% 100%, 50px 50px, 50px 50px;
            font-family: var(--font-family);
            color: var(--text-main);
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        /* ==================== 边缘信息面板 (HUD) ==================== */
        .hud-container {
            position: absolute;
            inset: 0;
            pointer-events: none;
            z-index: 100;
        }

        .panel {
            position: absolute;
            background: rgba(3, 7, 18, 0.85);
            border: 1px solid rgba(148, 163, 184, 0.2);
            backdrop-filter: blur(10px);
            border-radius: 8px;
            padding: 20px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.8);
            pointer-events: auto;
        }

        .panel-title {
            font-size: 16px;
            font-weight: bold;
            color: var(--color-target);
            margin-bottom: 12px;
            border-bottom: 2px solid rgba(6, 182, 212, 0.3);
            padding-bottom: 8px;
            letter-spacing: 1px;
            display: flex;
            justify-content: space-between;
        }

        .panel-left {
            top: 24px;
            left: 24px;
            width: 340px;
            border-left: 4px solid var(--color-target);
        }

        .panel-right {
            top: 24px;
            right: 24px;
            width: 320px;
            border-right: 4px solid var(--color-harmful);
        }

        .panel-bottom {
            bottom: 24px;
            left: 50%;
            transform: translateX(-50%);
            display: flex;
            gap: 24px;
            border-top: 2px solid var(--color-system);
            padding: 12px 32px;
        }

        /* 列表样式 */
        .triz-list {
            list-style: none;
            padding: 0;
            margin: 0;
            display: flex;
            flex-direction: column;
            gap: 10px;
        }

        .triz-item {
            font-size: 13px;
            line-height: 1.5;
            padding: 8px 12px;
            background: rgba(255,255,255,0.03);
            border-radius: 6px;
            border-left: 3px solid transparent;
            transition: all 0.3s ease;
            opacity: 0.4;
        }

        .triz-item.active {
            opacity: 1;
            background: rgba(255,255,255,0.1);
            transform: translateX(5px);
        }

        .triz-item.useful.active { border-left-color: var(--color-useful); box-shadow: 0 0 15px rgba(16,185,129,0.2); }
        .triz-item.insufficient.active { border-left-color: var(--color-insufficient); box-shadow: 0 0 15px rgba(245,158,11,0.2); }
        .triz-item.harmful.active { border-left-color: var(--color-harmful); box-shadow: 0 0 15px rgba(239,68,68,0.3); }

        .tag-useful { color: var(--color-useful); font-weight: bold; font-family: var(--font-mono); font-size: 12px;}
        .tag-insufficient { color: var(--color-insufficient); font-weight: bold; font-family: var(--font-mono); font-size: 12px;}
        .tag-harmful { color: var(--color-harmful); font-weight: bold; font-family: var(--font-mono); font-size: 12px;}

        /* 图例指示器 */
        .legend-box { display: flex; align-items: center; gap: 8px; font-size: 12px; font-weight: bold;}
        .indicator { width: 12px; height: 12px; border-radius: 50%; }
        
        /* 动态打字机状态条 */
        .status-bar {
            position: absolute;
            top: -40px;
            left: 50%;
            transform: translateX(-50%);
            font-family: var(--font-mono);
            font-size: 18px;
            font-weight: bold;
            color: var(--color-harmful);
            background: rgba(239,68,68,0.15);
            padding: 8px 24px;
            border-radius: 20px;
            border: 1px solid var(--color-harmful);
            text-shadow: 0 0 10px rgba(239,68,68,0.5);
            white-space: nowrap;
        }

        /* ==================== SVG 核心动画区 ==================== */
        .svg-container {
            width: 100vw;
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 10;
        }

        svg {
            width: 100%;
            height: 100%;
            max-width: 1400px;
            max-height: 900px;
            overflow: visible;
        }

        /* 基础组件样式 */
        .pole { fill: #1E293B; stroke: #334155; stroke-width: 2; }
        .crossarm { fill: #334155; stroke: #0F172A; stroke-width: 2; }
        .insulator { fill: #94A3B8; stroke: #475569; }
        .wire { fill: none; stroke: var(--color-target); stroke-width: 6; filter: drop-shadow(0 0 6px var(--color-target)); }
        
        /* 抽象节点样式 */
        .node-rect { fill: rgba(15, 23, 42, 0.8); stroke: var(--text-dim); stroke-width: 2; rx: 6; transition: all 0.3s; }
        .node-text { fill: var(--text-main); font-size: 16px; font-weight: bold; text-anchor: middle; font-family: var(--font-family); }
        .node-subtext { fill: var(--text-dim); font-size: 12px; text-anchor: middle; font-family: var(--font-mono); }

        /* 人员动作 (纯CSS) */
        .worker-body { fill: #F59E0B; }
        .worker-head { fill: #FDE047; }
        .worker-limb { stroke: #F59E0B; stroke-width: 6; stroke-linecap: round; }
        
        #worker-group { transform-origin: 600px 400px; }
        .is-working #worker-group { animation: struggle 1s infinite alternate ease-in-out; }
        .is-working .worker-arm-r { animation: bindAction 0.4s infinite alternate; transform-origin: top left; }
        .is-working .worker-arm-l { animation: bindAction 0.5s infinite alternate reverse; transform-origin: top right; }
        
        @keyframes struggle { 0% { transform: rotate(-2deg); } 100% { transform: rotate(2deg); } }
        @keyframes bindAction { 0% { transform: rotate(-20deg); } 100% { transform: rotate(40deg); } }

        /* ==================== TRIZ 相互作用连线 (动态流向) ==================== */
        .triz-link { fill: none; stroke-width: 3; transition: all 0.4s; opacity: 0.2; }
        .triz-flow { fill: none; stroke-width: 3; stroke-dasharray: 8 16; opacity: 0; transition: all 0.4s; pointer-events: none;}
        
        /* 各种功能流向的激活状态 */
        /* 1. 正常有用 (翠绿) */
        .link-useful.active { stroke: var(--color-useful); opacity: 0.6; }
        .flow-useful.active { stroke: var(--color-useful); opacity: 1; animation: flowAnim 1s linear infinite; filter: drop-shadow(0 0 8px var(--color-useful));}
        
        /* 2. 不足功能 (明黄虚线) */
        .link-insufficient.active { stroke: var(--color-insufficient); opacity: 0.8; stroke-dasharray: 6 6; }
        .flow-insufficient.active { stroke: var(--color-insufficient); opacity: 1; animation: flowAnim 2s linear infinite reverse; filter: drop-shadow(0 0 8px var(--color-insufficient)); }
        
        /* 3. 有害功能 (亮红粗线) */
        .link-harmful.active { stroke: var(--color-harmful); opacity: 0.8; stroke-width: 5; }
        .flow-harmful.active { stroke: var(--color-harmful); opacity: 1; animation: flowAnim 0.6s linear infinite; stroke-width: 5; filter: drop-shadow(0 0 10px var(--color-harmful)); }

        @keyframes flowAnim { to { stroke-dashoffset: -48; } }

        /* 标签文字 */
        .link-label { font-size: 14px; font-weight: bold; font-family: var(--font-family); text-anchor: middle; opacity: 0; transition: opacity 0.3s; }
        .link-label.active { opacity: 1; }
        .label-useful { fill: var(--color-useful); }
        .label-insufficient { fill: var(--color-insufficient); }
        .label-harmful { fill: var(--color-harmful); }

        /* 危险特效 (红圈闪烁与触电) */
        .hazard-ring { opacity: 0; fill: none; stroke-width: 4; stroke: var(--color-harmful); transform-origin: center; pointer-events: none;}
        .hazard-ring.active { animation: ringPulse 1.5s infinite cubic-bezier(0.1, 0.8, 0.3, 1); }
        @keyframes ringPulse { 0% { transform: scale(0.5); opacity: 1; } 100% { transform: scale(3.5); opacity: 0; } }

        .arc-flash { opacity: 0; fill: none; stroke: #FFF; stroke-width: 3; filter: drop-shadow(0 0 8px var(--color-target)); pointer-events: none; }
        .arc-flash.active { animation: arcFlash 0.5s infinite; }
        @keyframes arcFlash { 0%, 100% { opacity: 0; } 50% { opacity: 1; } 75% { opacity: 0.5; } }

        /* 停电变暗特效 */
        #scene-dimmer { opacity: 0; transition: opacity 0.5s; pointer-events: none; fill: rgba(0,0,0,0.6); }
        #scene-dimmer.active { opacity: 1; }

    </style>
</head>
<body>

    <!-- HUD 面板层 -->
    <div class="hud-container">
        
        <!-- 左侧:系统内部组件与作用定义 -->
        <div class="panel panel-left">
            <div class="panel-title">
                <span>组件相互作用分析</span>
                <span style="font-family: var(--font-mono); font-size: 12px; color: var(--text-dim);">[SYSTEM_COMPONENTS]</span>
            </div>
            <ul class="triz-list" id="interaction-list">
                <li class="triz-item harmful" data-step="1">
                    <span class="tag-harmful">[有害]</span> 作业人员 → 登高 → 杆塔<br>
                    <span style="color:var(--text-dim); font-size:11px;">导致极高的高处坠落危险</span>
                </li>
                <li class="triz-item harmful" data-step="2">
                    <span class="tag-harmful">[有害]</span> 作业人员 → 接近 → 高压导线<br>
                    <span style="color:var(--text-dim); font-size:11px;">极易触发感应电或直接触电</span>
                </li>
                <li class="triz-item useful" data-step="3">
                    <span class="tag-useful">[有用]</span> 作业人员 → 缠绕 → 绑扎线<br>
                    <span style="color:var(--text-dim); font-size:11px;">实现导线的物理挂载</span>
                </li>
                <li class="triz-item insufficient" data-step="4">
                    <span class="tag-insufficient">[不足]</span> 绑扎线 → 固定 → 导线<br>
                    <span style="color:var(--text-dim); font-size:11px;">传统铁丝/铝线极易松动、脱落</span>
                </li>
                <li class="triz-item harmful" data-step="5">
                    <span class="tag-harmful">[有害]</span> 断路器 → 切断 → 电源<br>
                    <span style="color:var(--text-dim); font-size:11px;">为保障安全导致下游全线停电</span>
                </li>
            </ul>
        </div>

        <!-- 右侧:核心矛盾总结 -->
        <div class="panel panel-right">
            <div class="panel-title" style="border-color: rgba(239,68,68,0.5); color: var(--color-harmful);">
                <span>核心矛盾与痛点总结</span>
                <span style="font-family: var(--font-mono); font-size: 12px; color: var(--text-dim);">[CONTRADICTIONS]</span>
            </div>
            <ul class="triz-list">
                <li class="triz-item active" style="border-color: var(--color-insufficient); opacity: 0.9;">
                    <strong>1. 可靠性与耗时的矛盾</strong><br>
                    <span style="color:var(--text-dim); font-size:12px;">要求绑扎紧固防松脱,却导致纯手工缠绕极度耗时、工具不趁手。</span>
                </li>
                <li class="triz-item active" style="border-color: var(--color-harmful); opacity: 0.9; margin-top: 10px;">
                    <strong>2. 作业与安全的矛盾</strong><br>
                    <span style="color:var(--text-dim); font-size:12px;">依赖人工登高接近导线,衍生出高坠与触电两大核心威胁。</span>
                </li>
                <li class="triz-item active" style="border-color: var(--color-harmful); opacity: 0.9; margin-top: 10px;">
                    <strong>3. 检修与供电的矛盾</strong><br>
                    <span style="color:var(--text-dim); font-size:12px;">为切断风险切断断路器,直接造成巨大的下游停电经济损失。</span>
                </li>
            </ul>
        </div>

        <!-- 底部图例 -->
        <div class="panel-bottom">
            <div class="legend-box"><div class="indicator" style="background: var(--color-target); box-shadow: 0 0 10px var(--color-target);"></div> 作用对象 (导线)</div>
            <div class="legend-box"><div class="indicator" style="background: var(--color-useful);"></div> 正常有用功能</div>
            <div class="legend-box"><div class="indicator" style="border: 2px dashed var(--color-insufficient);"></div> 不足功能 (可靠性差)</div>
            <div class="legend-box"><div class="indicator" style="background: var(--color-harmful); box-shadow: 0 0 10px var(--color-harmful);"></div> 有害功能 (风险/损失)</div>
        </div>

        <!-- 动态状态条 -->
        <div class="status-bar" id="status-bar">系统初始化监控...</div>
    </div>

    <!-- 核心动画 SVG -->
    <div class="svg-container">
        <svg viewBox="0 0 1400 900" preserveAspectRatio="xMidYMid meet">
            <defs>
                <!-- 发光滤镜 -->
                <filter id="glow-target"><feGaussianBlur stdDeviation="4" result="blur"/><feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
                <!-- 箭头 Marker -->
                <marker id="arrow-useful" 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-useful)" />
                </marker>
                <marker id="arrow-insufficient" 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-insufficient)" />
                </marker>
                <marker id="arrow-harmful" 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-harmful)" />
                </marker>
            </defs>

            <!-- ================= 具象物理场景层 ================= -->
            <g id="physical-scene">
                <!-- 地面 -->
                <line x1="200" y1="800" x2="1200" y2="800" stroke="#1E293B" stroke-width="4"/>
                
                <!-- 杆塔主体 -->
                <polygon class="pole" points="585,800 615,800 608,150 592,150" />
                <line x1="600" y1="150" x2="600" y2="800" stroke="#0F172A" stroke-width="2" stroke-dasharray="10 5"/>
                
                <!-- 横担与支撑 -->
                <rect class="crossarm" x="400" y="250" width="400" height="24" rx="4" />
                <line x1="440" y1="274" x2="600" y2="350" stroke="#334155" stroke-width="12" stroke-linecap="round"/>
                <line x1="760" y1="274" x2="600" y2="350" stroke="#334155" stroke-width="12" stroke-linecap="round"/>

                <!-- 绝缘子 -->
                <path class="insulator" d="M 430,200 L 470,200 L 460,250 L 440,250 Z" />
                <path class="insulator" d="M 580,200 L 620,200 L 610,250 L 590,250 Z" />
                <path class="insulator" d="M 730,200 L 770,200 L 760,250 L 740,250 Z" />

                <!-- 高压导线 (唯一作用对象) -->
                <path id="target-wire" class="wire" d="M 100,180 Q 300,280 450,200 T 750,200 T 1300,180" />
                <!-- 绑扎线 (固定点细节) -->
                <path d="M 590,195 Q 600,210 610,195 M 590,205 Q 600,220 610,205" fill="none" stroke="#94A3B8" stroke-width="3"/>
            </g>

            <!-- 停电遮罩 -->
            <rect id="scene-dimmer" x="0" y="0" width="1400" height="900" />

            <!-- ================= 作业人员具象模型 ================= -->
            <g id="worker-group" class="is-working" transform="translate(0,-60)">
                <!-- 脚踩位置 -->
                <path d="M 590,460 L 610,460" stroke="#475569" stroke-width="4"/>
                
                <!-- 身体 -->
                <rect class="worker-body" x="585" y="340" width="30" height="50" rx="8"/>
                <rect x="583" y="370" width="34" height="8" fill="#1E293B"/> <!-- 安全带 -->
                <!-- 头部 -->
                <circle cx="600" cy="325" r="14" class="worker-head"/>
                <path d="M 582,320 Q 600,295 618,320 Z" fill="#EAB308"/>

                <!-- 左臂 -->
                <g transform="translate(585, 350)">
                    <line class="worker-limb worker-arm-l" x1="0" y1="0" x2="-25" y2="35"/>
                </g>
                <!-- 右臂向上操作绑扎线 -->
                <g transform="translate(615, 350)">
                    <line class="worker-limb worker-arm-r" x1="0" y1="0" x2="10" y2="-40"/>
                </g>
                
                <!-- 双腿 -->
                <line class="worker-limb" x1="595" y1="390" x2="595" y2="455"/>
                <line class="worker-limb" x1="605" y1="390" x2="605" y2="455"/>
            </g>

            <!-- ================= 抽象超系统节点 ================= -->
            <g id="abstract-nodes">
                <!-- 断路器 -->
                <g transform="translate(250, 650)">
                    <rect class="node-rect" x="-70" y="-30" width="140" height="60" />
                    <text class="node-text" y="-5">断路器</text>
                    <text class="node-subtext" y="15">超系统</text>
                </g>
                
                <!-- 高压电源 -->
                <g transform="translate(250, 450)">
                    <rect class="node-rect" x="-70" y="-30" width="140" height="60" />
                    <text class="node-text" y="-5">高压电源</text>
                    <text class="node-subtext" y="15">超系统</text>
                </g>

                <!-- 供电负荷 -->
                <g transform="translate(1150, 650)">
                    <rect class="node-rect" x="-70" y="-30" width="140" height="60" />
                    <text class="node-text" y="-5">下游负荷</text>
                    <text class="node-subtext" y="15">超系统 / 用户</text>
                </g>
            </g>

            <!-- ================= TRIZ 相互作用流 (连线与动画) ================= -->
            <g id="triz-interactions">
                
                <!-- 1. 作业人员 -> 杆塔 (有害:高坠) -->
                <g id="link-group-1">
                    <path d="M 640 400 Q 750 450 630 650" class="triz-link link-harmful" marker-end="url(#arrow-harmful)"/>
                    <path d="M 640 400 Q 750 450 630 650" class="triz-flow flow-harmful" />
                    <circle cx="620" cy="650" r="40" class="hazard-ring" id="ring-fall"/>
                    <text x="730" y="550" class="link-label label-harmful">产生高空坠落危险</text>
                </g>

                <!-- 2. 作业人员 -> 导线 (有害:触电) -->
                <g id="link-group-2">
                    <path d="M 570 320 Q 500 250 500 200" class="triz-link link-harmful" marker-end="url(#arrow-harmful)"/>
                    <path d="M 570 320 Q 500 250 500 200" class="triz-flow flow-harmful" />
                    <path d="M 500 200 L 480 250 L 520 270 L 500 320" class="arc-flash" id="arc-shock"/>
                    <text x="460" y="270" class="link-label label-harmful">产生触电风险</text>
                </g>

                <!-- 3. 作业人员 -> 绑扎线 (有用:缠绕) -->
                <g id="link-group-3">
                    <path d="M 630 310 Q 650 250 620 200" class="triz-link link-useful" marker-end="url(#arrow-useful)"/>
                    <path d="M 630 310 Q 650 250 620 200" class="triz-flow flow-useful" />
                    <text x="680" y="260" class="link-label label-useful">纯手工缠绕操作</text>
                </g>

                <!-- 4. 绑扎线 -> 导线 (不足:松动) -->
                <g id="link-group-4">
                    <path d="M 610 180 Q 650 150 680 185" class="triz-link link-insufficient" marker-end="url(#arrow-insufficient)"/>
                    <path d="M 610 180 Q 650 150 680 185" class="triz-flow flow-insufficient" />
                    <text x="650" y="140" class="link-label label-insufficient">固定极易松动、脱落</text>
                </g>

                <!-- 5. 断路器 -> 电源 -> 负荷 (有害:全线停电) -->
                <g id="link-group-5">
                    <path d="M 250 620 L 250 480" class="triz-link link-harmful" marker-end="url(#arrow-harmful)"/>
                    <path d="M 250 620 L 250 480" class="triz-flow flow-harmful" />
                    
                    <path d="M 320 450 Q 700 350 1150 620" class="triz-link link-harmful" marker-end="url(#arrow-harmful)"/>
                    <path d="M 320 450 Q 700 350 1150 620" class="triz-flow flow-harmful" />
                    
                    <circle cx="1150" cy="650" r="50" class="hazard-ring" id="ring-outage"/>
                    <text x="700" y="450" class="link-label label-harmful" style="font-size:18px;">切断电源:导致严重停电经济损失</text>
                </g>

            </g>
        </svg>
    </div>

    <!-- 控制脚本 -->
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const listItems = document.querySelectorAll('.triz-item[data-step]');
            const statusBar = document.getElementById('status-bar');
            const sceneDimmer = document.getElementById('scene-dimmer');
            
            // 各个动画组的引用
            const linkGroups = {
                1: { link: '#link-group-1 .triz-link', flow: '#link-group-1 .triz-flow', label: '#link-group-1 .link-label', extra: '#ring-fall' },
                2: { link: '#link-group-2 .triz-link', flow: '#link-group-2 .triz-flow', label: '#link-group-2 .link-label', extra: '#arc-shock' },
                3: { link: '#link-group-3 .triz-link', flow: '#link-group-3 .triz-flow', label: '#link-group-3 .link-label' },
                4: { link: '#link-group-4 .triz-link', flow: '#link-group-4 .triz-flow', label: '#link-group-4 .link-label' },
                5: { link: '#link-group-5 .triz-link', flow: '#link-group-5 .triz-flow', label: '#link-group-5 .link-label', extra: '#ring-outage' }
            };

            const STEP_DURATION = 3500; // 每步展示 3.5 秒
            let currentStep = 1;
            const totalSteps = 5;

            function clearAll() {
                listItems.forEach(item => item.classList.remove('active'));
                
                Object.values(linkGroups).forEach(group => {
                    document.querySelectorAll(group.link).forEach(el => el.classList.remove('active'));
                    document.querySelectorAll(group.flow).forEach(el => el.classList.remove('active'));
                    document.querySelectorAll(group.label).forEach(el => el.classList.remove('active'));
                    if (group.extra) {
                        document.querySelectorAll(group.extra).forEach(el => el.classList.remove('active'));
                    }
                });
                
                sceneDimmer.classList.remove('active');
            }

            function activateStep(step) {
                clearAll();
                
                // 激活左侧列表
                const listItem = document.querySelector(`.triz-item[data-step="${step}"]`);
                if (listItem) listItem.classList.add('active');

                // 激活 SVG 连线与特效
                const group = linkGroups[step];
                if (group) {
                    document.querySelectorAll(group.link).forEach(el => el.classList.add('active'));
                    document.querySelectorAll(group.flow).forEach(el => el.classList.add('active'));
                    document.querySelectorAll(group.label).forEach(el => el.classList.add('active'));
                    if (group.extra) {
                        document.querySelectorAll(group.extra).forEach(el => el.classList.add('active'));
                    }
                }

                // 更新顶部状态栏文字
                if (step === 1) statusBar.innerHTML = "⚠️ 检出有害功能:【高处坠落风险】";
                else if (step === 2) statusBar.innerHTML = "⚡ 检出有害功能:【高压触电危险】";
                else if (step === 3) statusBar.innerHTML = "✅ 检出有用功能:【物理固定导线】 (极度耗时)";
                else if (step === 4) statusBar.innerHTML = "❌ 检出不足功能:【可靠性差,易松动】";
                else if (step === 5) {
                    statusBar.innerHTML = "📉 检出超系统有害相互作用:【大面积停电损失】";
                    sceneDimmer.classList.add('active'); // 模拟全场景停电变暗
                }
            }

            // 状态机循环
            function runStateMachine() {
                activateStep(currentStep);
                currentStep++;
                if (currentStep > totalSteps) {
                    currentStep = 1; // 循环
                }
            }

            // 启动
            runStateMachine();
            setInterval(runStateMachine, STEP_DURATION);
        });
    </script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>楔形自锁效应 (Wedge Self-Locking Effect) - 原理仿真</title>
    <style>
        :root {
            /* 深度工程蓝图配色 */
            --bg-base: #040814;
            --grid-main: rgba(0, 240, 255, 0.1);
            --grid-sub: rgba(0, 240, 255, 0.03);
            
            /* 组件色彩 */
            --color-casing: #1E293B;       /* 外壳装甲色 */
            --color-wedge: #334155;        /* 楔形块金属色 */
            --color-wire: #E2E8F0;         /* 导线银白色 */
            
            /* 数据与力学特征色 */
            --color-neon-cyan: #00F0FF;    /* 结构与维度线 */
            --color-force-down: #FF3B30;   /* 下拉力/重力 (危险红) */
            --color-force-clamp: #10B981;  /* 夹紧力 (安全绿) */
            --color-force-fric: #F59E0B;   /* 摩擦力 (警告黄) */
            
            /* 排版规范 */
            --font-mono: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
            --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
            
            --anim-duration: 8s;
        }

        * { margin: 0; padding: 0; box-sizing: border-box; }

        body, html {
            width: 100%;
            height: 100%;
            background-color: var(--bg-base);
            /* 工程网格背景 */
            background-image: 
                linear-gradient(var(--grid-main) 1px, transparent 1px),
                linear-gradient(90deg, var(--grid-main) 1px, transparent 1px),
                linear-gradient(var(--grid-sub) 1px, transparent 1px),
                linear-gradient(90deg, var(--grid-sub) 1px, transparent 1px);
            background-size: 100px 100px, 100px 100px, 20px 20px, 20px 20px;
            font-family: var(--font-sans);
            color: #fff;
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        /* ==================== 边缘 HUD 数据面板 (严控字号防遮挡) ==================== */
        .hud-layer {
            position: absolute;
            inset: 0;
            pointer-events: none;
            z-index: 100;
        }

        .panel {
            position: absolute;
            background: rgba(4, 8, 20, 0.85);
            border: 1px solid rgba(0, 240, 255, 0.2);
            backdrop-filter: blur(8px);
            padding: 16px;
            box-shadow: 0 4px 20px rgba(0,0,0,0.5);
            font-family: var(--font-mono);
        }

        .panel-top-left { top: 24px; left: 24px; width: 280px; border-left: 3px solid var(--color-neon-cyan); }
        .panel-top-right { top: 24px; right: 24px; width: 260px; text-align: right; border-right: 3px solid var(--color-force-clamp); }
        .panel-bottom-left { bottom: 24px; left: 24px; width: 300px; }
        .panel-bottom-right { bottom: 24px; right: 24px; text-align: right; }

        .panel-title {
            font-size: 12px;
            font-weight: bold;
            color: var(--color-neon-cyan);
            margin-bottom: 8px;
            text-transform: uppercase;
            letter-spacing: 1px;
            border-bottom: 1px solid rgba(0, 240, 255, 0.3);
            padding-bottom: 4px;
        }

        .data-row {
            display: flex;
            justify-content: space-between;
            font-size: 11px;
            margin-bottom: 6px;
            color: #94A3B8;
        }

        .data-val { font-weight: bold; font-size: 12px; }
        .val-cyan { color: var(--color-neon-cyan); }
        .val-green { color: var(--color-force-clamp); }
        .val-red { color: var(--color-force-down); }
        .val-yellow { color: var(--color-force-fric); }

        .desc-text {
            font-size: 10px;
            line-height: 1.6;
            color: #64748B;
            font-family: var(--font-sans);
            margin-top: 8px;
        }

        .eq-block {
            background: rgba(255,255,255,0.05);
            padding: 6px;
            border-radius: 4px;
            font-size: 11px;
            color: #CBD5E1;
            margin-top: 6px;
            text-align: center;
        }

        /* ==================== SVG 核心动画区 ==================== */
        .svg-canvas {
            width: 100vw;
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 10;
        }

        svg {
            width: 100%;
            height: 100%;
            max-width: 1200px;
            max-height: 900px;
            overflow: visible;
        }

        /* ----- 静态结构样式 ----- */
        .casing { fill: var(--color-casing); stroke: var(--color-neon-cyan); stroke-width: 2; }
        .casing-hatch { stroke: rgba(0, 240, 255, 0.1); stroke-width: 1; }
        .dimension-line { stroke: var(--color-neon-cyan); stroke-width: 1; stroke-dasharray: 4 4; opacity: 0.5; }
        .dimension-text { fill: var(--color-neon-cyan); font-family: var(--font-mono); font-size: 14px; opacity: 0.8; }
        
        /* ----- 动态物理实体 ----- */
        .wedge { fill: var(--color-wedge); stroke: #475569; stroke-width: 2; }
        .friction-pad { fill: #0F172A; stroke: #000; }
        .wire { fill: var(--color-wire); stroke: #94A3B8; stroke-width: 2; }
        .wire-glow { fill: none; stroke: var(--color-wire); stroke-width: 8; opacity: 0.2; filter: blur(4px); }

        /* ----- 动画定义 (纯CSS物理模拟) ----- */
        
        /* 系统整体下降缓冲 */
        #dynamic-system {
            animation: systemDrop var(--anim-duration) cubic-bezier(0.4, 0, 0.2, 1) infinite;
        }
        @keyframes systemDrop {
            0%, 15% { transform: translateY(-80px); }
            35%, 85% { transform: translateY(0px); }
            95%, 100% { transform: translateY(-80px); }
        }

        /* 导线独立位移 (受重力先下沉,推动楔块) */
        #wire-group {
            animation: wireDrop var(--anim-duration) cubic-bezier(0.4, 0, 0.2, 1) infinite;
        }
        @keyframes wireDrop {
            0%, 10% { transform: translateY(-20px); }
            35%, 85% { transform: translateY(0px); }
            90%, 100% { transform: translateY(-20px); }
        }

        /* 左楔块: 沿导轨斜面向下向内滑动 (假设斜角15度, dx = dy * tan(15)) */
        #wedge-l {
            animation: wedgeSlideL var(--anim-duration) cubic-bezier(0.4, 0, 0.2, 1) infinite;
        }
        @keyframes wedgeSlideL {
            0%, 15% { transform: translate(-16px, -60px); }
            35%, 85% { transform: translate(0px, 0px); }
            95%, 100% { transform: translate(-16px, -60px); }
        }

        /* 右楔块: 沿导轨斜面向下向内滑动 */
        #wedge-r {
            animation: wedgeSlideR var(--anim-duration) cubic-bezier(0.4, 0, 0.2, 1) infinite;
        }
        @keyframes wedgeSlideR {
            0%, 15% { transform: translate(16px, -60px); }
            35%, 85% { transform: translate(0px, 0px); }
            95%, 100% { transform: translate(16px, -60px); }
        }

        /* ----- 力学矢量箭头动画 ----- */
        .force-vector { stroke-width: 3; fill: none; opacity: 0; }
        .force-label { font-family: var(--font-mono); font-size: 16px; font-weight: bold; opacity: 0; }
        
        /* 导线向下重力/拉力 */
        .anim-force-down { animation: showForceDown var(--anim-duration) infinite; stroke: var(--color-force-down); }
        .anim-label-down { animation: showForceDown var(--anim-duration) infinite; fill: var(--color-force-down); }
        @keyframes showForceDown {
            0%, 20% { opacity: 0; transform: scaleY(0.5); }
            30%, 80% { opacity: 1; transform: scaleY(1); }
            85%, 100% { opacity: 0; transform: scaleY(0.5); }
        }

        /* 侧向夹紧力 (放大效应) */
        .anim-force-clamp { animation: showForceClamp var(--anim-duration) infinite; stroke: var(--color-force-clamp); }
        .anim-label-clamp { animation: showForceClamp var(--anim-duration) infinite; fill: var(--color-force-clamp); }
        @keyframes showForceClamp {
            0%, 30% { opacity: 0; transform: scaleX(0.2); }
            40%, 80% { opacity: 1; transform: scaleX(1); }
            85%, 100% { opacity: 0; transform: scaleX(0.2); }
        }

        /* 斜面摩擦力与支持力 */
        .anim-force-fric { animation: showForceFric var(--anim-duration) infinite; stroke: var(--color-force-fric); }
        .anim-label-fric { animation: showForceFric var(--anim-duration) infinite; fill: var(--color-force-fric); font-size: 14px;}
        @keyframes showForceFric {
            0%, 35% { opacity: 0; }
            45%, 80% { opacity: 1; }
            85%, 100% { opacity: 0; }
        }

        /* 自锁成功状态光晕 */
        .lock-glow {
            fill: none;
            stroke: var(--color-force-clamp);
            stroke-width: 4;
            opacity: 0;
            filter: blur(6px);
            animation: lockSuccess var(--anim-duration) infinite;
        }
        @keyframes lockSuccess {
            0%, 38% { opacity: 0; }
            45%, 80% { opacity: 0.6; }
            85%, 100% { opacity: 0; }
        }

    </style>
</head>
<body>

    <!-- 边缘物理量监控面板 -->
    <div class="hud-layer">
        
        <!-- 左上:效应定义 -->
        <div class="panel panel-top-left">
            <div class="panel-title">Wedge Self-Locking Effect</div>
            <div class="data-row">
                <span>物理机制</span>
                <span class="val-cyan">摩擦自锁</span>
            </div>
            <div class="data-row">
                <span>能量转化</span>
                <span class="val-cyan">轴向拉力 → 径向夹紧力</span>
            </div>
            <div class="desc-text">
                利用斜面原理,当输入的外力(导线自重或拉力)驱使楔形块沿斜面向下运动时,斜面迫使楔块向内收缩,将较小的下拉力按三角函数几何放大为巨大的侧向夹紧力。
            </div>
        </div>

        <!-- 右上:实时遥测数据 -->
        <div class="panel panel-top-right">
            <div class="panel-title" style="border-color: var(--color-force-clamp); color: var(--color-force-clamp);">实时动态遥测</div>
            <div class="data-row">
                <span>系统状态</span>
                <span class="data-val" id="ui-status" style="color: #94A3B8;">待机 / 松弛</span>
            </div>
            <div class="data-row">
                <span>轴向下拉力 (F_y)</span>
                <span class="data-val val-red" id="ui-force-down">0 N</span>
            </div>
            <div class="data-row">
                <span>侧向夹紧力 (F_c)</span>
                <span class="data-val val-green" id="ui-force-clamp">0 N</span>
            </div>
            <div class="data-row">
                <span>机械放大倍率 (M.A.)</span>
                <span class="data-val val-cyan" id="ui-ratio">1.0 x</span>
            </div>
        </div>

        <!-- 左下:力学条件 -->
        <div class="panel panel-bottom-left">
            <div class="panel-title">自锁临界条件分析</div>
            <div class="data-row">
                <span>斜面夹角 (α)</span>
                <span class="data-val val-cyan">15°</span>
            </div>
            <div class="data-row">
                <span>静摩擦系数 (μ)</span>
                <span class="data-val val-yellow">0.35</span>
            </div>
            <div class="eq-block">
                自锁条件: μ ≥ tan(α)<br>
                0.35 ≥ tan(15°) ≈ 0.268  [<span style="color:var(--color-force-clamp)">满足</span>]
            </div>
            <div class="desc-text" style="text-align: center;">
                无论下拉力多大,系统绝不滑脱,越拉越紧。
            </div>
        </div>

    </div>

    <!-- 核心 SVG 动画 -->
    <div class="svg-canvas">
        <svg viewBox="0 0 1000 1000" preserveAspectRatio="xMidYMid meet">
            <defs>
                <!-- 箭头标记 -->
                <marker id="arrow-down" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="8" markerHeight="8" orient="auto">
                    <path d="M 0 0 L 10 5 L 0 10 z" fill="var(--color-force-down)" />
                </marker>
                <marker id="arrow-clamp" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="8" markerHeight="8" orient="auto">
                    <path d="M 0 0 L 10 5 L 0 10 z" fill="var(--color-force-clamp)" />
                </marker>
                <marker id="arrow-fric" 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-force-fric)" />
                </marker>
                
                <!-- 剖面斜线填充 -->
                <pattern id="hatch" width="10" height="10" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse">
                    <line x1="0" y1="0" x2="0" y2="10" stroke="rgba(0, 240, 255, 0.15)" stroke-width="2" />
                </pattern>
                
                <!-- 金属材质渐变 -->
                <linearGradient id="metal-grad" x1="0%" y1="0%" x2="100%" y2="0%">
                    <stop offset="0%" stop-color="#334155" />
                    <stop offset="50%" stop-color="#64748B" />
                    <stop offset="100%" stop-color="#334155" />
                </linearGradient>
            </defs>

            <!-- 坐标辅助线 (工业感背景) -->
            <line x1="500" y1="100" x2="500" y2="900" stroke="rgba(255,255,255,0.1)" stroke-dasharray="10 10" />
            <line x1="100" y1="500" x2="900" y2="500" stroke="rgba(255,255,255,0.1)" stroke-dasharray="10 10" />
            
            <circle cx="500" cy="500" r="300" fill="none" stroke="rgba(0, 240, 255, 0.05)" stroke-width="1" />
            
            <!-- V型外壳 (固定参考系) -->
            <g transform="translate(500, 500)">
                <!-- 左半外壳 (内侧倾角 15度) -->
                <path class="casing" d="M -160,-250 L -180,-250 L -180,250 L -40,250 L -100,-250 Z" />
                <path d="M -160,-250 L -180,-250 L -180,250 L -40,250 L -100,-250 Z" fill="url(#hatch)"/>
                
                <!-- 右半外壳 (内侧倾角 15度) -->
                <path class="casing" d="M 160,-250 L 180,-250 L 180,250 L 40,250 L 100,-250 Z" />
                <path d="M 160,-250 L 180,-250 L 180,250 L 40,250 L 100,-250 Z" fill="url(#hatch)"/>

                <!-- 角度标注 -->
                <line class="dimension-line" x1="-100" y1="-250" x2="-100" y2="-150" />
                <path d="M -100,-180 A 70 70 0 0 0 -80,-185" fill="none" stroke="var(--color-neon-cyan)" stroke-width="1" />
                <text x="-95" y="-195" class="dimension-text">α=15°</text>
            </g>

            <!-- 动态系统组 (受外力驱动整体下沉) -->
            <g id="dynamic-system" transform="translate(500, 500)">
                
                <!-- 左侧楔块 -->
                <g id="wedge-l">
                    <path class="wedge" fill="url(#metal-grad)" d="M -90,-200 L -30,-200 L -30,200 L -90,-200 Z" />
                    <!-- 摩擦橡胶垫/防滑齿 -->
                    <rect class="friction-pad" x="-30" y="-150" width="8" height="300" rx="2" />
                    <path d="M -22,-140 L -28,-135 M -22,-130 L -28,-125 M -22,-120 L -28,-115" stroke="#475569" stroke-width="2"/>
                    <path d="M -22,140 L -28,135 M -22,130 L -28,125 M -22,120 L -28,115" stroke="#475569" stroke-width="2"/>

                    <!-- 力学分析向量 (左侧) -->
                    <!-- 支持力 F_N -->
                    <line class="force-vector anim-force-fric" x1="-80" y1="0" x2="-30" y2="15" marker-end="url(#arrow-fric)" />
                    <text x="-90" y="30" class="force-label anim-label-fric">F_N</text>
                    <!-- 摩擦力 f -->
                    <line class="force-vector anim-force-fric" x1="-60" y1="0" x2="-80" y2="-75" marker-end="url(#arrow-fric)" />
                    <text x="-95" y="-85" class="force-label anim-label-fric">f</text>
                </g>

                <!-- 右侧楔块 -->
                <g id="wedge-r">
                    <path class="wedge" fill="url(#metal-grad)" d="M 90,-200 L 30,-200 L 30,200 L 90,-200 Z" />
                    <!-- 摩擦橡胶垫/防滑齿 -->
                    <rect class="friction-pad" x="22" y="-150" width="8" height="300" rx="2" />
                    <path d="M 22,-140 L 28,-135 M 22,-130 L 28,-125 M 22,-120 L 28,-115" stroke="#475569" stroke-width="2"/>
                    <path d="M 22,140 L 28,135 M 22,130 L 28,125 M 22,120 L 28,115" stroke="#475569" stroke-width="2"/>
                </g>

                <!-- 导线与输入力 (居中) -->
                <g id="wire-group">
                    <circle cx="0" cy="0" r="30" class="wire-glow" />
                    <circle cx="0" cy="0" r="28" class="wire" />
                    <circle cx="0" cy="0" r="10" fill="none" stroke="#64748B" stroke-dasharray="4 2" />
                    <circle cx="0" cy="0" r="20" fill="none" stroke="#64748B" stroke-dasharray="6 4" />

                    <!-- 向下的主驱动力 (F_pull / 导线重力) -->
                    <g transform="translate(0, 35)">
                        <line class="force-vector anim-force-down" x1="0" y1="0" x2="0" y2="120" marker-end="url(#arrow-down)" style="transform-origin: top center;" />
                        <text x="15" y="100" class="force-label anim-label-down">F_pull</text>
                    </g>
                </g>

                <!-- 夹紧力动画 (F_c) -->
                <g transform="translate(0, 0)">
                    <!-- 左侧向右的夹紧力 -->
                    <line class="force-vector anim-force-clamp" x1="-150" y1="0" x2="-40" y2="0" marker-end="url(#arrow-clamp)" style="transform-origin: left center;" />
                    <text x="-130" y="-15" class="force-label anim-label-clamp">F_clamp</text>
                    
                    <!-- 右侧向左的夹紧力 -->
                    <line class="force-vector anim-force-clamp" x1="150" y1="0" x2="40" y2="0" marker-end="url(#arrow-clamp)" style="transform-origin: right center;" />
                    <text x="70" y="-15" class="force-label anim-label-clamp">F_clamp</text>
                </g>

                <!-- 成功锁紧的光晕提示 -->
                <rect x="-35" y="-180" width="70" height="360" rx="4" class="lock-glow" />

            </g>
        </svg>
    </div>

    <!-- 数据同步逻辑:将物理数值与 CSS 动画时间轴同步 -->
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const elStatus = document.getElementById('ui-status');
            const elForceDown = document.getElementById('ui-force-down');
            const elForceClamp = document.getElementById('ui-force-clamp');
            const elRatio = document.getElementById('ui-ratio');

            const animDuration = 8000; // 8秒周期,与 CSS 保持一致

            function updateTelemetry(timestamp) {
                // 计算当前动画在周期内的进度 0.0 ~ 1.0
                const progress = (timestamp % animDuration) / animDuration;

                // 基于 CSS Keyframes 的定义同步数值
                // 0-15%: 开始下沉
                // 15-35%: 锁紧过程 (力急剧增加)
                // 35-85%: 保持锁紧状态
                // 85-100%: 释放复位
                
                let forceDown = 0;
                let forceClamp = 0;
                let status = "待机 / 松弛";
                let statusColor = "#94A3B8";

                if (progress < 0.15 || progress > 0.90) {
                    // 待机阶段
                    forceDown = 0;
                    forceClamp = 0;
                } else if (progress >= 0.15 && progress < 0.35) {
                    // 动态增加阶段
                    const localP = (progress - 0.15) / 0.20; // 0 to 1
                    // 使用缓动曲线模拟
                    const easeOut = 1 - Math.pow(1 - localP, 3);
                    forceDown = easeOut * 250; 
                    forceClamp = easeOut * 920; 
                    status = "楔块介入收缩...";
                    statusColor = "var(--color-force-fric)";
                } else if (progress >= 0.35 && progress <= 0.85) {
                    // 自锁保持阶段 (加入微小扰动显得真实)
                    forceDown = 250 + Math.random() * 5;
                    forceClamp = 920 + Math.random() * 15;
                    status = "自锁生效 [LOCKED]";
                    statusColor = "var(--color-force-clamp)";
                } else {
                    // 释放阶段
                    const localP = (progress - 0.85) / 0.05;
                    forceDown = 250 * (1 - localP);
                    forceClamp = 920 * (1 - localP);
                    status = "释放脱离...";
                    statusColor = "var(--color-force-down)";
                }

                // 渲染数值
                elForceDown.textContent = Math.floor(forceDown) + " N";
                elForceClamp.textContent = Math.floor(forceClamp) + " N";
                elStatus.textContent = status;
                elStatus.style.color = statusColor;

                // 计算实际放大倍率
                if (forceDown > 10) {
                    const ratio = forceClamp / forceDown;
                    elRatio.textContent = ratio.toFixed(1) + " x";
                } else {
                    elRatio.textContent = "1.0 x";
                }

                requestAnimationFrame(updateTelemetry);
            }

            // 启动同步循环
            requestAnimationFrame(updateTelemetry);
        });
    </script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>楔形自锁效应原理可视化 (Wedge Self-Locking Effect)</title>
    <style>
        :root {
            /* 工业科研级配色 */
            --bg-color: #050508;
            --grid-line: rgba(30, 64, 175, 0.2);
            --blueprint-blue: #1E3A8A;
            --tech-cyan: #00E5FF;
            --accent-orange: #FF6D00;
            --force-green: #00E676;
            --force-red: #FF1744;
            --housing-dark: #0F172A;
            --wedge-color: #1E293B;
            
            --text-main: #F8FAFC;
            --text-dim: #64748B;
            --font-mono: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
            --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            
            --anim-duration: 8s;
        }

        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            background-color: var(--bg-color);
            background-image: 
                linear-gradient(var(--grid-line) 1px, transparent 1px),
                linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
            background-size: 40px 40px;
            font-family: var(--font-sans);
            color: var(--text-main);
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        /* ================= HUD 信息面板 (边缘停靠、极简小字号、防遮挡) ================= */
        .hud-layer {
            position: absolute;
            inset: 0;
            pointer-events: none;
            z-index: 100;
            display: flex;
            flex-direction: column;
            justify-content: space-between;
        }

        .panel {
            position: absolute;
            background: rgba(5, 5, 8, 0.85);
            border: 1px solid rgba(0, 229, 255, 0.2);
            backdrop-filter: blur(8px);
            padding: 16px 20px;
            border-radius: 4px;
        }

        /* 左上:原理描述 */
        .panel-top-left {
            top: 24px;
            left: 24px;
            max-width: 320px;
            border-left: 3px solid var(--tech-cyan);
        }

        .title {
            font-family: var(--font-mono);
            font-size: 14px;
            font-weight: bold;
            color: var(--tech-cyan);
            margin-bottom: 8px;
            letter-spacing: 1px;
            text-transform: uppercase;
        }

        .desc {
            font-size: 12px;
            color: var(--text-dim);
            line-height: 1.6;
        }

        .highlight { color: var(--accent-orange); font-weight: bold; }

        /* 右上:力学实时参数监控 */
        .panel-top-right {
            top: 24px;
            right: 24px;
            width: 240px;
            border-right: 3px solid var(--force-green);
            text-align: right;
        }

        .data-row {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 8px;
            font-size: 12px;
            font-family: var(--font-mono);
        }

        .data-value {
            font-size: 20px;
            font-weight: bold;
            transition: color 0.2s;
        }

        /* 底部居中:公式定理 */
        .panel-bottom {
            bottom: 24px;
            left: 50%;
            transform: translateX(-50%);
            display: flex;
            gap: 32px;
            border-top: 2px solid var(--blueprint-blue);
            padding: 12px 32px;
            font-family: var(--font-mono);
            font-size: 12px;
            color: var(--text-dim);
        }

        /* ================= 核心 SVG 动画区域 ================= */
        .svg-container {
            width: 100vw;
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 10;
        }

        svg {
            width: 100%;
            height: 100%;
            max-width: 1000px;
            max-height: 800px;
            overflow: visible;
        }

        /* --- 动画状态类 --- */

        /* 1. 楔形块滑动 (斜向移动) */
        .anim-wedge-left { animation: slideLeft var(--anim-duration) ease-in-out infinite; }
        .anim-wedge-right { animation: slideRight var(--anim-duration) ease-in-out infinite; }
        
        @keyframes slideLeft {
            0%, 15% { transform: translate(-25px, -200px); }
            20% { transform: translate(-25px, -200px); }
            40%, 75% { transform: translate(0px, 0px); }
            85%, 100% { transform: translate(-25px, -200px); }
        }
        @keyframes slideRight {
            0%, 15% { transform: translate(25px, -200px); }
            20% { transform: translate(25px, -200px); }
            40%, 75% { transform: translate(0px, 0px); }
            85%, 100% { transform: translate(25px, -200px); }
        }

        /* 2. 导线垂直下沉 */
        .anim-wire { animation: dropWire var(--anim-duration) ease-in-out infinite; }
        @keyframes dropWire {
            0%, 10% { transform: translate(0px, -350px); }
            20% { transform: translate(0px, -200px); } /* 接触楔形块 */
            40%, 75% { transform: translate(0px, 0px); }   /* 共同下沉自锁 */
            85%, 100% { transform: translate(0px, -350px); }
        }

        /* 3. 力学矢量箭头显隐 */
        .anim-force { animation: showForces var(--anim-duration) infinite; }
        @keyframes showForces {
            0%, 42% { opacity: 0; transform: scale(0.8); }
            48%, 70% { opacity: 1; transform: scale(1); }
            75%, 100% { opacity: 0; transform: scale(0.8); }
        }

        /* 4. 力流特效线 */
        .force-flow { stroke-dasharray: 8 8; animation: flowDash 0.5s linear infinite; }
        @keyframes flowDash { to { stroke-dashoffset: -16; } }

        /* 5. 支撑弹簧压缩 */
        .anim-spring-l { animation: compressSpringL var(--anim-duration) ease-in-out infinite; transform-origin: center bottom; }
        .anim-spring-r { animation: compressSpringR var(--anim-duration) ease-in-out infinite; transform-origin: center bottom; }
        @keyframes compressSpringL {
            0%, 20% { transform: scaleY(1) translate(-25px, 0); }
            40%, 75% { transform: scaleY(0.4) translate(0px, 0); }
            85%, 100% { transform: scaleY(1) translate(-25px, 0); }
        }
        @keyframes compressSpringR {
            0%, 20% { transform: scaleY(1) translate(25px, 0); }
            40%, 75% { transform: scaleY(0.4) translate(0px, 0); }
            85%, 100% { transform: scaleY(1) translate(25px, 0); }
        }

    </style>
</head>
<body>

    <!-- UI 面板 -->
    <div class="hud-layer">
        <div class="panel panel-top-left">
            <div class="title">TRIZ 创新原理:楔形自锁效应</div>
            <div class="desc">
                系统利用导线自身的<span class="highlight">重力/下拔力</span>作为驱动源。当导线向下移动时,迫使两侧楔形块沿导轨斜面滑动。<br><br>
                通过斜面的几何特性,垂直向下的位移被转化为巨大的<span style="color:var(--force-green); font-weight:bold;">侧向夹紧力</span>。拉力越大,夹得越紧,实现了在不增加复杂机械结构前提下的“最终理想解 (IFR)”。
            </div>
        </div>

        <div class="panel panel-top-right">
            <div class="title" style="color: var(--text-main); border-color: var(--force-green);">动态力学监测</div>
            
            <div class="data-row">
                <span style="color: var(--text-dim);">系统状态</span>
                <span id="ui-status" style="color: var(--tech-cyan);">待机 / 挂载中</span>
            </div>
            <div style="height: 1px; background: rgba(255,255,255,0.1); margin: 12px 0;"></div>
            
            <div class="data-row">
                <span style="color: var(--text-dim);">导线垂直载荷 (Fy)</span>
                <span class="data-value" id="ui-force-y" style="color: var(--accent-orange);">0 N</span>
            </div>
            
            <div class="data-row">
                <span style="color: var(--text-dim);">单侧夹紧力 (Fx)</span>
                <span class="data-value" id="ui-force-x" style="color: var(--force-green);">0 N</span>
            </div>
            
            <div class="data-row" style="margin-top: 12px; font-size: 10px;">
                <span style="color: var(--text-dim);">力放大倍数 (MA)</span>
                <span id="ui-ma" style="color: var(--text-main);">--</span>
            </div>
        </div>

        <div class="panel panel-bottom">
            <span>几何斜角: θ = 7.125°</span>
            <span>自锁条件: tan(θ) ≤ μ</span>
            <span style="color: var(--force-green);">力学方程: F_clamp = F_y / [2(tanθ + μ)]</span>
        </div>
    </div>

    <!-- 核心 SVG 动画 -->
    <div class="svg-container">
        <svg viewBox="0 0 1000 800" preserveAspectRatio="xMidYMid meet">
            <defs>
                <!-- 发光滤镜 -->
                <filter id="glow-cyan"><feGaussianBlur stdDeviation="4" result="blur" /><feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
                <filter id="glow-orange"><feGaussianBlur stdDeviation="6" result="blur" /><feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
                <filter id="glow-green"><feGaussianBlur stdDeviation="5" result="blur" /><feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
                
                <!-- 箭头标识 -->
                <marker id="arrow-red" 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(--force-red)" />
                </marker>
                <marker id="arrow-green" 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(--force-green)" />
                </marker>
                <marker id="arrow-blue" 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="#3B82F6" />
                </marker>

                <!-- 防滑齿纹理 (用于楔形块内侧) -->
                <pattern id="teeth-pattern" width="10" height="8" patternUnits="userSpaceOnUse">
                    <path d="M 0 0 L 10 4 L 0 8 Z" fill="#334155" />
                </pattern>
                <pattern id="teeth-pattern-r" width="10" height="8" patternUnits="userSpaceOnUse">
                    <path d="M 10 0 L 0 4 L 10 8 Z" fill="#334155" />
                </pattern>
            </defs>

            <!-- 坐标系辅助线 (增强科技感) -->
            <g opacity="0.2">
                <line x1="500" y1="50" x2="500" y2="750" stroke="#94A3B8" stroke-dasharray="4 4"/>
                <line x1="250" y1="450" x2="750" y2="450" stroke="#94A3B8" stroke-dasharray="4 4"/>
            </g>

            <!-- 系统整体坐标变换 (中心对齐) -->
            <g transform="translate(500, 450)">
                
                <!-- 1. 外部底座与导轨 (V型槽) -->
                <!-- 斜率设计:1/8 (约7.1度) -->
                <g id="housing">
                    <!-- 左侧外壳 -->
                    <polygon points="-160,-250 -81.25,-250 -43.75,50 -160,50" fill="var(--housing-dark)" stroke="var(--tech-cyan)" stroke-width="3" filter="url(#glow-cyan)"/>
                    <line x1="-81.25" y1="-250" x2="-43.75" y2="50" stroke="#38BDF8" stroke-width="2"/> <!-- 导轨滑动面 -->
                    
                    <!-- 右侧外壳 -->
                    <polygon points="160,-250 81.25,-250 43.75,50 160,50" fill="var(--housing-dark)" stroke="var(--tech-cyan)" stroke-width="3" filter="url(#glow-cyan)"/>
                    <line x1="81.25" y1="-250" x2="43.75" y2="50" stroke="#38BDF8" stroke-width="2"/>
                    
                    <!-- 底部连接桥 -->
                    <rect x="-160" y="50" width="320" height="40" fill="var(--housing-dark)" stroke="var(--tech-cyan)" stroke-width="3"/>
                    <text x="0" y="75" font-family="var(--font-mono)" font-size="12" fill="var(--tech-cyan)" text-anchor="middle" letter-spacing="2">BASE_FIXTURE_STRUCT</text>
                </g>

                <!-- 2. 复位支撑弹簧 (抽象液压推杆) -->
                <g class="anim-spring-l">
                    <rect x="-65" y="50" width="10" height="150" fill="#475569" transform="translate(0, -150)"/>
                    <path d="M -75,-100 L -55,-100 M -70,-80 L -60,-80 M -75,-60 L -55,-60 M -70,-40 L -60,-40" stroke="#94A3B8" stroke-width="2"/>
                </g>
                <g class="anim-spring-r">
                    <rect x="55" y="50" width="10" height="150" fill="#475569" transform="translate(0, -150)"/>
                    <path d="M 55,-100 L 75,-100 M 60,-80 L 70,-80 M 55,-60 L 75,-60 M 60,-40 L 70,-40" stroke="#94A3B8" stroke-width="2"/>
                </g>

                <!-- 3. 左侧楔形块 (自锁滑块) -->
                <!-- 自锁状态位置:内缘 x=-30, 顶y=-100, 底y=50 -->
                <g class="anim-wedge-left">
                    <polygon points="-30,-100 -62.5,-100 -43.75,50 -30,50" fill="var(--wedge-color)" stroke="#38BDF8" stroke-width="2"/>
                    <!-- 防滑齿 -->
                    <rect x="-30" y="-95" width="10" height="140" fill="url(#teeth-pattern)"/>
                </g>

                <!-- 4. 右侧楔形块 -->
                <g class="anim-wedge-right">
                    <polygon points="30,-100 62.5,-100 43.75,50 30,50" fill="var(--wedge-color)" stroke="#38BDF8" stroke-width="2"/>
                    <rect x="20" y="-95" width="10" height="140" fill="url(#teeth-pattern-r)"/>
                </g>

                <!-- 5. 导线实体 (受力源) -->
                <g class="anim-wire">
                    <circle cx="0" cy="-25" r="30" fill="#E2E8F0" stroke="var(--accent-orange)" stroke-width="4" filter="url(#glow-orange)"/>
                    <!-- 截面纹理 -->
                    <circle cx="0" cy="-25" r="20" fill="none" stroke="#94A3B8" stroke-width="1" stroke-dasharray="3 3"/>
                    <circle cx="0" cy="-25" r="10" fill="none" stroke="#94A3B8" stroke-width="1" stroke-dasharray="2 2"/>
                    <text x="0" y="-21" font-family="var(--font-mono)" font-size="10" fill="var(--housing-dark)" font-weight="bold" text-anchor="middle">WIRE</text>

                    <!-- 6. 力学矢量可视化 (跟随导线并在自锁时显示) -->
                    <g class="anim-force">
                        <!-- 向下重力/拔力 (Fy) -->
                        <line x1="0" y1="5" x2="0" y2="85" stroke="var(--force-red)" stroke-width="4" marker-end="url(#arrow-red)"/>
                        <text x="15" y="75" font-family="var(--font-sans)" font-size="14" font-weight="bold" fill="var(--force-red)">Fy</text>
                        
                        <!-- 左侧外壳给予楔形块的法向支持力 (Fn) 垂直于斜面 -->
                        <!-- 斜率1/8,法线斜率-8 -->
                        <line x1="-100" y1="-32.5" x2="-60" y2="-27.5" stroke="#3B82F6" stroke-width="3" marker-end="url(#arrow-blue)"/>
                        
                        <!-- 右侧法向支持力 (Fn) -->
                        <line x1="100" y1="-32.5" x2="60" y2="-27.5" stroke="#3B82F6" stroke-width="3" marker-end="url(#arrow-blue)"/>

                        <!-- 左侧楔形块对导线的侧向夹紧力 (Fx) -->
                        <line x1="-90" y1="-25" x2="-35" y2="-25" class="force-flow" stroke="var(--force-green)" stroke-width="4" marker-end="url(#arrow-green)"/>
                        <text x="-65" y="-35" font-family="var(--font-sans)" font-size="14" font-weight="bold" fill="var(--force-green)">Fx</text>

                        <!-- 右侧楔形块对导线的侧向夹紧力 (Fx) -->
                        <line x1="90" y1="-25" x2="35" y2="-25" class="force-flow" stroke="var(--force-green)" stroke-width="4" marker-end="url(#arrow-green)"/>
                        <text x="50" y="-35" font-family="var(--font-sans)" font-size="14" font-weight="bold" fill="var(--force-green)">Fx</text>
                    </g>
                </g>

            </g>
        </svg>
    </div>

    <!-- 逻辑控制脚本:同步力学参数显示 -->
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const uiStatus = document.getElementById('ui-status');
            const uiForceY = document.getElementById('ui-force-y');
            const uiForceX = document.getElementById('ui-force-x');
            const uiMA = document.getElementById('ui-ma');
            
            const totalDuration = 8000; // 动画周期 8s
            
            // 物理参数设定
            const theta = 7.125; // 角度
            const mu = 0.05;     // 滑动摩擦系数假设值
            const tanTheta = 0.125;
            
            // 力放大倍数 MA = 1 / [2 * (tanθ + μ)]
            const MA = 1 / (2 * (tanTheta + mu));

            function updateData() {
                const now = Date.now();
                const progress = (now % totalDuration) / totalDuration;
                
                // 根据 CSS 动画进度区间设定力学数值
                // 0.0 - 0.2: 导线下沉未接触
                // 0.2 - 0.4: 接触并推动楔形块下沉
                // 0.4 - 0.75: 完全锁紧 (力最大)
                // 0.75 - 0.85: 解锁复位中
                // 0.85 - 1.0: 顶部待机
                
                let fy = 0;
                let fx = 0;

                if (progress < 0.2) {
                    uiStatus.textContent = "空载下行中...";
                    uiStatus.style.color = "var(--text-dim)";
                } else if (progress < 0.4) {
                    uiStatus.textContent = "楔入自锁行程";
                    uiStatus.style.color = "var(--tech-cyan)";
                    // 力值线性增加
                    const ratio = (progress - 0.2) / 0.2;
                    fy = ratio * 450; 
                } else if (progress < 0.75) {
                    uiStatus.textContent = "触发最终理想解 (IFR自锁)";
                    uiStatus.style.color = "var(--force-green)";
                    // 模拟微小的动态力学波动
                    fy = 450 + Math.random() * 20;
                } else if (progress < 0.85) {
                    uiStatus.textContent = "卸载复位";
                    uiStatus.style.color = "var(--text-dim)";
                    const ratio = 1 - ((progress - 0.75) / 0.1);
                    fy = ratio * 450;
                } else {
                    uiStatus.textContent = "待机准备";
                    uiStatus.style.color = "var(--text-dim)";
                }

                // 根据公式计算夹紧力
                fx = fy * MA;

                uiForceY.textContent = fy.toFixed(0) + " N";
                uiForceX.textContent = fx.toFixed(0) + " N";
                
                if (fy > 10) {
                    uiMA.textContent = MA.toFixed(2) + "x";
                    uiMA.style.color = "var(--force-green)";
                } else {
                    uiMA.textContent = "--";
                    uiMA.style.color = "var(--text-dim)";
                }

                requestAnimationFrame(updateData);
            }

            // 启动同步循环
            requestAnimationFrame(updateData);
        });
    </script>
</body>
</html>

这里为您提供一份全新设计的、基于高科技工程 CAD 蓝图风格的高保真动画,深度仿真并可视化“楔形自锁效应”的核心力学原理。动画无需任何点击,加载后即刻自动循环播放。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>楔形自锁效应 (Wedge Self-Locking) - 高保真力学仿真</title>
    <style>
        :root {
            /* 战术工程蓝图配色系统 */
            --bg-color: #020617;           /* 极暗蓝底色 */
            --grid-line: rgba(14, 165, 233, 0.15); /* 网格线 */
            --grid-sub: rgba(14, 165, 233, 0.05);
            
            /* 核心组件色彩 */
            --color-casing: #0F172A;       /* 外壳装甲底色 */
            --color-casing-border: #38BDF8;/* 外壳边框发光 */
            --color-wedge: #1E293B;        /* 楔形块 */
            --color-wedge-border: #94A3B8;
            --color-wire: #E2E8F0;         /* 导线核心 */
            
            /* 力学特征色 (高对比度霓虹色) */
            --force-input: #F97316;        /* 输入拉力 (亮橙) */
            --force-clamp: #10B981;        /* 夹紧力 (荧光绿) */
            --force-fric: #FACC15;         /* 摩擦力 (警示黄) */
            --force-stress: #EF4444;       /* 应力集中/危险 (亮红) */
            
            /* 字体排版规范 */
            --font-mono: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
            --font-sans: system-ui, -apple-system, sans-serif;
            
            /* 全局动画周期 */
            --cycle: 8s;
        }

        * { margin: 0; padding: 0; box-sizing: border-box; }

        body, html {
            width: 100%;
            height: 100%;
            background-color: var(--bg-color);
            background-image: 
                linear-gradient(var(--grid-line) 1px, transparent 1px),
                linear-gradient(90deg, var(--grid-line) 1px, transparent 1px),
                linear-gradient(var(--grid-sub) 1px, transparent 1px),
                linear-gradient(90deg, var(--grid-sub) 1px, transparent 1px);
            background-size: 100px 100px, 100px 100px, 20px 20px, 20px 20px;
            background-position: center center;
            font-family: var(--font-sans);
            color: #fff;
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        /* ==================== 边缘数据面板 (严控尺寸防遮挡) ==================== */
        .hud-layer {
            position: absolute;
            inset: 0;
            pointer-events: none;
            z-index: 100;
        }

        .hud-panel {
            position: absolute;
            background: rgba(2, 6, 23, 0.75);
            border: 1px solid rgba(56, 189, 248, 0.2);
            backdrop-filter: blur(12px);
            padding: 16px 20px;
            box-shadow: 0 8px 32px rgba(0,0,0,0.6);
            border-radius: 4px;
        }

        /* 绝对边缘定位 */
        .panel-tl { top: 20px; left: 20px; width: 300px; border-left: 3px solid var(--color-casing-border); }
        .panel-tr { top: 20px; right: 20px; width: 280px; text-align: right; border-right: 3px solid var(--force-clamp); }
        .panel-bl { bottom: 20px; left: 20px; width: 320px; border-left: 3px solid var(--force-fric); }
        
        .panel-title {
            font-size: 12px;
            font-weight: bold;
            color: var(--color-casing-border);
            margin-bottom: 12px;
            letter-spacing: 1px;
            text-transform: uppercase;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        
        .panel-tr .panel-title { justify-content: flex-end; color: var(--force-clamp); }
        .panel-bl .panel-title { color: var(--force-fric); }

        .data-row {
            display: flex;
            justify-content: space-between;
            align-items: center;
            font-size: 11px;
            font-family: var(--font-mono);
            color: #94A3B8;
            margin-bottom: 8px;
        }

        .data-val { font-size: 13px; font-weight: bold; }
        .val-orange { color: var(--force-input); text-shadow: 0 0 8px rgba(249,115,22,0.4); }
        .val-green { color: var(--force-clamp); text-shadow: 0 0 8px rgba(16,185,129,0.4); }
        .val-cyan { color: var(--color-casing-border); }

        .desc-text {
            font-size: 11px;
            line-height: 1.6;
            color: #64748B;
            margin-top: 12px;
            border-top: 1px solid rgba(255,255,255,0.05);
            padding-top: 8px;
        }

        /* ==================== SVG 核心动画区 ==================== */
        .svg-canvas {
            width: 100vw;
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 10;
        }

        svg {
            width: 100%;
            height: 100%;
            max-width: 1000px;
            max-height: 800px;
            overflow: visible;
        }

        /* ----- 几何实体基础样式 ----- */
        .geo-casing { fill: var(--color-casing); stroke: var(--color-casing-border); stroke-width: 2; }
        .geo-wedge { fill: var(--color-wedge); stroke: var(--color-wedge-border); stroke-width: 1.5; }
        .geo-pad { fill: #000; stroke: #334155; }
        .geo-wire { fill: var(--color-wire); stroke: #CBD5E1; stroke-width: 2; }
        
        .dim-line { stroke: var(--color-casing-border); stroke-dasharray: 4 4; stroke-width: 1; opacity: 0.5; }
        .dim-text { fill: var(--color-casing-border); font-family: var(--font-mono); font-size: 12px; }

        /* ----- 力学矢量 (透明度由CSS动画控制) ----- */
        .vector-arrow { stroke-width: 3; fill: none; opacity: 0; }
        .vector-label { font-family: var(--font-mono); font-size: 14px; font-weight: bold; opacity: 0; }
        
        .vec-input { stroke: var(--force-input); }
        .lbl-input { fill: var(--force-input); }
        
        .vec-clamp { stroke: var(--force-clamp); }
        .lbl-clamp { fill: var(--force-clamp); }
        
        .vec-fric { stroke: var(--force-fric); stroke-width: 2;}
        .lbl-fric { fill: var(--force-fric); font-size: 12px;}

        /* ----- 应力热区 (危险红) ----- */
        .stress-glow {
            fill: none;
            stroke: var(--force-stress);
            stroke-width: 6;
            filter: blur(4px);
            opacity: 0;
        }

        /* ==================== 物理系统动画 (CSS Keyframes) ==================== */
        
        /* 1. 中央导线下沉 (主驱动) */
        .anim-wire { animation: wireDrop var(--cycle) cubic-bezier(0.25, 0.1, 0.25, 1) infinite; }
        @keyframes wireDrop {
            0%, 15% { transform: translateY(0px); }
            30%, 80% { transform: translateY(80px); }
            90%, 100% { transform: translateY(0px); }
        }

        /* 2. 左侧楔块沿斜面滑动 (dx = 0.2 * dy -> x:16px, y:80px) */
        .anim-wedge-l { animation: wedgeSlideL var(--cycle) cubic-bezier(0.25, 0.1, 0.25, 1) infinite; }
        @keyframes wedgeSlideL {
            0%, 15% { transform: translate(0px, 0px); }
            30%, 80% { transform: translate(16px, 80px); }
            90%, 100% { transform: translate(0px, 0px); }
        }

        /* 3. 右侧楔块沿斜面滑动 (dx = -0.2 * dy -> x:-16px, y:80px) */
        .anim-wedge-r { animation: wedgeSlideR var(--cycle) cubic-bezier(0.25, 0.1, 0.25, 1) infinite; }
        @keyframes wedgeSlideR {
            0%, 15% { transform: translate(0px, 0px); }
            30%, 80% { transform: translate(-16px, 80px); }
            90%, 100% { transform: translate(0px, 0px); }
        }

        /* 4. 输入力 (下拉) 显示动画 */
        .anim-f-input { animation: fInputShow var(--cycle) ease-in-out infinite; transform-origin: top center; }
        @keyframes fInputShow {
            0%, 10% { opacity: 0; transform: scaleY(0.2); }
            25%, 85% { opacity: 1; transform: scaleY(1); }
            90%, 100% { opacity: 0; transform: scaleY(0.2); }
        }

        /* 5. 夹紧力 (侧向) 放大显示动画 */
        .anim-f-clamp { animation: fClampShow var(--cycle) ease-in-out infinite; }
        .anim-f-clamp-l { transform-origin: right center; }
        .anim-f-clamp-r { transform-origin: left center; }
        @keyframes fClampShow {
            0%, 25% { opacity: 0; transform: scaleX(0.2); }
            35%, 80% { opacity: 1; transform: scaleX(1); }
            88%, 100% { opacity: 0; transform: scaleX(0.2); }
        }

        /* 6. 摩擦力/法向力 显示动画 */
        .anim-f-fric { animation: fFricShow var(--cycle) ease-in-out infinite; }
        @keyframes fFricShow {
            0%, 25% { opacity: 0; }
            35%, 80% { opacity: 0.8; }
            85%, 100% { opacity: 0; }
        }

        /* 7. 接触面应力发光 (表示自锁死死咬住) */
        .anim-stress { animation: stressGlow var(--cycle) ease-in-out infinite; }
        @keyframes stressGlow {
            0%, 28% { opacity: 0; }
            35%, 80% { opacity: 0.8; }
            85%, 100% { opacity: 0; }
        }

    </style>
</head>
<body>

    <!-- 边缘数据面板层 -->
    <div class="hud-layer">
        
        <!-- 左上:物理机制描述 -->
        <div class="hud-panel panel-tl">
            <div class="panel-title">
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path></svg>
                楔形自锁 (Wedge Effect)
            </div>
            <div class="data-row">
                <span>能量转换拓扑</span>
                <span class="val-cyan">轴向拉力 → 径向夹紧力</span>
            </div>
            <div class="data-row">
                <span>系统核心状态</span>
                <span class="val-cyan" id="ui-sys-status">待命 (STANDBY)</span>
            </div>
            <div class="desc-text">
                楔形结构利用斜面原理,将微小的轴向位移转化为巨大的侧向挤压。当输入外力(如导线自重或外界拉力)拖动楔块下滑时,受固定外壳约束,楔块被迫向内收缩收紧。
            </div>
        </div>

        <!-- 右上:遥测数据流 -->
        <div class="hud-panel panel-tr">
            <div class="panel-title">动态载荷遥测 (TELEMETRY)</div>
            <div class="data-row">
                <span>输入轴向拉力 (F_pull)</span>
                <span class="data-val val-orange" id="ui-f-input">0 N</span>
            </div>
            <div class="data-row">
                <span>输出径向夹紧力 (F_clamp)</span>
                <span class="data-val val-green" id="ui-f-clamp">0 N</span>
            </div>
            <div class="data-row">
                <span style="color:#64748B;">力学放大倍数 (M.A.)</span>
                <span class="data-val val-cyan" id="ui-ratio">1.0 x</span>
            </div>
        </div>

        <!-- 左下:自锁条件计算 -->
        <div class="hud-panel panel-bl">
            <div class="panel-title">自锁临界条件模型 (SELF-LOCK)</div>
            <div class="data-row">
                <span>外壳斜面夹角 (α)</span>
                <span class="data-val val-cyan">11.3° (Slope=0.2)</span>
            </div>
            <div class="data-row">
                <span>界面静摩擦系数 (μ)</span>
                <span class="data-val" style="color:var(--force-fric);">0.30</span>
            </div>
            <div style="background: rgba(0,0,0,0.3); padding: 8px; border-radius: 4px; margin-top: 8px; font-family: var(--font-mono); font-size: 11px; color:#CBD5E1; text-align:center;">
                条件: μ ≥ tan(α)<br>
                0.30 ≥ 0.20 &nbsp;[ <span style="color:var(--force-clamp); font-weight:bold;">条件达成</span> ]
            </div>
            <div class="desc-text">
                由于接触面的静摩擦力始终大于下滑分力,一旦咬合,无论下方受到多大的破坏性拉扯,系统均绝对不会滑脱,且<strong>“越拉越紧”</strong>。
            </div>
        </div>

    </div>

    <!-- 核心 SVG 动画区 -->
    <div class="svg-canvas">
        <svg viewBox="0 0 1000 800" preserveAspectRatio="xMidYMid meet">
            <defs>
                <!-- 发光滤镜 -->
                <filter id="glow-cyan"><feGaussianBlur stdDeviation="3" result="blur"/><feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
                <filter id="glow-orange"><feGaussianBlur stdDeviation="4" result="blur"/><feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
                
                <!-- 箭头标识 -->
                <marker id="arrow-in" 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(--force-input)" />
                </marker>
                <marker id="arrow-cl" 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(--force-clamp)" />
                </marker>
                <marker id="arrow-fr" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="5" markerHeight="5" orient="auto">
                    <path d="M 0 0 L 10 5 L 0 10 z" fill="var(--force-fric)" />
                </marker>

                <!-- 阴影剖面线 -->
                <pattern id="hatch-pattern" width="8" height="8" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse">
                    <line x1="0" y1="0" x2="0" y2="8" stroke="rgba(56, 189, 248, 0.15)" stroke-width="2" />
                </pattern>
            </defs>

            <!-- 中心坐标辅助系 -->
            <g opacity="0.3">
                <line x1="500" y1="100" x2="500" y2="700" stroke="var(--color-casing-border)" stroke-dasharray="8 8" stroke-width="1"/>
                <circle cx="500" cy="400" r="250" fill="none" stroke="var(--color-casing-border)" stroke-width="0.5"/>
            </g>

            <!-- ================= 静态外壳 (V型座) ================= -->
            <!-- 设定斜率 dx/dy = 0.2, 角度约为 11.3度 -->
            <g id="outer-casing">
                <!-- 左半壳体 -->
                <path class="geo-casing" d="M 360,150 L 420,150 L 476,430 L 360,430 Z" />
                <path d="M 360,150 L 420,150 L 476,430 L 360,430 Z" fill="url(#hatch-pattern)" />
                
                <!-- 右半壳体 -->
                <path class="geo-casing" d="M 640,150 L 580,150 L 524,430 L 640,430 Z" />
                <path d="M 640,150 L 580,150 L 524,430 L 640,430 Z" fill="url(#hatch-pattern)" />

                <!-- 角度标注 -->
                <line class="dim-line" x1="420" y1="150" x2="420" y2="280" />
                <path d="M 420,230 A 80 80 0 0 0 436,230" fill="none" stroke="var(--color-casing-border)" stroke-width="1"/>
                <text x="390" y="225" class="dim-text">α=11.3°</text>
            </g>

            <!-- ================= 动态楔块与导线 ================= -->
            <g id="dynamic-system">
                
                <!-- 导线本体 (居中,受力下沉) -->
                <!-- 初始占据 x:480~520 -->
                <g class="anim-wire" transform="translate(500, 260)">
                    <rect x="-20" y="-120" width="40" height="400" rx="4" class="geo-wire" />
                    <!-- 表面纹理 -->
                    <line x1="-8" y1="-100" x2="-8" y2="250" stroke="#94A3B8" stroke-dasharray="10 10"/>
                    <line x1="8" y1="-100" x2="8" y2="250" stroke="#94A3B8" stroke-dasharray="10 10"/>
                    
                    <!-- 输入拉力动画 (F_pull) -->
                    <g class="anim-f-input" transform="translate(0, 180)">
                        <line class="vector-arrow vec-input" x1="0" y1="0" x2="0" y2="100" marker-end="url(#arrow-in)" />
                        <text x="15" y="80" class="vector-label lbl-input">F_pull</text>
                    </g>
                </g>

                <!-- 左侧楔块 -->
                <!-- 初始内壁 x=470,下沉80px后向内移动16px,内壁达到486。与导线(边缘480)产生视觉挤压咬合 -->
                <g class="anim-wedge-l">
                    <!-- 楔形本体 -->
                    <path class="geo-wedge" d="M 420,150 L 460,150 L 460,350 L 452,350 L 412,150 Z" transform="translate(10, 0)" />
                    <!-- 橡胶防滑齿/高摩擦面 -->
                    <rect class="geo-pad" x="468" y="160" width="4" height="180" rx="2" />
                    
                    <!-- 摩擦力/法向力图示 -->
                    <g class="anim-f-fric" transform="translate(440, 250)">
                        <line class="vector-arrow vec-fric" x1="-30" y1="6" x2="20" y2="-4" marker-end="url(#arrow-fr)" />
                        <text x="-40" y="25" class="vector-label lbl-fric">F_N</text>
                        
                        <line class="vector-arrow vec-fric" x1="-10" y1="30" x2="-20" y2="-20" marker-end="url(#arrow-fr)" />
                        <text x="-35" y="-15" class="vector-label lbl-fric">f</text>
                    </g>
                </g>

                <!-- 右侧楔块 -->
                <g class="anim-wedge-r">
                    <path class="geo-wedge" d="M 580,150 L 540,150 L 540,350 L 548,350 L 588,150 Z" transform="translate(-10, 0)" />
                    <rect class="geo-pad" x="528" y="160" width="4" height="180" rx="2" />
                </g>

                <!-- ================= 应力可视化与夹紧力 (随咬合显示) ================= -->
                <!-- 左侧夹紧力 -->
                <g class="anim-f-clamp anim-f-clamp-l" transform="translate(470, 260)">
                    <line class="vector-arrow vec-clamp" x1="-120" y1="0" x2="-20" y2="0" marker-end="url(#arrow-cl)" />
                    <text x="-130" y="-12" class="vector-label lbl-clamp">F_clamp</text>
                </g>
                
                <!-- 右侧夹紧力 -->
                <g class="anim-f-clamp anim-f-clamp-r" transform="translate(530, 260)">
                    <line class="vector-arrow vec-clamp" x1="120" y1="0" x2="20" y2="0" marker-end="url(#arrow-cl)" />
                    <text x="60" y="-12" class="vector-label lbl-clamp">F_clamp</text>
                </g>

                <!-- 咬合界面的红色应力高亮 -->
                <g class="anim-stress">
                    <line class="stress-glow" x1="475" y1="260" x2="475" y2="400" />
                    <line class="stress-glow" x1="525" y1="260" x2="525" y2="400" />
                </g>

            </g>
        </svg>
    </div>

    <!-- 数据同步脚本:将 CSS 时间轴映射为 UI 数字展示 -->
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const uiInput = document.getElementById('ui-f-input');
            const uiClamp = document.getElementById('ui-f-clamp');
            const uiRatio = document.getElementById('ui-ratio');
            const uiStatus = document.getElementById('ui-sys-status');
            
            const CYCLE_MS = 8000; // 与 CSS 变量 --cycle 一致

            function updateData(timestamp) {
                // 计算 0 ~ 1 进度
                const p = (timestamp % CYCLE_MS) / CYCLE_MS;
                
                let inputForce = 0;
                let clampForce = 0;
                let statusText = "待命 (STANDBY)";
                let statusColor = "var(--color-casing-border)";

                // 状态机映射 (匹配 CSS Keyframes)
                // 0-15%: 待机
                // 15-30%: 下拉发力
                // 30-80%: 锁定/最大受力
                // 80-90%: 释放复位
                // 90-100%: 待机

                if (p > 0.15 && p <= 0.30) {
                    const ratio = (p - 0.15) / 0.15;
                    // 缓动曲线
                    const ease = 1 - Math.pow(1 - ratio, 3);
                    inputForce = ease * 1200;
                    clampForce = ease * 6000; // 放大系数约为 5x
                    statusText = "位移触发/收紧中...";
                    statusColor = "var(--force-fric)";
                } 
                else if (p > 0.30 && p <= 0.80) {
                    // 加入随机抖动模拟真实受力
                    inputForce = 1200 + Math.random() * 20;
                    clampForce = 6000 + Math.random() * 50;
                    statusText = "完全自锁 [LOCKED]";
                    statusColor = "var(--force-clamp)";
                }
                else if (p > 0.80 && p <= 0.90) {
                    const ratio = (p - 0.80) / 0.10;
                    inputForce = 1200 * (1 - ratio);
                    clampForce = 6000 * (1 - ratio);
                    statusText = "张力释放...";
                    statusColor = "var(--force-input)";
                }

                // 渲染数据
                uiInput.textContent = Math.floor(inputForce) + " N";
                uiClamp.textContent = Math.floor(clampForce) + " N";
                uiStatus.textContent = statusText;
                uiStatus.style.color = statusColor;

                // 机械增益 (Mechanical Advantage)
                if (inputForce > 50) {
                    uiRatio.textContent = (clampForce / inputForce).toFixed(1) + " x";
                } else {
                    uiRatio.textContent = "1.0 x";
                }

                requestAnimationFrame(updateData);
            }

            // 启动引擎
            requestAnimationFrame(updateData);
        });
    </script>
</body>
</html>
积分规则:第一轮对话扣减8分,后续每轮扣6分