index.html 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. <!doctype html>
  2. <html lang="zh-Hant">
  3. <head>
  4. <meta charset="utf-8" />
  5. <meta name="viewport" content="width=device-width,initial-scale=1" />
  6. <title>ASR / 翻譯 分欄顯示</title>
  7. <style>
  8. :root { --bg:#0b1020; --panel:#121833; --fg:#e7ebff; --muted:#9aa4c7; --blue:#7aa2ff; --green:#93e1a4; }
  9. * { box-sizing: border-box; }
  10. 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; }
  11. header { background:#101739; padding:10px 14px; border-bottom:1px solid #1f2650; display:flex; justify-content:space-between; align-items:center; }
  12. h1 { margin:0; font-size:16px; }
  13. .wrap { flex:1; display:grid; grid-template-columns:1fr 1fr; gap:8px; padding:8px; min-height:0; }
  14. .col { display:flex; flex-direction:column; border:1px solid #1f2650; border-radius:10px; background:var(--panel); min-height:0; }
  15. .col h2 { margin:0; padding:8px 10px; font-size:13px; border-bottom:1px solid #1f2650; }
  16. .stream { flex:1; overflow:auto; padding:10px; white-space:pre-wrap; word-break:break-word; }
  17. .asr .line::before { content:"ASR "; color:var(--blue); font-weight:700; margin-right:6px; }
  18. .trans .line::before { content:"TRANS_TW "; color:var(--green); font-weight:700; margin-right:6px; }
  19. .controls { display:flex; gap:8px; }
  20. button { background:var(--panel); color:var(--fg); border:1px solid #2a3570; border-radius:999px; padding:6px 12px; cursor:pointer; }
  21. button:hover { border-color:var(--blue); }
  22. </style>
  23. </head>
  24. <body>
  25. <header>
  26. <h1>ASR / 翻譯 分欄顯示</h1>
  27. <div class="controls">
  28. <button id="clear">清除</button>
  29. <button id="freeze">暫停自動捲動</button>
  30. </div>
  31. </header>
  32. <div class="wrap">
  33. <section class="col asr">
  34. <h2>英文 ASR</h2>
  35. <div id="asr" class="stream"></div>
  36. </section>
  37. <section class="col trans">
  38. <h2>中文 翻譯</h2>
  39. <div id="trans" class="stream"></div>
  40. </section>
  41. </div>
  42. <script>
  43. let autoScroll = true;
  44. const asrEl = document.getElementById("asr");
  45. const transEl = document.getElementById("trans");
  46. document.getElementById("clear").onclick = () => { asrEl.textContent=""; transEl.textContent=""; };
  47. document.getElementById("freeze").onclick = (e) => { autoScroll = !autoScroll; e.target.textContent = autoScroll ? "暫停自動捲動" : "恢復自動捲動"; };
  48. function connect(url, container){
  49. const es = new EventSource(url);
  50. es.onmessage = (e) => {
  51. const text = (e.data || "").replaceAll("\\\\n","\\n");
  52. const div = document.createElement("div");
  53. div.className = "line";
  54. div.textContent = text;
  55. container.appendChild(div);
  56. if (autoScroll) container.scrollTop = container.scrollHeight;
  57. };
  58. es.onerror = () => {
  59. const div = document.createElement("div");
  60. div.className="line";
  61. div.style.color="#ff9b9b";
  62. div.textContent="[連線中斷,稍後自動重試]";
  63. container.appendChild(div);
  64. };
  65. }
  66. connect("/stream/asr", asrEl);
  67. connect("/stream/trans", transEl);
  68. </script>
  69. </body>
  70. </html>