fix(AI 建任务): 切走再切回来不再重置/重复探索回放
现象(用户报):离开「AI 建任务」子页再回来,回放与步骤计数像是被重置了。 真因与修法(`static/admin/taskgen.js`): 1. 每次进入子页 `initTaskGen → tgRestore` 都会重新订阅 SSE。已在盯同一轮时这是多余的: 服务端 `_Fanout` 带历史缓冲,会把这一轮**从头补发**一遍 → 回放区里卡片变两份、 步骤计数从 0 重数。现在用 `_tgRunId` 记当前订阅,同一轮直接复用连接; 换了一轮/刚刷新过页面才清空回放区重新订阅(历史缓冲会把已发生的事件补回来)。 2. 跟随画面的 MJPEG 长连接在切 Tab 时可能被浏览器挂起(画面定格)—— 切回来时重新拉一次流(`tgRearmLive`)。 实测(真机,12 步探索):切走 6 秒再切回 → 卡片 11→14 无重复、状态继续计数; 跑完后再切两次 → 14 张卡片与草稿预览均保持、跟随画面正常、无 JS 报错。
This commit is contained in:
+5
-1
@@ -214,7 +214,11 @@
|
|||||||
`static/admin/base.js` 的 `showSubTab`)。草稿预览能直接点「在步骤编辑器中打开」→
|
`static/admin/base.js` 的 `showSubTab`)。草稿预览能直接点「在步骤编辑器中打开」→
|
||||||
`openTaskModal(null, prefill)` 预填(用唯一 draftKey,避开 localStorage 旧草稿覆盖)。
|
`openTaskModal(null, prefill)` 预填(用唯一 draftKey,避开 localStorage 旧草稿覆盖)。
|
||||||
- **两个页面共用一个运行槽**:`GET /api/agent/run` 回 `mode`,两个前端各按 mode 决定
|
- **两个页面共用一个运行槽**:`GET /api/agent/run` 回 `mode`,两个前端各按 mode 决定
|
||||||
是否订阅 SSE(一个 run 只有一个事件队列,两个 EventSource 同时消费会互相瓜分事件)。
|
是否订阅 SSE;服务端用 `_Fanout` 给**每个订阅者一条自己的队列**(谁都不丢事件)。
|
||||||
|
- **切 Tab 不丢回放**:`initTaskGen()` 每次进入子页都会 `tgRestore()`——已经在盯同一轮就
|
||||||
|
**不重复订阅**(否则服务端会把这一轮从头补发一遍,卡片成两份);换了一轮/刚刷新过页面才清空
|
||||||
|
回放区重新订阅(`_Fanout` 的历史缓冲会把已发生的事件补回来)。跟随画面的 MJPEG 长连接
|
||||||
|
在切回来时重新拉一次(`tgRearmLive`),避免定格。
|
||||||
- **落库出口**:页面上的「✓ 直接创建任务」(`POST /api/agent/task_draft/create`)与
|
- **落库出口**:页面上的「✓ 直接创建任务」(`POST /api/agent/task_draft/create`)与
|
||||||
「在步骤编辑器中核对」(预填编辑器 → 用户点保存)——两条路最终都汇到 `add_job`。
|
「在步骤编辑器中核对」(预填编辑器 → 用户点保存)——两条路最终都汇到 `add_job`。
|
||||||
|
|
||||||
|
|||||||
+26
-1
@@ -10,6 +10,7 @@
|
|||||||
let _tgInit = false;
|
let _tgInit = false;
|
||||||
let _tgStream = null; // EventSource
|
let _tgStream = null; // EventSource
|
||||||
let _tgBusy = false;
|
let _tgBusy = false;
|
||||||
|
let _tgRunId = ''; // 当前已订阅的 run(切 Tab 回来时避免重复订阅)
|
||||||
let _tgDraft = null; // {summary, task, notes, evidence}
|
let _tgDraft = null; // {summary, task, notes, evidence}
|
||||||
let _tgWarnings = [];
|
let _tgWarnings = [];
|
||||||
let _tgPrompt = ''; // 本次需求(回存草稿时带上)
|
let _tgPrompt = ''; // 本次需求(回存草稿时带上)
|
||||||
@@ -29,6 +30,17 @@ function initTaskGen(){
|
|||||||
tgLoadDevices();
|
tgLoadDevices();
|
||||||
tgLoadGroups();
|
tgLoadGroups();
|
||||||
tgRestore();
|
tgRestore();
|
||||||
|
tgRearmLive();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切走再切回来时,观众侧的 MJPEG 长连接可能被浏览器挂起(画面定格)——
|
||||||
|
// 重新拉一次流,画面接着动
|
||||||
|
function tgRearmLive(){
|
||||||
|
const card = document.getElementById('tg-live-card');
|
||||||
|
const img = document.getElementById('tg-live-img');
|
||||||
|
if(!card || !img || !_tgLiveSerial || card.style.display === 'none') return;
|
||||||
|
img.src = '/api/screen/stream?serial=' + encodeURIComponent(_tgLiveSerial)
|
||||||
|
+ '&q=80&fps=8&t=' + Date.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
function tgExample(){
|
function tgExample(){
|
||||||
@@ -178,6 +190,7 @@ function tgStatus(t){
|
|||||||
// ---------------- 事件流 ----------------
|
// ---------------- 事件流 ----------------
|
||||||
function listenTaskGenStream(runId){
|
function listenTaskGenStream(runId){
|
||||||
if(_tgStream) _tgStream.close();
|
if(_tgStream) _tgStream.close();
|
||||||
|
_tgRunId = runId;
|
||||||
const es = new EventSource('/api/agent/stream?run_id=' + runId);
|
const es = new EventSource('/api/agent/stream?run_id=' + runId);
|
||||||
_tgStream = es;
|
_tgStream = es;
|
||||||
let steps = 0;
|
let steps = 0;
|
||||||
@@ -461,7 +474,19 @@ function tgRestore(){
|
|||||||
if(!r||!r.ok) return;
|
if(!r||!r.ok) return;
|
||||||
// 运行中的 designer 由本页接管订阅;聊天页见 agent.js 的 mode 判断
|
// 运行中的 designer 由本页接管订阅;聊天页见 agent.js 的 mode 判断
|
||||||
if(r.running && r.mode === 'designer' && r.run_id){
|
if(r.running && r.mode === 'designer' && r.run_id){
|
||||||
tgSetBusy(true, '探索进行中…(刷新后已重新连接)');
|
tgSetBusy(true, '探索进行中…');
|
||||||
|
// 已经在盯着同一轮了(切走再切回来)→ 别重复订阅:
|
||||||
|
// 重订阅会让服务端把这一轮从头发一遍(历史缓冲),卡片就成两份了
|
||||||
|
if(_tgRunId === r.run_id && _tgStream && _tgStream.readyState !== 2){
|
||||||
|
tgStatus('探索进行中…');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 换了一轮 / 刚刷新过页面:回放区清空重建(服务端会把已发生的事件补发回来)
|
||||||
|
const box = document.getElementById('tg-stream');
|
||||||
|
if(box) box.innerHTML = '';
|
||||||
|
const db = document.getElementById('tg-draft');
|
||||||
|
if(db) db.innerHTML = '';
|
||||||
|
tgStatus('探索进行中…(已连接,回放会从头补齐)');
|
||||||
listenTaskGenStream(r.run_id);
|
listenTaskGenStream(r.run_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user