test.html 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. <!DOCTYPE html>
  2. <html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
  3. <title>药典AI 连接测试</title>
  4. <style>
  5. body{font-family:sans-serif;padding:20px;max-width:800px;margin:0 auto}
  6. h3{color:#002FA7}
  7. #log{background:#f5f5f5;padding:12px;border-radius:8px;margin-top:12px;font-size:13px;white-space:pre-wrap;min-height:120px;max-height:400px;overflow-y:auto}
  8. .status{font-size:12px;color:#666;margin-top:8px}
  9. button{padding:8px 16px;background:#002FA7;color:#fff;border:none;border-radius:6px;cursor:pointer;margin-left:8px}
  10. button:hover{background:#001a5c}
  11. input{padding:8px;width:60%;border:1px solid #ccc;border-radius:6px}
  12. </style>
  13. </head><body>
  14. <h3>药典AI 连接测试</h3>
  15. <div>
  16. <input id="apiBase" placeholder="API 地址" value="http://localhost:9000" style="width:40%">
  17. <input id="q" placeholder="输入问题" style="width:40%">
  18. <button onclick="go()">发送</button>
  19. </div>
  20. <div class="status" id="status">点击发送将自动获取 Token 并发起 SSE 流式对话</div>
  21. <div id="log">等待输入...</div>
  22. <script>
  23. let TOKEN = '';
  24. async function fetchToken(apiBase) {
  25. // 通过 /api/v1/auth/guest 获取游客 Token
  26. const r = await fetch(apiBase + '/api/v1/auth/guest', {
  27. method: 'POST',
  28. headers: {'Content-Type': 'application/json'},
  29. body: JSON.stringify({})
  30. });
  31. if (!r.ok) throw new Error('获取 Token 失败: HTTP ' + r.status);
  32. const d = await r.json();
  33. if (!d.access_token && !d.token) throw new Error('返回中无 token 字段');
  34. return d.access_token || d.token;
  35. }
  36. function log(m) {
  37. const el = document.getElementById('log');
  38. el.textContent += m + '\n';
  39. el.scrollTop = el.scrollHeight;
  40. }
  41. async function go() {
  42. const apiBase = document.getElementById('apiBase').value.trim().replace(/\/$/, '');
  43. const q = document.getElementById('q').value.trim();
  44. if (!q) return;
  45. document.getElementById('log').textContent = '';
  46. // 1. 获取 Token(首次或过期时)
  47. if (!TOKEN) {
  48. log('获取 Token 中...');
  49. try {
  50. TOKEN = await fetchToken(apiBase);
  51. log('Token 获取成功');
  52. } catch (e) {
  53. log('Token 获取失败: ' + e.message);
  54. return;
  55. }
  56. }
  57. log('发送: ' + q);
  58. try {
  59. const r = await fetch(apiBase + '/api/v1/chat/stream', {
  60. method: 'POST',
  61. headers: {
  62. 'Content-Type': 'application/json',
  63. 'Accept': 'text/event-stream',
  64. 'Authorization': 'Bearer ' + TOKEN
  65. },
  66. body: JSON.stringify({message: q})
  67. });
  68. if (r.status === 401) {
  69. log('Token 已过期,重新获取...');
  70. TOKEN = '';
  71. return go();
  72. }
  73. if (!r.ok) throw new Error('HTTP ' + r.status);
  74. log('连接成功,开始接收...');
  75. const reader = r.body.getReader();
  76. const d = new TextDecoder();
  77. let buf = '', txt = '';
  78. let curEvent = 'content';
  79. while (true) {
  80. const {value, done} = await reader.read();
  81. if (done) break;
  82. buf += d.decode(value, {stream: true});
  83. const lines = buf.split('\n');
  84. buf = lines.pop() || '';
  85. for (const l of lines) {
  86. if (l.indexOf('event:') === 0) { curEvent = l.substring(6).trim(); continue; }
  87. if (l.indexOf('data:') !== 0) continue;
  88. let v = l.slice(5);
  89. if (v.startsWith(' ')) v = v.substring(1);
  90. if (v === '[DONE]') { log('\n[DONE]'); continue; }
  91. if (curEvent === 'intent') { log('[intent] ' + v); }
  92. else if (curEvent === 'status') { log('[status] ' + v); }
  93. else if (curEvent === 'meta') { log('[meta] ' + v); }
  94. else {
  95. txt += v;
  96. document.getElementById('log').textContent = '接收中...\n' + txt.slice(-500);
  97. }
  98. }
  99. }
  100. log('\n完成');
  101. } catch (e) {
  102. log('错误: ' + e.message);
  103. }
  104. }
  105. </script></body></html>