From 07e6a5e49f890c0d80e953d70bbd9f837fe179ee Mon Sep 17 00:00:00 2001 From: Aisland Date: Tue, 18 Aug 2026 00:40:02 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=8D=A1=E7=89=87=E5=8F=8D=E9=80=89(?= =?UTF-8?q?=E9=AB=98=E4=BA=AE=E8=B7=9F=E9=9A=8F=E5=BC=95=E6=93=8E=E5=BC=80?= =?UTF-8?q?=E5=90=88)=20+=20=E8=AE=BE=E7=BD=AE=E9=9D=A2=E6=9D=BF:=E6=8E=92?= =?UTF-8?q?=E5=BA=8F/=E7=AE=A1=E7=90=86=E5=90=8C=E5=AD=97=E4=BD=93=C2=B7?= =?UTF-8?q?=E5=AE=BD280=C2=B7=E6=8E=92=E5=BA=8F=E6=94=B9=E5=B7=A6=E5=8F=B3?= =?UTF-8?q?=E4=B8=A4=E6=8C=89=E9=92=AE=C2=B7=E5=8E=BB=E6=81=A2=E5=A4=8D?= =?UTF-8?q?=E9=BB=98=E8=AE=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 01_content/src/client/index.tsx | 46 +++++++++---------- 01_content/src/client/locales.ts | 2 - 01_content/src/client/styles.ts | 5 ++ .../worklogs/2026-08-16_worktable-v2.md | 27 ++++++----- 04_test/functional-diag.cjs | 14 +++--- 5 files changed, 50 insertions(+), 44 deletions(-) diff --git a/01_content/src/client/index.tsx b/01_content/src/client/index.tsx index 37c4dd4..82a9190 100644 --- a/01_content/src/client/index.tsx +++ b/01_content/src/client/index.tsx @@ -635,18 +635,6 @@ function WorktableSection(props: any) { }) } - // 恢复默认:还原排序/隐藏/改名/图标/视图覆盖;已删除的项目不复活(真删除,可在「已删除的项目」重新添加) - const resetProjects = () => { - persistProjects((prev) => ({ - ...prev, - order: [], - hidden: [], - nameOverrides: {}, - iconOverrides: {}, - views: {}, - })) - } - /** 重新添加已删除的入驻项目(删除 ↔ 重新添加 完全可逆) */ const readdProject = (id: string) => { persistProjects((prev) => ({ @@ -794,10 +782,17 @@ function WorktableSection(props: any) { if (ovr) icon.setAttribute('data-wt-icon', ovr) else icon.removeAttribute('data-wt-icon') } - // 选中态统一由工作台判定(引擎打开的项目高亮;未打开时若引擎空闲则保留卡片自带状态, - // 兼容自带分栏实现的插件) - if (activeSplitId === id) el.setAttribute('data-on', 'true') - else if (activeSplitId != null) el.setAttribute('data-on', 'false') + // 选中态统一由工作台判定: + // - 有视图覆盖的项目:点击恒由工作台接管 → 高亮完全跟随 activeSplitId(关闭即熄灭); + // - 无视图覆盖:引擎打开时点亮;引擎开着别的时熄灭;引擎空闲时保留卡片自带状态 + // (兼容自带分栏实现的插件)。 + if (projects.views[id]) { + el.setAttribute('data-on', activeSplitId === id ? 'true' : 'false') + } else if (activeSplitId === id) { + el.setAttribute('data-on', 'true') + } else if (activeSplitId != null) { + el.setAttribute('data-on', 'false') + } } else { el.removeAttribute('data-wt-id') } @@ -807,7 +802,7 @@ function WorktableSection(props: any) { const mo = new MutationObserver(sync) mo.observe(document.body, { childList: true, subtree: true }) return () => mo.disconnect() - }, [aliveRegisteredIds, projects.iconOverrides, activeSplitId]) + }, [aliveRegisteredIds, projects.iconOverrides, projects.views, activeSplitId]) useEffect(() => { const onDocClick = (e: MouseEvent) => { @@ -1070,12 +1065,16 @@ function WorktableSection(props: any) { {viewOptionsOpen &&
setViewOptionsOpen(false)} />} {viewOptionsOpen && ( -
- {t('sort.label')} - - +
+
+ {t('sort.label')} +
+
+ + +
{t('manage.title')} @@ -1149,7 +1148,6 @@ function WorktableSection(props: any) {
))} - {projects.removed.length > 0 && ( <>
diff --git a/01_content/src/client/locales.ts b/01_content/src/client/locales.ts index 42a2d51..2f0d599 100644 --- a/01_content/src/client/locales.ts +++ b/01_content/src/client/locales.ts @@ -37,7 +37,6 @@ export const zh = { 'manage.removed': '已删除的项目', 'manage.readd': '重新添加', 'manage.deleteShortcut': '删除快捷方式', - 'manage.reset': '恢复默认', 'shortcut.badge': '本地', 'add.chooseLayout': '选择布局模式', 'add.layoutNamePh': '布局名称', @@ -117,7 +116,6 @@ export const en = { 'manage.removed': 'Removed projects', 'manage.readd': 'Re-add', 'manage.deleteShortcut': 'Delete shortcut', - 'manage.reset': 'Reset defaults', 'shortcut.badge': 'Local', 'add.chooseLayout': 'Choose a layout', 'add.layoutNamePh': 'Layout name', diff --git a/01_content/src/client/styles.ts b/01_content/src/client/styles.ts index db687de..58c6c38 100644 --- a/01_content/src/client/styles.ts +++ b/01_content/src/client/styles.ts @@ -48,6 +48,11 @@ export const css = [ '.dsh-wt_manageTitle{font-size:11px;font-weight:600;letter-spacing:.04em;color:var(--dsw-alias-label-primary,#e6e8eb)}', '.dsh-wt_manageDone{display:flex;align-items:center;padding:2px 8px;border:none;border-radius:5px;background:transparent;color:var(--dsw-alias-state-accent-primary,#4f8ef7);font:inherit;font-size:11px;line-height:16px;cursor:pointer}', '.dsh-wt_manageDone:hover{background:var(--dsw-alias-fill-l1,rgba(255,255,255,.05))}', + // 排序方式:一左一右两个选择按钮(手动 / 最近) + '.dsh-wt_sortRow{display:flex;gap:6px;padding:0 8px 2px}', + '.dsh-wt_sortBtn{flex:1;display:flex;align-items:center;justify-content:center;padding:4px 8px;border:1px solid var(--dsw-alias-border-l1,#262b36);border-radius:6px;background:var(--dsw-alias-fill-l1,rgba(255,255,255,.02));color:var(--dsw-alias-label-secondary,#9aa4b2);font:inherit;font-size:11px;line-height:16px;cursor:pointer}', + '.dsh-wt_sortBtn:hover{color:var(--dsw-alias-label-primary,#e6e8eb);border-color:var(--dsw-alias-border-l2,#3a4150)}', + '.dsh-wt_sortBtn[data-on=true]{border-color:var(--dsw-alias-state-accent-primary,#4f8ef7);color:var(--dsw-alias-state-accent-primary,#4f8ef7);background:var(--dsw-alias-fill-l1,rgba(255,255,255,.05))}', '.dsh-wt_manageRow{display:flex;align-items:center;gap:6px;padding:4px 6px;border:1px solid transparent;border-radius:6px;background:var(--dsw-alias-fill-l1,rgba(255,255,255,.03))}', '.dsh-wt_manageRow:hover{border-color:var(--dsw-alias-border-l2,#3a4150)}', '.dsh-wt_manageRowOff{opacity:.45}', diff --git a/02_process/worklogs/2026-08-16_worktable-v2.md b/02_process/worklogs/2026-08-16_worktable-v2.md index 6338373..ca41959 100644 --- a/02_process/worklogs/2026-08-16_worktable-v2.md +++ b/02_process/worklogs/2026-08-16_worktable-v2.md @@ -639,17 +639,20 @@ 原生视图内部是浏览器扩展页,插件注入不了按钮、拦不到鼠标,也驱动不了内部滚动—— 向用户如实说明后按指示回退);② 视图选项改名「设置」,点开直接内嵌「排序方式 + 管理项目 展开列表」,不再二次点击;③ 管理项目里给现有项目加「变更视图」:换预设拓扑, -## 补记(工作台状态持久化修复 + tsx/css 代码预览) +## 补记(反选修复 + 设置面板五项微调) -- 用户反馈:① 项目里布置好的窗口内容(如上面浏览器/下面终端)切换项目再切回就变回默认, - 每个项目的工作台应保持上一次的样子;② 资源管理器要能点开 tsx/css 文件预览(同 MD)。 -- 根因:onSpecMutated 回写只写 layouts 条目,漏了 views(视图覆盖工作区)→ 常驻项目 - 内容丢失;布局路径本身正常(实测确认)。 -- 处理:① onSpecMutated 按 spec.id 分流:layouts 里有该 id → 更新布局条目;否则写回 - views[id](入驻项目工作区)。所有变更(开标签/关标签/换聊天边/换位)都会触发; - ② 资源管理器文件匹配加 tsx/ts/jsx/js/css/json → kind:file 预览(等宽文本展示,同 TXT 模式)。 -- 验证(functional-diag 重排 STEP14/15 到 STEP10 前 + STEP9 改查 planreview 键 + - 恢复误删的 STEP13 打印行):STEP14 布局 layoutSavedTabs=1/layoutRestoredTabs=1、 - 视图覆盖 taSavedTabs=1/taRestoredTabs=1(切换回来内容保持);STEP15 tsx/css 双标签预览 - 且内容含 WorktableSection;全 15 STEP ERROR_COUNT: 0。 +- 用户反馈(五项):① 旅行 Atlas 卡片再点一次应反选(取消选中),现在做不到; + ② 「排序方式」与「管理项目」应同级别同字体(按管理项目样式);③ 设置弹窗宽度略宽; + ④ 排序方式两行字改成一左一右两个选择按钮(手动/最近);⑤ 去掉「恢复默认」按钮。 +- 处理: + ① 根因:引擎其实已关,但 DOM 同步写入的 data-on=true 在引擎空闲时从不还原 → 高亮残留。 + 修正规则:有视图覆盖的项目高亮完全跟随 activeSplitId(关闭即 false);无覆盖项目引擎空闲时 + 保留卡片自带状态; + ② 「排序方式」标签改用 manageHead/manageTitle(与管理项目同款 11px/600); + ③ 设置弹窗 316 → 280px; + ④ 排序改为 .dsh-wt_sortRow 一左一右两个 .dsh-wt_sortBtn(选中态描边高亮); + ⑤ 删除恢复默认按钮与 resetProjects 函数、locale manage.reset(zh/en)。 +- 验证(functional-diag):STEP13 增反选断言 activeAfterSecondClick=false + + taOnAfterSecondClick='false';STEP8 sortItems=2;STEP10 resetBtnGone=true 且删除/重新添加 + 流程保持;全 15 STEP ERROR_COUNT: 0。 - 备注:纯客户端改动,F5 即生效。 diff --git a/04_test/functional-diag.cjs b/04_test/functional-diag.cjs index b81d7e6..bb09150 100644 --- a/04_test/functional-diag.cjs +++ b/04_test/functional-diag.cjs @@ -157,7 +157,7 @@ const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); if(btn){ btn.click(); } await new Promise(function(r){setTimeout(r,300)}); var sp=document.querySelector('.dsh-wt_settings'); - if(sp){ var cs=getComputedStyle(sp); out.pos=cs.position; out.left=sp.getBoundingClientRect().left; out.sortItems=sp.querySelectorAll('.dsh-wt_menuItem').length; out.rows=sp.querySelectorAll('.dsh-wt_manageRow').length; } + if(sp){ var cs=getComputedStyle(sp); out.pos=cs.position; out.left=sp.getBoundingClientRect().left; out.sortItems=sp.querySelectorAll('.dsh-wt_sortBtn').length; out.rows=sp.querySelectorAll('.dsh-wt_manageRow').length; } out.backdrop=!!document.querySelector('.dsh-wt_popBackdrop'); var bd=document.querySelector('.dsh-wt_popBackdrop'); if(bd){ bd.click(); } @@ -342,12 +342,9 @@ const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); await new Promise(function(r){setTimeout(r,300)}); out.layoutGoneAfterDelete=!document.querySelector('.dsh-wt_layout'); try{ out.layoutsLeft=JSON.parse(localStorage.getItem('dsh.worktable.projects.v1')).layouts.length }catch(e){ out.layoutsLeft='ERR' } - // 恢复默认不应复活已删除项目;「已删除的项目」里重新添加可逆 - var resetBtn=document.querySelector('.dsh-wt_manageReset'); - if(resetBtn){ resetBtn.click(); } - await new Promise(function(r){setTimeout(r,250)}); - try{ out.removedAfterReset=JSON.parse(localStorage.getItem('dsh.worktable.projects.v1')).removed }catch(e){ out.removedAfterReset='ERR' } + // 真删除:「已删除的项目」区块出现,重新添加可逆(无恢复默认按钮) out.removedSection=!!document.querySelector('.dsh-wt_settings .dsh-wt_manageRowRemoved'); + out.resetBtnGone=!document.querySelector('.dsh-wt_manageReset'); var readdBtn=document.querySelector('.dsh-wt_settings .dsh-wt_manageRowRemoved .dsh-wt_manageBtn'); if(readdBtn){ readdBtn.click(); } await new Promise(function(r){setTimeout(r,300)}); @@ -445,6 +442,11 @@ const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); await new Promise(function(r){setTimeout(r,500)}); out.taOnAfterOpen=ta?ta.getAttribute('data-on'):null; out.engineSpecId=st.spec?st.spec.id:null; + // 反选:再点一次卡片 → 引擎关闭 + 高亮熄灭 + if(ta){ ta.click(); } + await new Promise(function(r){setTimeout(r,400)}); + out.activeAfterSecondClick=st.active; + out.taOnAfterSecondClick=ta?ta.getAttribute('data-on'):null; st.close(); await new Promise(function(r){setTimeout(r,300)}); }catch(err){ out.err=String(err) }