From 20d877a34600d7ce4849f9dc6584d42db39385b6 Mon Sep 17 00:00:00 2001 From: Codex Bot Date: Fri, 6 Nov 2026 23:57:32 +0800 Subject: [PATCH] Make uploading images fully editable local canvas nodes --- PERFORMANCE.md | 2 + README.md | 2 + VALIDATION.md | 9 +++ src/components/canvas/ai-panel.tsx | 4 +- src/components/canvas/graph-canvas.tsx | 46 +++++++------ src/components/canvas/use-canvas-tree.ts | 76 ++++++++++++++++++---- src/components/canvas/use-image-uploads.ts | 7 +- src/lib/canvas-elements.ts | 2 +- src/lib/canvas-sync.ts | 5 +- tests/canvas-member-scenario.mjs | 32 ++++++++- tests/canvas-sync.test.mjs | 13 ++++ tests/canvas-upload-scenario.mjs | 29 +++++++-- 12 files changed, 181 insertions(+), 46 deletions(-) diff --git a/PERFORMANCE.md b/PERFORMANCE.md index d496dfe..c683573 100644 --- a/PERFORMANCE.md +++ b/PERFORMANCE.md @@ -102,3 +102,5 @@ Core PR #16 已由用户合并为 2207c85;push #946、PR #947、主线 #949、 能力协商 2 秒截止与约 1,989ms 的服务端路由耗时接近,且真实三次移动前仍有仅 position 变化的 PATCH。现移除短截止并禁止把网络错误永久缓存为“不支持”;慢响应和失败预取回归均保持原子成员移动。后端三笔事务各移动 1 个节点,总数、非位置内容与版本递增均正确。 首次上传改为本地即时预览 + 后台原图上传,服务端确认后保存引用,远端预览加载完才切换显示。该改动消除空画布等待,不将即时显示误报为网络上传已完成或服务端延迟已消失。实际交互复测待用户操作后补充。 + +用户随后指出只读预览不等于已添加元素。已修正为选图时就创建可编辑的本地节点,后台上传仅补齐引用;位置、尺寸、名称、删除及撤销状态都以本地最新状态为准。未准备好的文件节点和关联边不传给 Core;其他编辑仍可保存。该修正不依赖公网延迟降低,也不将本地添加误报成后台文件已上传。 diff --git a/README.md b/README.md index e957b14..a966a21 100644 --- a/README.md +++ b/README.md @@ -136,3 +136,5 @@ Headless Canvas API 的拆包方案保留在本地忽略的 `docs/HEADLESS_CANVA Core `subgraphs.member_positions` 能力启用时,最终落点(源画布局部坐标)与归属通过一次 members POST 原子保存,单纯拖放不再先 PATCH 坐标。旧后端仍使用先保存坐标再迁移的兼容流程,但不显示整屏等待遮罩。Core 配套 PR #16 已合并并部署为 2207c85;刷新页面后会重新检测并启用新接口能力。 上传图片时立即在画布显示本地预览,并在后台上传原始文件;上传成功才把稳定附件引用加入快照。服务端预览加载完成前继续显示本地图片,避免网络等待期间空白。失败保留文件供重试/取消,重试沿用同一幂等键;本地 blob URL 不保存到服务端。 + +上传中的图片也是正常本地节点,可立即选中、拖动、缩放、改名、删除和撤销;上传完成只补齐附件引用,不重置节点。上传前改变分区归属会先在本地完成,文件准备好后保存到当时的实际所属画布。临时上传标记和 blob 地址由传输层排除,不发送给 Core;文件仍未可用时,依赖服务端文件的 AI 生成需等待上传完成。 diff --git a/VALIDATION.md b/VALIDATION.md index 1f41e2c..82058f8 100644 --- a/VALIDATION.md +++ b/VALIDATION.md @@ -68,3 +68,12 @@ 生产复核发现 capabilities 请求约 1,989ms,原先 2 秒客户端截止可能误将慢响应缓存为不支持。已删除该短截止,网络错误清除缓存并重试;只有成功响应明确未声明能力才走旧流程。DOM 回归增加 2.1 秒能力响应、预取失败后重试的场景,均保持原子移动、无前置 PATCH。 上传 DOM 回归覆盖:网络未确认前本地图片已显示、可添加其他内容、快照没有 blob URL、原始附件引用与 assetId 正确、远端预览加载后释放本地 URL、失败保留文件、同键重试只创建一个节点、取消/卸载清理与原图比例。TypeScript、83 项单元测试与隔离生产构建通过。生产新上传的交互体验及修正后的能力协商仍需用户刷新后实测。 + +## 上传期间的真实本地节点 + +改为在选图时创建可编辑的本地 CanvasNode,上传确认只更新 src/assetId,并同步修正本地撤销记录,不新增无意义的撤销步骤。传输过滤临时节点与关联边,写入基线使用实际发送的干净快照。 + +- 84 项单元测试通过,新增上传节点/关联边不会进入网络快照、其他内容仍能保存、附件可用后正常保存的覆盖。 +- DOM/Hook 回归通过:上传期间拖动/缩放/改名在确认后保留;确认前删除不会被重新插入;删除可撤销;尺寸初始化与引用补齐不消耗撤销;本地跨分区移动与复合撤销、文件确认到当前所属画布;已持久化后的归属撤销走真实事务。 +- 并发回归通过:版本号型响应的重新读取、包含重复 parent 的事务快照,都保留本地上传节点;其他事务与附件完成同时发生不会覆盖新图片。AI 在文件上传完成后可执行,编辑无需等待。 +- 最终 TypeScript、84 项单元测试、完整 DOM 回归和隔离生产构建均通过;未访问用户浏览器,不将 DOM 测试描述为用户已完成浏览器验收。 diff --git a/src/components/canvas/ai-panel.tsx b/src/components/canvas/ai-panel.tsx index 57ef981..3ae6347 100644 --- a/src/components/canvas/ai-panel.tsx +++ b/src/components/canvas/ai-panel.tsx @@ -40,11 +40,11 @@ export function AIPanel({ id, node, workspace, boardId, ai, save }: { id: string