| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- <!DOCTYPE html>
- <html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
- <title>药典AI 连接测试</title>
- <style>
- body{font-family:sans-serif;padding:20px;max-width:800px;margin:0 auto}
- h3{color:#002FA7}
- #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}
- .status{font-size:12px;color:#666;margin-top:8px}
- button{padding:8px 16px;background:#002FA7;color:#fff;border:none;border-radius:6px;cursor:pointer;margin-left:8px}
- button:hover{background:#001a5c}
- input{padding:8px;width:60%;border:1px solid #ccc;border-radius:6px}
- </style>
- </head><body>
- <h3>药典AI 连接测试</h3>
- <div>
- <input id="apiBase" placeholder="API 地址" value="http://localhost:9000" style="width:40%">
- <input id="q" placeholder="输入问题" style="width:40%">
- <button onclick="go()">发送</button>
- </div>
- <div class="status" id="status">点击发送将自动获取 Token 并发起 SSE 流式对话</div>
- <div id="log">等待输入...</div>
- <script>
- let TOKEN = '';
- async function fetchToken(apiBase) {
- // 通过 /api/v1/auth/guest 获取游客 Token
- const r = await fetch(apiBase + '/api/v1/auth/guest', {
- method: 'POST',
- headers: {'Content-Type': 'application/json'},
- body: JSON.stringify({})
- });
- if (!r.ok) throw new Error('获取 Token 失败: HTTP ' + r.status);
- const d = await r.json();
- if (!d.access_token && !d.token) throw new Error('返回中无 token 字段');
- return d.access_token || d.token;
- }
- function log(m) {
- const el = document.getElementById('log');
- el.textContent += m + '\n';
- el.scrollTop = el.scrollHeight;
- }
- async function go() {
- const apiBase = document.getElementById('apiBase').value.trim().replace(/\/$/, '');
- const q = document.getElementById('q').value.trim();
- if (!q) return;
- document.getElementById('log').textContent = '';
- // 1. 获取 Token(首次或过期时)
- if (!TOKEN) {
- log('获取 Token 中...');
- try {
- TOKEN = await fetchToken(apiBase);
- log('Token 获取成功');
- } catch (e) {
- log('Token 获取失败: ' + e.message);
- return;
- }
- }
- log('发送: ' + q);
- try {
- const r = await fetch(apiBase + '/api/v1/chat/stream', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'Accept': 'text/event-stream',
- 'Authorization': 'Bearer ' + TOKEN
- },
- body: JSON.stringify({message: q})
- });
- if (r.status === 401) {
- log('Token 已过期,重新获取...');
- TOKEN = '';
- return go();
- }
- if (!r.ok) throw new Error('HTTP ' + r.status);
- log('连接成功,开始接收...');
- const reader = r.body.getReader();
- const d = new TextDecoder();
- let buf = '', txt = '';
- let curEvent = 'content';
- while (true) {
- const {value, done} = await reader.read();
- if (done) break;
- buf += d.decode(value, {stream: true});
- const lines = buf.split('\n');
- buf = lines.pop() || '';
- for (const l of lines) {
- if (l.indexOf('event:') === 0) { curEvent = l.substring(6).trim(); continue; }
- if (l.indexOf('data:') !== 0) continue;
- let v = l.slice(5);
- if (v.startsWith(' ')) v = v.substring(1);
- if (v === '[DONE]') { log('\n[DONE]'); continue; }
- if (curEvent === 'intent') { log('[intent] ' + v); }
- else if (curEvent === 'status') { log('[status] ' + v); }
- else if (curEvent === 'meta') { log('[meta] ' + v); }
- else {
- txt += v;
- document.getElementById('log').textContent = '接收中...\n' + txt.slice(-500);
- }
- }
- }
- log('\n完成');
- } catch (e) {
- log('错误: ' + e.message);
- }
- }
- </script></body></html>
|