From 47c5ccc0343f60ce225e74edb17c215ed372e182 Mon Sep 17 00:00:00 2001 From: Aisland Date: Thu, 20 Aug 2026 22:29:39 +0800 Subject: [PATCH] feat: remove Deleted-projects section (delete = permanent removal, files kept) + refresh button on iframe tab windows --- 01_content/src/client/index.tsx | 39 +++------ 01_content/src/client/locales.ts | 4 +- 01_content/src/client/split.tsx | 19 +++- 01_content/src/client/styles.ts | 4 + .../worklogs/2026-08-16_worktable-v2.md | 14 +++ 04_test/functional-diag.cjs | 8 +- 04_test/probe-batch13.cjs | 86 +++++++++++++++++++ 7 files changed, 140 insertions(+), 34 deletions(-) create mode 100644 04_test/probe-batch13.cjs diff --git a/01_content/src/client/index.tsx b/01_content/src/client/index.tsx index 5b33b77..7ade564 100644 --- a/01_content/src/client/index.tsx +++ b/01_content/src/client/index.tsx @@ -1352,13 +1352,7 @@ function buildCustomLayoutPrompt(req: string): string { }) } - /** 重新添加已删除的入驻项目(删除 ↔ 重新添加 完全可逆) */ - const readdProject = (id: string) => { - persistProjects((prev) => ({ - ...prev, - removed: prev.removed.filter((x) => x !== id), - })) - } + // ── 快捷方式(表单已移除,仅保留存量条目的删除能力) ── const removeShortcut = (id: string) => { @@ -1441,13 +1435,20 @@ function buildCustomLayoutPrompt(req: string): string { return def ? def.id : '2h' } - // ── 删除(全部走二次确认;常驻项目 = 移出工作台,插件不卸载) ── + // ── 删除(全部走二次确认;项目彻底移出工作台:对话与项目文件均保留,仅清理本地关联状态) ── const removeProject = (id: string) => { - persistProjects((prev) => ({ - ...prev, - removed: prev.removed.includes(id) ? prev.removed : [...prev.removed, id], - hidden: prev.hidden.filter((x) => x !== id), - })) + persistProjects((prev) => { + const next = { + ...prev, + removed: prev.removed.includes(id) ? prev.removed : [...prev.removed, id], + hidden: prev.hidden.filter((x) => x !== id), + order: prev.order.filter((x) => x !== id), + } + if (next.bindings[id]) { next.bindings = { ...next.bindings }; delete next.bindings[id] } + if (next.folders[id]) { next.folders = { ...next.folders }; delete next.folders[id] } + if (next.views[id]) { next.views = { ...next.views }; delete next.views[id] } + return next + }) } const askDelete = (kind: 'layout' | 'shortcut' | 'project', id: string, name: string) => { setRequestDelete({ kind, id, name }) @@ -1925,18 +1926,6 @@ function buildCustomLayoutPrompt(req: string): string { ))} - {projects.removed.length > 0 && ( - <> -
- {t('manage.removed')} - {projects.removed.map((rid) => ( -
- {projects.nameOverrides[rid] ?? metas[rid]?.name ?? rid} - -
- ))} - - )}
)} diff --git a/01_content/src/client/locales.ts b/01_content/src/client/locales.ts index 54a8699..646d838 100644 --- a/01_content/src/client/locales.ts +++ b/01_content/src/client/locales.ts @@ -55,7 +55,7 @@ export const zh = { 'confirm.delete': '删除', 'confirm.layoutBody': '确定删除「{name}」?该工作区及其布局将被移除,此操作不可恢复。', 'confirm.shortcutBody': '确定删除快捷方式「{name}」?此操作不可恢复。', - 'confirm.projectBody': '确定从工作台删除「{name}」?插件本身不会被卸载,「恢复默认」也不会复活它;之后可在设置里「已删除的项目」中重新添加。', + 'confirm.projectBody': '「{name}」将从工作台彻底移除(对话与项目文件都保留,只是不再显示项目卡片)。', 'pane.browser': '浏览器', 'pane.explorer': '资源管理器', 'pane.scm': '源代码管理', @@ -189,7 +189,7 @@ export const en = { 'confirm.delete': 'Delete', 'confirm.layoutBody': 'Delete "{name}"? Its workspace and layout will be removed. This cannot be undone.', 'confirm.shortcutBody': 'Delete shortcut "{name}"? This cannot be undone.', - 'confirm.projectBody': 'Remove "{name}" from the worktable? The plugin stays installed; Reset defaults will NOT bring it back — re-add it later under Removed projects in Settings.', + 'confirm.projectBody': '"{name}" will be removed from the worktable permanently (the conversation and project files are kept).', 'pane.browser': 'Browser', 'pane.explorer': 'Explorer', 'pane.scm': 'Source control', diff --git a/01_content/src/client/split.tsx b/01_content/src/client/split.tsx index f18772e..692fc2e 100644 --- a/01_content/src/client/split.tsx +++ b/01_content/src/client/split.tsx @@ -891,6 +891,23 @@ function BrowserPane() { ) } +/** iframe 内容标签(网页/站点产物):右上角常驻刷新按钮(重挂载整页刷新,跨域可靠) */ +function IframePane(props: { url: string; title?: string }) { + const [reloadKey, setReloadKey] = useState(0) + return ( +
+