1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 |
- <!doctype html>
- <html lang="zh-Hant">
- <head>
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width,initial-scale=1" />
- <title>ASR / 翻譯 分欄顯示</title>
- <style>
- :root { --bg:#0b1020; --panel:#121833; --fg:#e7ebff; --muted:#9aa4c7; --blue:#7aa2ff; --green:#93e1a4; }
- * { box-sizing: border-box; }
- body { margin:0; background:var(--bg); color:var(--fg); font:14px/1.5 ui-monospace, SFMono-Regular, Menlo, Consolas, "Noto Sans TC", monospace; height:100vh; display:flex; flex-direction:column; }
- header { background:#101739; padding:10px 14px; border-bottom:1px solid #1f2650; display:flex; justify-content:space-between; align-items:center; }
- h1 { margin:0; font-size:16px; }
- .wrap { flex:1; display:grid; grid-template-columns:1fr 1fr; gap:8px; padding:8px; min-height:0; }
- .col { display:flex; flex-direction:column; border:1px solid #1f2650; border-radius:10px; background:var(--panel); min-height:0; }
- .col h2 { margin:0; padding:8px 10px; font-size:13px; border-bottom:1px solid #1f2650; }
- .stream { flex:1; overflow:auto; padding:10px; white-space:pre-wrap; word-break:break-word; }
- .asr .line::before { content:"ASR "; color:var(--blue); font-weight:700; margin-right:6px; }
- .trans .line::before { content:"TRANS_TW "; color:var(--green); font-weight:700; margin-right:6px; }
- .controls { display:flex; gap:8px; }
- button { background:var(--panel); color:var(--fg); border:1px solid #2a3570; border-radius:999px; padding:6px 12px; cursor:pointer; }
- button:hover { border-color:var(--blue); }
- </style>
- </head>
- <body>
- <header>
- <h1>ASR / 翻譯 分欄顯示</h1>
- <div class="controls">
- <button id="clear">清除</button>
- <button id="freeze">暫停自動捲動</button>
- </div>
- </header>
- <div class="wrap">
- <section class="col asr">
- <h2>英文 ASR</h2>
- <div id="asr" class="stream"></div>
- </section>
- <section class="col trans">
- <h2>中文 翻譯</h2>
- <div id="trans" class="stream"></div>
- </section>
- </div>
- <script>
- let autoScroll = true;
- const asrEl = document.getElementById("asr");
- const transEl = document.getElementById("trans");
- document.getElementById("clear").onclick = () => { asrEl.textContent=""; transEl.textContent=""; };
- document.getElementById("freeze").onclick = (e) => { autoScroll = !autoScroll; e.target.textContent = autoScroll ? "暫停自動捲動" : "恢復自動捲動"; };
- function connect(url, container){
- const es = new EventSource(url);
- es.onmessage = (e) => {
- const text = (e.data || "").replaceAll("\\\\n","\\n");
- const div = document.createElement("div");
- div.className = "line";
- div.textContent = text;
- container.appendChild(div);
- if (autoScroll) container.scrollTop = container.scrollHeight;
- };
- es.onerror = () => {
- const div = document.createElement("div");
- div.className="line";
- div.style.color="#ff9b9b";
- div.textContent="[連線中斷,稍後自動重試]";
- container.appendChild(div);
- };
- }
- connect("/stream/asr", asrEl);
- connect("/stream/trans", transEl);
- </script>
- </body>
- </html>
|