Skip to content

Commit 87e9899

Browse files
authored
Update index.html
1 parent 4d49c4f commit 87e9899

1 file changed

Lines changed: 106 additions & 4 deletions

File tree

‎app/views/index.html‎

Lines changed: 106 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,14 @@
103103
.artifact { display:inline-flex; align-items:center; gap:6px; background:var(--panel); border:1px solid var(--line); border-radius:999px; padding:5px 14px; font-size:13px; text-decoration:none; color:var(--fg); box-shadow:var(--shadow); }
104104
.artifact:hover { border-color:var(--accent); color:var(--accent); }
105105
.artifact .size { color:var(--muted); font-size:11px; }
106+
#runStatus { margin:10px 0 0; font-size:13px; color:var(--muted); display:flex; align-items:center; gap:8px; }
107+
#runStatus .spin { display:inline-block; animation:spin 1s linear infinite; }
108+
@keyframes spin { to { transform: rotate(360deg); } }
109+
#todoPanel { margin:10px 0 0; background:var(--panel); border:1px solid var(--line); border-radius:12px; box-shadow:var(--shadow); padding:10px 14px; }
110+
#todoPanel .t-title { font-size:12px; color:var(--muted); margin-bottom:6px; font-weight:600; }
111+
#todoPanel .t-item { font-size:13px; padding:2px 0; display:flex; gap:8px; align-items:baseline; }
112+
#todoPanel .t-item.done { color:var(--muted); text-decoration:line-through; }
113+
#todoPanel .t-item.doing { color:var(--accent); font-weight:600; }
106114
html[data-theme="dark"] .msg pre { background:rgba(255,255,255,.06); }
107115

108116
/* ---------- auth ---------- */
@@ -172,6 +180,8 @@ <h1>一句话处理 Excel 表格</h1>
172180
</div>
173181
</div>
174182
<div id="chat">
183+
<div id="runStatus" style="display:none"></div>
184+
<div id="todoPanel" style="display:none"></div>
175185
<div id="messages"></div>
176186
<div id="artifacts" style="display:none">
177187
<div style="font-size:13px;color:var(--muted);margin:8px 0 6px">📦 生成的文件(点击下载)</div>
@@ -297,6 +307,8 @@ <h1>一句话处理 Excel 表格</h1>
297307
if (es) { es.close(); es = null; }
298308
pendingFiles = [];
299309
renderFiles();
310+
setRunStatus('', false);
311+
renderTodos(null);
300312
$('artifacts').style.display = 'none';
301313
$('promptBox').value = ''; $('charCount').textContent = '0';
302314
$('home').style.display = 'block'; $('chat').style.display = 'none';
@@ -312,6 +324,8 @@ <h1>一句话处理 Excel 表格</h1>
312324
currentConv = id;
313325
if (es) { es.close(); es = null; }
314326
currentRun = null;
327+
setRunStatus('', false);
328+
renderTodos(null);
315329
const res = await api.req('/conversations/' + id);
316330
const detail = await res.json();
317331
pendingFiles = detail.files || [];
@@ -446,9 +460,79 @@ <h1>一句话处理 Excel 表格</h1>
446460
return frag;
447461
}
448462

463+
function addAsk(data, runId) {
464+
const div = document.createElement('div');
465+
div.className = 'msg agent';
466+
const questions = (data && data.questions) || [];
467+
div.innerHTML = '<div class="who">AI 提问</div>';
468+
for (const q of questions) {
469+
const qtext = q.question || q.text || JSON.stringify(q);
470+
const opts = q.options || [];
471+
const row = document.createElement('div');
472+
row.style.margin = '8px 0';
473+
row.innerHTML = `<div>${escapeHtml(qtext)}</div>`;
474+
const input = document.createElement('input');
475+
input.style.cssText = 'width:100%;margin-top:6px;background:var(--bg);border:1px solid var(--line);border-radius:8px;padding:8px;color:var(--fg)';
476+
input.placeholder = opts.length ? '选择或输入…' : '输入回答…';
477+
row.appendChild(input);
478+
div.appendChild(row);
479+
if (opts.length) {
480+
for (const o of opts) {
481+
const label = typeof o === 'string' ? o : (o.label || JSON.stringify(o));
482+
const b = document.createElement('button');
483+
b.className = 'attach-btn'; b.style.margin = '0 6px 6px 0';
484+
b.textContent = label;
485+
b.onclick = () => { input.value = label; };
486+
row.appendChild(b);
487+
}
488+
}
489+
}
490+
const send = document.createElement('button');
491+
send.id = 'askSend';
492+
send.style.cssText = 'background:var(--accent);color:#fff;border:0;border-radius:8px;padding:7px 16px;margin-top:6px';
493+
send.textContent = '回答';
494+
send.onclick = async () => {
495+
const answers = [...div.querySelectorAll('input')].map(i => i.value.trim()).filter(Boolean);
496+
if (!answers.length) return;
497+
send.disabled = true;
498+
const res = await api.req(`/conversations/${currentConv}/runs/${runId}/answer`,
499+
{ method: 'POST', body: JSON.stringify({ answers }) });
500+
if (!res.ok) { send.disabled = false; addMsg('err', await errMsg(res)); return; }
501+
div.style.opacity = '.5';
502+
};
503+
div.appendChild(send);
504+
$('messages').appendChild(div);
505+
$('messages').scrollTop = $('messages').scrollHeight;
506+
}
507+
508+
function strData(d) {
509+
if (d == null) return '';
510+
if (typeof d === 'string') return d;
511+
if (Array.isArray(d)) return d.map(strData).join(', ');
512+
return JSON.stringify(d);
513+
}
514+
function setRunStatus(text, busy) {
515+
const box = $('runStatus');
516+
if (!text) { box.style.display = 'none'; return; }
517+
box.style.display = 'flex';
518+
box.innerHTML = (busy ? '<span class="spin">⚙️</span>' : '') + '<span>' + escapeHtml(text) + '</span>';
519+
}
520+
function renderTodos(items) {
521+
const box = $('todoPanel');
522+
if (!items || !items.length) { box.style.display = 'none'; return; }
523+
box.style.display = 'block';
524+
box.innerHTML = '<div class="t-title">📋 任务进度</div>' + items.map(t => {
525+
const s = String(t.status || '');
526+
const cls = /done|complete/i.test(s) ? 'done' : /progress|active|current/i.test(s) ? 'doing' : '';
527+
const icon = cls === 'done' ? '✅' : cls === 'doing' ? '🔄' : '⬜';
528+
return `<div class="t-item ${cls}"><span>${icon}</span><span>${escapeHtml(t.content || '')}</span></div>`;
529+
}).join('');
530+
}
531+
449532
function startStream(runId) {
450533
currentRun = runId;
451534
$('stopBtn2').style.display = 'inline-block';
535+
setRunStatus('正在启动…', true);
452536
const url = `/conversations/${currentConv}/runs/${runId}/stream?access_token=${encodeURIComponent(api.token)}`;
453537
es = new EventSource(url);
454538
let agentDiv = null;
@@ -458,13 +542,31 @@ <h1>一句话处理 Excel 表格</h1>
458542
if (!agentDiv) agentDiv = addMsg('agent', '');
459543
agentDiv.lastChild.textContent = (agentDiv.lastChild.textContent || '') + (e.data?.text ?? '');
460544
$('messages').scrollTop = $('messages').scrollHeight;
461-
} else if (e.type === 'notify' && e.data && e.data.kind === 'tool_start') {
462-
addMsg('tool', '· 工具: ' + (e.data.data || []).join(', '));
463-
} else if (e.type === 'notify' && e.data && e.data.kind === 'error') {
464-
addMsg('err', e.data.data);
545+
} else if (e.type === 'notify' && e.data) {
546+
const kind = e.data.kind, data = e.data.data;
547+
if (kind === 'tool_start') {
548+
setRunStatus('准备执行: ' + strData(data), true);
549+
} else if (kind === 'tool_running') {
550+
setRunStatus('正在执行: ' + strData(data), true);
551+
} else if (kind === 'tool') {
552+
setRunStatus('工具执行完成', true);
553+
} else if (kind === 'todos') {
554+
renderTodos(data);
555+
} else if (kind === 'error') {
556+
addMsg('err', typeof data === 'string' ? data : JSON.stringify(data));
557+
} else if (kind === 'retry') {
558+
setRunStatus('模型调用重试中…', true);
559+
} else if (kind === 'compact') {
560+
setRunStatus('正在压缩上下文…', true);
561+
} else if (kind === 'ask' || kind === 'confirm') {
562+
addAsk(data, runId);
563+
}
564+
} else if (e.type === 'log' && e.data && e.data.message) {
565+
setRunStatus(e.data.message, true);
465566
} else if (e.type === 'run') {
466567
es.close(); es = null; currentRun = null;
467568
$('stopBtn2').style.display = 'none';
569+
setRunStatus('', false);
468570
openConversation(currentConv, '');
469571
loadConversations();
470572
loadArtifacts();

0 commit comments

Comments
 (0)