<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebSocket 验证测试</title>
    <style>
        * { box-sizing: border-box; }
        body {
            font-family: "SF Mono", "Monaco", "Consolas", monospace;
            max-width: 900px;
            margin: 20px auto;
            padding: 0 16px;
            background: #1a1b26;
            color: #a9b1d6;
            min-height: 100vh;
        }
        h1 {
            color: #7aa2f7;
            font-size: 1.4rem;
            margin-bottom: 8px;
        }
        .hint {
            font-size: 12px;
            color: #565f89;
            margin-bottom: 16px;
            line-height: 1.5;
        }
        .panel {
            background: #24283b;
            border-radius: 8px;
            padding: 16px;
            margin-bottom: 16px;
        }
        .panel-title {
            color: #7dcfff;
            font-size: 13px;
            margin-bottom: 10px;
            font-weight: 600;
        }
        label {
            display: block;
            font-size: 12px;
            color: #9ece6a;
            margin-bottom: 4px;
        }
        input[type="text"], input[type="number"] {
            width: 100%;
            padding: 10px 12px;
            margin-bottom: 12px;
            border: 1px solid #3b4261;
            border-radius: 6px;
            background: #1a1b26;
            color: #c0caf5;
            font-size: 13px;
        }
        input:focus {
            outline: none;
            border-color: #7aa2f7;
        }
        .row {
            display: flex;
            gap: 12px;
            flex-wrap: wrap;
            align-items: center;
            margin-bottom: 12px;
        }
        .btn {
            padding: 10px 20px;
            border: none;
            border-radius: 6px;
            font-size: 13px;
            cursor: pointer;
            font-weight: 500;
        }
        .btn-connect {
            background: #9ece6a;
            color: #1a1b26;
        }
        .btn-connect:hover { background: #b9f27c; }
        .btn-connect:disabled {
            background: #3b4261;
            color: #565f89;
            cursor: not-allowed;
        }
        .btn-send {
            background: #7aa2f7;
            color: #1a1b26;
        }
        .btn-send:hover { background: #89b4fa; }
        .btn-send:disabled {
            background: #3b4261;
            color: #565f89;
            cursor: not-allowed;
        }
        .btn-close {
            background: #f7768e;
            color: #1a1b26;
        }
        .btn-close:hover { background: #ff9e9e; }
        .btn-close:disabled {
            background: #3b4261;
            color: #565f89;
            cursor: not-allowed;
        }
        .btn-clear {
            background: #565f89;
            color: #c0caf5;
        }
        .btn-clear:hover { background: #6b7a9e; }
        .status {
            display: inline-block;
            padding: 4px 10px;
            border-radius: 4px;
            font-size: 12px;
            margin-left: 8px;
        }
        .status.closed { background: #3b4261; color: #565f89; }
        .status.connecting { background: #e0af68; color: #1a1b26; }
        .status.open { background: #9ece6a; color: #1a1b26; }
        .status.error { background: #f7768e; color: #1a1b26; }
        .message-box {
            height: 320px;
            border: 1px solid #3b4261;
            border-radius: 6px;
            background: #1a1b26;
            padding: 12px;
            overflow-y: auto;
            font-size: 12px;
            line-height: 1.6;
        }
        .message-box .line {
            margin-bottom: 8px;
            padding: 6px 8px;
            border-radius: 4px;
            word-break: break-all;
        }
        .message-box .line.time { color: #565f89; font-size: 11px; }
        .message-box .line.sys { color: #7dcfff; }
        .message-box .line.send { color: #9ece6a; background: rgba(158, 206, 106, 0.12); }
        .message-box .line.recv { color: #bb9af7; background: rgba(187, 154, 247, 0.12); }
        .message-box .line.err { color: #f7768e; background: rgba(247, 118, 142, 0.12); }
        textarea {
            width: 100%;
            min-height: 80px;
            padding: 10px 12px;
            border: 1px solid #3b4261;
            border-radius: 6px;
            background: #1a1b26;
            color: #c0caf5;
            font-size: 12px;
            resize: vertical;
            margin-bottom: 10px;
        }
        .ws-url {
            font-size: 11px;
            color: #565f89;
            word-break: break-all;
            margin-top: 8px;
        }
    </style>
</head>
<body>
    <h1>WebSocket 验证测试</h1>
    <p class="hint">
        用于验证 <code>/ws/base/&lt;service_uid&gt;/&lt;nid&gt;/</code> 连接。
        service_uid 请填写登录接口返回的 <strong>access</strong>（JWT），nid 为设备 ID（整数，默认 0）。
    </p>

    <div class="panel">
        <div class="panel-title">连接参数 <span id="statusLabel" class="status closed">未连接</span></div>
        <label>JWT Token（登录后的 access）</label>
        <input type="text" id="token" placeholder="粘贴 access token" value="">
        <label>设备 ID (nid)</label>
        <input type="number" id="nid" placeholder="0" value="0" min="0">
        <div class="row">
            <button type="button" class="btn btn-connect" id="btnConnect">连接</button>
            <button type="button" class="btn btn-close" id="btnClose" disabled>关闭连接</button>
        </div>
        <div class="ws-url" id="wsUrl">—</div>
    </div>

    <div class="panel">
        <div class="panel-title">消息记录</div>
        <div class="message-box" id="messageBox"></div>
        <div class="row" style="margin-top: 10px;">
            <button type="button" class="btn btn-clear" id="btnClear">清空</button>
        </div>
    </div>

    <div class="panel">
        <div class="panel-title">发送消息</div>
        <label>发送文本（服务端 receive 接收原始文本，推送为 JSON）</label>
        <textarea id="txt" placeholder='可发送任意文本或 JSON，例如: {"content":"测试","message_id":1}'>{"content":"测试","message_id":1}</textarea>
        <button type="button" class="btn btn-send" id="btnSend" disabled>发送</button>
    </div>

    <script>
        (function () {
            var socket = null;
            var messageBox = document.getElementById("messageBox");
            var statusLabel = document.getElementById("statusLabel");
            var tokenInput = document.getElementById("token");
            var nidInput = document.getElementById("nid");
            var txtInput = document.getElementById("txt");
            var wsUrlEl = document.getElementById("wsUrl");
            var btnConnect = document.getElementById("btnConnect");
            var btnClose = document.getElementById("btnClose");
            var btnSend = document.getElementById("btnSend");
            var btnClear = document.getElementById("btnClear");

            function setStatus(klass, text) {
                statusLabel.className = "status " + klass;
                statusLabel.textContent = text;
            }

            function addLog(type, text) {
                var line = document.createElement("div");
                line.className = "line " + type;
                var time = new Date().toLocaleTimeString("zh-CN", { hour12: false });
                line.innerHTML = "<span class=\"time\">[" + time + "]</span> " + (type === "err" ? "错误: " : "") + escapeHtml(text);
                messageBox.appendChild(line);
                messageBox.scrollTop = messageBox.scrollHeight;
            }

            function escapeHtml(s) {
                var div = document.createElement("div");
                div.textContent = s;
                return div.innerHTML;
            }

            function getWsBaseUrl() {
                var protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
                var host = window.location.host;
                return protocol + "//" + host;
            }

            function connect() {
                var token = (tokenInput.value || "").trim();
                var nid = parseInt(nidInput.value, 10) || 0;
                if (!token) {
                    addLog("err", "请先填写 JWT Token（登录后的 access）");
                    return;
                }
                if (socket && socket.readyState === WebSocket.OPEN) {
                    addLog("sys", "当前已连接，请先关闭再重连");
                    return;
                }

                var base = getWsBaseUrl();
                var url = base + "/ws/base/" + encodeURIComponent(token) + "/" + nid + "/";
                wsUrlEl.textContent = url;

                setStatus("connecting", "连接中…");
                btnConnect.disabled = true;
                addLog("sys", "正在连接: " + url);

                socket = new WebSocket(url);

                socket.onopen = function () {
                    setStatus("open", "已连接");
                    btnConnect.disabled = true;
                    btnClose.disabled = false;
                    btnSend.disabled = false;
                    addLog("sys", "连接成功");
                };

                socket.onmessage = function (event) {
                    var data = event.data;
                    try {
                        var parsed = JSON.parse(data);
                        data = JSON.stringify(parsed, null, 2);
                    } catch (e) {}
                    addLog("recv", data);
                };

                socket.onclose = function (event) {
                    setStatus("closed", "已断开");
                    btnConnect.disabled = false;
                    btnClose.disabled = true;
                    btnSend.disabled = true;
                    socket = null;
                    addLog("sys", "连接已关闭" + (event.code ? " (code: " + event.code + (event.reason ? ", " + event.reason : "") + ")" : ""));
                };

                socket.onerror = function () {
                    setStatus("error", "错误");
                    addLog("err", "WebSocket 发生错误，请检查 Token 与网络");
                };
            }

            function closeConn() {
                if (socket) {
                    socket.close();
                    socket = null;
                }
            }

            function sendMessage() {
                if (!socket || socket.readyState !== WebSocket.OPEN) {
                    addLog("err", "未连接，无法发送");
                    return;
                }
                var text = txtInput.value;
                socket.send(text);
                addLog("send", text);
            }

            function clearLog() {
                messageBox.innerHTML = "";
            }

            btnConnect.addEventListener("click", connect);
            btnClose.addEventListener("click", closeConn);
            btnSend.addEventListener("click", sendMessage);
            btnClear.addEventListener("click", clearLog);

            // 页面加载时显示将使用的 WS 基础地址
            wsUrlEl.textContent = "连接后将显示: " + getWsBaseUrl() + "/ws/base/<token>/<nid>/";
        })();
    </script>
</body>
</html>
