5FNe.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>Fursuit Pro V1.0</title>
<style>
    :root { --bg: #f5f7fa; --card: #ffffff; --text: #333333; --accent: #81c784; --border: #e0e0e0; --btn-bg: #eef2f5; --danger: #ff9999; }
    [data-theme="dark"] { --bg: #12171f; --card: #1e2733; --text: #e0e0e0; --accent: #a5d6a7; --border: #2d3b4a; --btn-bg: #263340; }
    body { font-family: -apple-system, sans-serif; background: var(--bg); color: var(--text); margin: 0; padding: 12px; display: flex; flex-direction: column; align-items: center; transition: 0.3s; }
    .container { width: 100%; max-width: 420px; }
    .top-bar { display: flex; justify-content: space-between; margin-bottom: 12px; width: 100%; }
    .mini-btn { padding: 6px 12px; border-radius: 10px; border: 1px solid var(--border); background: var(--card); color: var(--text); font-size: 13px; }
    .mini-btn.active { background: var(--accent); color: #fff; }
    .card { background: var(--card); border: 1px solid var(--border); padding: 16px; border-radius: 20px; margin-bottom: 12px; box-shadow: 0 3px 8px rgba(0,0,0,0.08); }
    h2 { font-size: 1rem; margin: 0 0 12px 0; border-left: 4px solid var(--accent); padding-left: 10px; }
    button { width: 100%; padding: 14px; border: none; border-radius: 14px; font-weight: bold; font-size: 1rem; cursor: pointer; background: var(--btn-bg); color: var(--text); margin-bottom: 8px; }
    .grid-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px; }
    input[type=range] { width: 100%; height: 8px; margin: 12px 0; accent-color: var(--accent); border-radius: 4px; }
    .btn-lock { background: #fff0f0 !important; color: var(--danger) !important; border: 1px solid #ffcccc !important; }
    .btn-unlock { background: var(--accent) !important; color: #fff !important; margin-top: 12px; }
    #status { font-size: 13px; text-align: center; margin-bottom: 6px; font-weight: bold; }
    .ir-list { font-size: 0.9rem; line-height: 1.9; padding-left: 10px; }
</style>
</head>
<body data-theme="dark">
<div class="container">
    <div class="top-bar">
        <div class="lang-group">
            <button class="mini-btn active" onclick="setLang('zh')">中</button>
            <button class="mini-btn" onclick="setLang('en')">EN</button>
            <button class="mini-btn" onclick="setLang('jp')">日</button>
        </div>
        <div class="theme-group">
            <button class="mini-btn" onclick="setTheme('light')">☀️</button>
            <button class="mini-btn active" onclick="setTheme('dark')">🌙</button>
        </div>
    </div>

    <div class="card" style="text-align:center;">
        <h1 style="font-size:1.3rem; margin:0; color:var(--accent);">FUYI PRO V1.0</h1>
        <div id="status" style="color:var(--danger);">OFFLINE</div>
        <button id="btn-connect" onclick="connectBLE()" style="background:var(--accent); color:#fff; font-size:1.1rem;">🔌 连接设备</button>
    </div>

    <div id="panel" style="opacity: 0.3; pointer-events: none;">
        <div class="card">
            <h2 id="t-angle">实时角度 <span id="realAngle" style="font-weight:bold; color:var(--accent);">90°</span></h2>
            <input type="range" min="40" max="90" value="90" oninput="document.getElementById('realAngle').innerText=this.value+'°'" onchange="send('ANG', this.value)">
            <div class="grid-3">
                <button onclick="send('BLINK', 1)" id="t-lfast">左快眨</button>
                <button onclick="send('BLINK', 0)" id="t-dfast">双快眨</button>
                <button onclick="send('BLINK', 2)" id="t-rfast">右快眨</button>
            </div>
        </div>

        <div class="card">
            <div style="display:flex; justify-content:space-between; align-items:center;">
                <h2 id="t-auto" style="margin:0;">自动眨眼</h2>
                <input type="checkbox" style="width:28px; height:28px; accent-color:var(--accent);" onchange="send('AUTO', this.checked?1:0)">
            </div>
            <input type="range" min="1000" max="10000" step="500" value="4000" onchange="send('AUTODUR', this.value)">
        </div>

        <div class="card">
            <h2 id="t-locktitle">拍照定格锁定</h2>
            <div class="grid-3">
                <button class="btn-lock" onclick="send('CLOSE', 1)" id="t-lockl">仅锁左眼</button>
                <button class="btn-lock" onclick="send('CLOSE', 0)" id="t-lockd">全闭锁定</button>
                <button class="btn-lock" onclick="send('CLOSE', 2)" id="t-lockr">仅锁右眼</button>
            </div>
            <button class="btn-unlock" onclick="send('OPEN', 0)" id="t-unlock">解除锁定</button>
        </div>

        <div class="card">
            <h2 id="t-slowtitle">慢动作眨眼 <span id="durVal" style="color:var(--accent);">0.5s</span></h2>
            <input type="range" min="500" max="3000" step="100" value="500" oninput="document.getElementById('durVal').innerText=(this.value/1000).toFixed(1)+'s'" onchange="send('DUR', this.value)">
            <div class="grid-3">
                <button onclick="send('SLOW', 1)" id="t-lslow">左慢眨</button>
                <button onclick="send('SLOW', 0)" id="t-dslow">双慢眨</button>
                <button onclick="send('SLOW', 2)" id="t-rslow">右慢眨</button>
            </div>
        </div>

        <!-- 遥控器教程(更新OK键说明) -->
        <div class="card">
            <h2 id="t-irtitle">遥控器按键指南</h2>
            <div class="ir-list" id="t-irlist">
                1键 → 左眼快速眨眼<br>
                2键 → 双眼快速眨眼<br>
                3键 → 右眼快速眨眼<br>
                4键 → 左眼慢眨<br>
                5键 → 双眼慢眨<br>
                6键 → 右眼慢眨<br>
                上键 → 双眼全闭锁定<br>
                下键 → 解除所有锁定(快速睁眼)<br>
                左键 → 仅锁左眼<br>
                右键 → 仅锁右眼<br>
                OK键 → 开启自动眨眼(默认4秒)<br>
                &nbsp;&nbsp;&nbsp;&nbsp;连续按可循环切换间隔:2秒 → 4秒 → 6秒 → 8秒<br>
                &nbsp;&nbsp;&nbsp;&nbsp;(关闭自动眨眼请用网页开关)
            </div>
        </div>
    </div>
</div>

<script>
    const S_UUID = "4fafc201-1fb5-459e-8fcc-c5c9c331914b";
    const C_UUID = "beb5483e-36e1-4688-b7f5-ea07361b26a8";
    let bC;
    
    const i18n = {
        zh: { 
            angle: "实时角度", lfast: "左快眨", dfast: "双快眨", rfast: "右快眨", 
            auto: "自动眨眼", locktitle: "拍照定格锁定", lockl: "仅锁左眼", lockd: "全闭锁定", lockr: "仅锁右眼", unlock: "解除锁定", 
            slow: "慢动作眨眼", lslow: "左慢眨", dslow: "双慢眨", rslow: "右慢眨", 
            conn: "🔌 连接设备", irtitle: "遥控器按键指南",
            irlist: "1键 → 左眼快速眨眼\n2键 → 双眼快速眨眼\n3键 → 右眼快速眨眼\n4键 → 左眼慢眨\n5键 → 双眼慢眨\n6键 → 右眼慢眨\n上键 → 双眼全闭锁定\n下键 → 解除所有锁定(快速睁眼)\n左键 → 仅锁左眼\n右键 → 仅锁右眼\nOK键 → 开启自动眨眼(默认4秒)\n    连续按可循环切换间隔:2秒 → 4秒 → 6秒 → 8秒\n    (关闭自动眨眼请用网页开关)"
        },
        en: { 
            angle: "Real-time Angle", lfast: "Left Fast", dfast: "Both Fast", rfast: "Right Fast", 
            auto: "Auto Blink", locktitle: "Pose Lock", lockl: "Lock Left", lockd: "Lock Both", lockr: "Lock Right", unlock: "Release", 
            slow: "Slow Motion", lslow: "Left Slow", dslow: "Both Slow", rslow: "Right Slow", 
            conn: "🔌 CONNECT", irtitle: "Remote Guide",
            irlist: "1 key → Left Fast Blink\n2 key → Both Fast Blink\n3 key → Right Fast Blink\n4 key → Left Slow\n5 key → Both Slow\n6 key → Right Slow\nUp key → Lock Both Closed\nDown key → Release Lock\nLeft key → Lock Left Only\nRight key → Lock Right Only\nOK key → Turn On Auto Blink (default 4s)\n    Press repeatedly to cycle interval: 2s → 4s → 6s → 8s\n    (Turn off only via web switch)"
        },
        jp: { 
            angle: "リアルタイム角度", lfast: "左速眨", dfast: "両速眨", rfast: "右速眨", 
            auto: "自動眨眼", locktitle: "ポーズ固定", lockl: "左のみ固定", lockd: "全閉固定", lockr: "右のみ固定", unlock: "解除", 
            slow: "スローモーション", lslow: "左スロー", dslow: "両スロー", rslow: "右スロー", 
            conn: "🔌 接続", irtitle: "リモコンガイド",
            irlist: "1キー → 左速まばたき\n2キー → 両目速まばたき\n3キー → 右速まばたき\n4キー → 左スロー\n5キー → 両目スロー\n6キー → 右スロー\n上キー → 両目全閉\n下キー → 全解除\n左キー → 左のみ固定\n右キー → 右のみ固定\nOKキー → 自動眨眼をオン(デフォルト4秒)\n    連続押して間隔切替:2秒 → 4秒 → 6秒 → 8秒\n    (オフはウェブスイッチのみ)"
        }
    };
    
    function setLang(l) {
        const d = i18n[l];
        document.getElementById('t-angle').childNodes[0].textContent = d.angle + " ";
        document.getElementById('t-lfast').innerText = d.lfast;
        document.getElementById('t-dfast').innerText = d.dfast;
        document.getElementById('t-rfast').innerText = d.rfast;
        document.getElementById('t-auto').innerText = d.auto;
        document.getElementById('t-locktitle').innerText = d.locktitle;
        document.getElementById('t-lockl').innerText = d.lockl;
        document.getElementById('t-lockd').innerText = d.lockd;
        document.getElementById('t-lockr').innerText = d.lockr;
        document.getElementById('t-unlock').innerText = d.unlock;
        document.getElementById('t-slowtitle').childNodes[0].textContent = d.slow + " ";
        document.getElementById('t-lslow').innerText = d.lslow;
        document.getElementById('t-dslow').innerText = d.dslow;
        document.getElementById('t-rslow').innerText = d.rslow;
        document.getElementById('btn-connect').innerText = d.conn;
        document.getElementById('t-irtitle').innerText = d.irtitle;
        document.getElementById('t-irlist').innerHTML = d.irlist.replace(/\n/g, '<br>').replace(/    /g, '&nbsp;&nbsp;&nbsp;&nbsp;');
    }
    
    function setTheme(t) { document.body.setAttribute('data-theme', t); }
    
    async function connectBLE() {
        try {
            const d = await navigator.bluetooth.requestDevice({ filters: [{ name: 'Fursuit-Pro-V1.0' }], optionalServices: [S_UUID] });
            const s = await d.gatt.connect();
            const sv = await s.getPrimaryService(S_UUID);
            bC = await sv.getCharacteristic(C_UUID);
            document.getElementById('status').innerText = "ONLINE";
            document.getElementById('status').style.color = "#a5d6a7";
            document.getElementById('panel').style.opacity = "1";
            document.getElementById('panel').style.pointerEvents = "auto";
        } catch (e) { alert("连接失败"); }
    }
    
    function send(c, v) { 
        if (bC) bC.writeValue(new TextEncoder().encode(c + ":" + v)); 
        if (navigator.vibrate) navigator.vibrate(30); 
    }
</script>
</body>
</html>
Download
pasted.sh