From b39172013389ef742ad194b9b77a413361c563fd Mon Sep 17 00:00:00 2001 From: Aisland Date: Tue, 18 Aug 2026 01:32:12 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20setActiveTab=E8=A1=A5onSpecMutated(?= =?UTF-8?q?=E6=BF=80=E6=B4=BB=E6=A0=87=E7=AD=BE=E6=8C=81=E4=B9=85=E5=8C=96?= =?UTF-8?q?,=E4=BF=9D=E6=B4=BB=E9=97=AE=E9=A2=98=E7=9C=9F=E6=AD=A3?= =?UTF-8?q?=E6=A0=B9=E5=9B=A0)=20+=20=E6=B5=8B=E8=AF=95=E4=BD=9C=E7=94=A8?= =?UTF-8?q?=E5=9F=9F=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 01_content/src/client/split.tsx | 1 + .../worklogs/2026-08-16_worktable-v2.md | 27 +++++++++---------- 04_test/functional-diag.cjs | 11 ++++---- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/01_content/src/client/split.tsx b/01_content/src/client/split.tsx index 889b40f..d8c4a97 100644 --- a/01_content/src/client/split.tsx +++ b/01_content/src/client/split.tsx @@ -678,6 +678,7 @@ export const splitStore: SplitState = { main[i] = mutate(main[i]) this.spec = { ...spec, main } } + this.onSpecMutated?.(this.spec) this.persist() this.notify() }, diff --git a/02_process/worklogs/2026-08-16_worktable-v2.md b/02_process/worklogs/2026-08-16_worktable-v2.md index 5a2d0e1..a7f1d5a 100644 --- a/02_process/worklogs/2026-08-16_worktable-v2.md +++ b/02_process/worklogs/2026-08-16_worktable-v2.md @@ -639,19 +639,18 @@ 原生视图内部是浏览器扩展页,插件注入不了按钮、拦不到鼠标,也驱动不了内部滚动—— 向用户如实说明后按指示回退);② 视图选项改名「设置」,点开直接内嵌「排序方式 + 管理项目 展开列表」,不再二次点击;③ 管理项目里给现有项目加「变更视图」:换预设拓扑, -## 补记(工作区切换保活 + 改名输入草稿修复) +## 补记(激活标签持久化漏写修复——保活问题的真正根因) -- 用户反馈:① 切到其他项目再回来,网页子页面/位置、MD 滚动位置、激活标签全部重置; - ② 改名时先删原名会立刻弹回(只有先加新字才能删)。 -- 处理: - ① SplitWorkspace 重构为「保活池」:按布局 id 把工作区层全部保持挂载(display:none 隐藏、 - 仅当前可见;池上限 6 个 LRU)。切走再切回时 iframe 实例不销毁(子页面/滚动保留)、 - TextViewer 滚动保留、激活标签保留;几何经 props 传入(隐藏层用 0 几何)。 - 重构中清理了 snap.leftW 长期缺省(clamp(undefined)→NaN)的隐患; - ② 改名输入改本地草稿(RenameInput 组件):输入不落盘,blur/Enter 才提交; - 清空提交 = 删除覆盖并回显原名。Enter 直接调 commit(无头实测发现程序化 blur() 不派发 - focusout,真实点击无碍,但 Enter 路径必须显式提交)。 -- 验证(functional-diag STEP17/18 + 多个探针):STEP17 scrollBeforeClose=320 → - scrollAfter=320、activeAfter=1、iframeSameRef=true;STEP18 cleared=true 且真实 CDP 点击 - 失焦后 revertedToOriginal=true;全 18 STEP ERROR_COUNT: 0。 +- 用户反馈:自媒体工作台建 3 标签选 MD 滚到中间,切建筑审图再切回 → MD 和位置都丢了, + 默认跳到第三个 index 网页标签。 +- 精确复现(按用户真实路径:布局卡↔带视图覆盖的常驻卡互相切换)确认:active 回到 2。 +- 根因:splitStore.setActiveTab 漏调 onSpecMutated → 激活标签变更从不落盘; + 持久化里保留的是最后一次 openTab 的 active(最后一个标签)。保活池机制本身一直正常, + 之前「不保活」的表象全部源于这个持久化缺口。 +- 修复:setActiveTab 补 this.onSpecMutated?.(this.spec)。 +- 事故记录:上一轮测试脚本作用域缺陷(点中隐藏保活层里 styles.ts 标签的保存按钮), + 用户重启后写路由生效,把 '# EDITED_OK' 写进了 styles.ts 源文件——已 git checkout 恢复, + 并修正 STEP16 全部选择器限定可见元素(只写临时夹具)。 +- 验证:probe-card 精确复现用户流程 → activeBack=0、scrollBack=300、iframeSame=true; + 全 18 STEP 回归:STEP17 scroll 320→320、STEP16 保存闭环 savedContent=true;ERRORS 0。 - 备注:纯客户端改动,F5 即生效。 diff --git a/04_test/functional-diag.cjs b/04_test/functional-diag.cjs index 32cb2e1..1cd49eb 100644 --- a/04_test/functional-diag.cjs +++ b/04_test/functional-diag.cjs @@ -485,11 +485,12 @@ const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); await new Promise(function(r){setTimeout(r,400)}); st.openTab('main',0,{kind:'file',path:'C:\\\\Users\\\\SJL\\\\AppData\\\\Local\\\\Temp\\\\wt-edit-test.md'}); await new Promise(function(r){setTimeout(r,1200)}); - out.bar=!!document.querySelector('.dsh-wt_mdBar'); - var btns=document.querySelectorAll('.dsh-wt_mdBtn'); + out.bar=!![].slice.call(document.querySelectorAll('.dsh-wt_mdBar')).find(function(el){return el.getBoundingClientRect().height>0}); + var bar=[].slice.call(document.querySelectorAll('.dsh-wt_mdBar')).find(function(el){return el.getBoundingClientRect().height>0}); + var btns=bar?bar.querySelectorAll('.dsh-wt_mdBtn'):[]; if(btns[1]){ btns[1].click(); } await new Promise(function(r){setTimeout(r,250)}); - var ta=document.querySelector('.dsh-wt_mdEdit'); + var ta=[].slice.call(document.querySelectorAll('.dsh-wt_mdEdit')).find(function(el){return el.getBoundingClientRect().height>0}); out.editArea=!!ta; out.draft0=ta?ta.value.slice(0,8):null; if(ta){ @@ -498,10 +499,10 @@ const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); ta.dispatchEvent(new Event('input',{bubbles:true})); } await new Promise(function(r){setTimeout(r,250)}); - var saveBtn=document.querySelector('.dsh-wt_mdSave'); + var saveBtn=[].slice.call(document.querySelectorAll('.dsh-wt_mdSave')).find(function(el){return el.getBoundingClientRect().height>0}); if(saveBtn){ saveBtn.click(); } await new Promise(function(r){setTimeout(r,900)}); - out.previewBack=!!document.querySelector('.dsh-wt_md'); + out.previewBack=!![].slice.call(document.querySelectorAll('.dsh-wt_md')).find(function(el){return el.getBoundingClientRect().height>0}); var chk=await fetch('/api/worktable/file?path='+encodeURIComponent('C:\\\\Users\\\\SJL\\\\AppData\\\\Local\\\\Temp\\\\wt-edit-test.md')).then(function(r){return r.text()}).catch(function(){return null}); out.savedContent=chk?String(chk).indexOf('EDITED_OK')>=0:false; st.close();