feat(canvas): 画布同步 - 新增操作事务、预演保存与并发恢复能力
This commit is contained in:
@@ -15,9 +15,19 @@ description: 当前项目已实现功能的手工验证清单与未确认边界
|
||||
|
||||
## 画布素材缺失时的本地强制覆盖
|
||||
|
||||
- 已实现:云端保存返回 `canvas_history_resources_missing` 时,画布同步面板提供“用本地版强制覆盖云端”。操作会先保存本地草稿,探测资源状态,清理确认已删除或不存在的资源定位,保留节点布局、提示词和连线后再提交;普通自动保存仍执行完整素材校验。
|
||||
- [x] 专项测试覆盖嵌套资源定位收集、失效媒体字段清理、素材绑定移除以及画布性能回归;前端构建、后端画布/处理器/仓储测试通过。
|
||||
- [ ] 使用已登录浏览器打开具体画布,点击强制覆盖并刷新确认:失效图片节点仍保留为可重新上传的空节点,本地草稿可从版本记录恢复。
|
||||
## 画布 operations 自动恢复验收
|
||||
|
||||
- 已实现:云端画布写入统一使用字段/对象 operations;本地 journal 保存未确认请求,响应丢失、断网、刷新和重试都复用原 `mutationId` 与 payload。服务端 receipt 与画布变更同事务提交,相同请求安全重放,摘要不同返回冲突。
|
||||
- [x] 专项测试覆盖字段合并、同字段冲突、显式创建、对象不存在、幂等重放以及删除后迟到更新不重新创建节点;前端类型检查、生产构建和后端全量测试通过。
|
||||
- [ ] 使用已登录浏览器打开同一画布的两个标签页:分别修改不同字段应自动合并;修改同一字段应显示同步错误并保留本地输入,恢复后自动重放。
|
||||
- [ ] 在浏览器开发者工具中模拟断网、刷新和响应丢失,确认本地 journal 保留原请求并在恢复连接后完成;检查同步状态图标的 pending/error/done 颜色。
|
||||
- [ ] 让 Agent 或媒体任务在节点删除后返回迟到更新,确认任务回执保留但不会重新创建幽灵节点。
|
||||
|
||||
- 已实现:云端画布写入统一使用字段/对象 operations;本地 journal 保存未确认请求,响应丢失、断网、刷新和重试都复用原 `mutationId` 与 payload。服务端 receipt 与画布变更同事务提交,相同请求安全重放,摘要不同返回冲突。
|
||||
- [x] 专项测试覆盖字段合并、同字段冲突、显式创建、对象不存在、幂等重放以及删除后迟到更新不重新创建节点;前端类型检查、生产构建和后端全量测试通过。
|
||||
- [ ] 使用已登录浏览器打开同一画布的两个标签页:分别修改不同字段应自动合并;修改同一字段应显示同步错误并保留本地输入,恢复后自动重放。
|
||||
- [ ] 在浏览器开发者工具中模拟断网、刷新和响应丢失,确认本地 journal 保留原请求并在恢复连接后完成;检查同步状态图标的 pending/error/done 颜色。
|
||||
- [ ] 让 Agent 或媒体任务在节点删除后返回迟到更新,确认任务回执保留但不会重新创建幽灵节点。
|
||||
|
||||
## Agent 只读循环软收敛
|
||||
|
||||
@@ -198,14 +208,14 @@ description: 当前项目已实现功能的手工验证清单与未确认边界
|
||||
- 画布编辑器左侧图标菜单与展开内容改用一块低圆角、半透明磨砂表面;删除双重标题、硬分隔线和搜索框边框。侧栏现在浮在真实画布上方,打开/折叠不再改变画布视口宽度;顶栏和左下缩放控件避开侧栏。工作区下拉菜单及共享单选下拉去掉高亮描边,用背景和阴影建立层次,键盘焦点保留低对比提示。仍待登录态真实页面验收明暗主题、画布节点透视、窄屏抽屉、菜单键盘导航和弹层层级。
|
||||
- [ ] 在已登录的真实画布和用户工作区以浏览器 100% 缩放验收明暗主题、侧栏展开/折叠、顶部/底部工具栏、Agent 历史与设置、输入区和标签横向滚动;再检查窄屏与触屏下是否截断或遮挡。当前本地独立浏览器会跳转登录页,未将静态检查视为视觉验收。
|
||||
|
||||
## 画布资源断链、前端发布兼容与画布热点
|
||||
## 画布资源校验、前端发布兼容与画布热点
|
||||
|
||||
- 已实现:统一递归识别持久资源字段(含嵌套 `videoPreview`);保存前和历史快照保存时校验当前资源归属/ready 状态,资源缺失返回带路径和 ID 的结构化 409。显式修复保留坏版本历史但要求新版本完整且 revision CAS 成功。后台 `repair-canvas-resources` 默认只读,仅可清除确认缺失的派生视频预览;主媒体问题报告为 unresolved。
|
||||
- 已实现:哈希 chunk 采用长缓存,缺失资源不缓存;HTML 显式 `no-cache, must-revalidate`。静态容器发布保留当前与上一发布 chunk,并在保留窗口内清理更旧资源;Vite preload 失败只自动恢复一次,之后交由路由错误页,用户手动重试仍可用。已有数据卷不会凭空恢复首次部署前已删的 chunk。
|
||||
- 已实现:同步显式 repair/force 请求不会被正在运行的普通同步吞掉;素材元数据请求按账号 scope/generation 隔离迟到响应。画布内容 hash 对 viewport/revision-only 副本复用;视口更新走轻量路径;loading 节点共享画布级 ticker,页面隐藏时暂停该 ticker。
|
||||
- [ ] 先备份隔离/测试数据库,验证 `repair-canvas-resources` dry-run、`--apply`、重复运行幂等、并发 revision 冲突、只清派生 preview、不改主媒体;检查 unresolved 后人工恢复历史或重传。未扫描或改写生产数据库。
|
||||
- 已实现:统一递归识别持久资源字段(含嵌套 `videoPreview`);operations 提交前校验资源归属和 ready 状态,资源缺失返回带路径和 ID 的结构化 409。未确认请求保留在 journal,不能通过覆盖或历史恢复绕过资源合同;主媒体问题继续报告为 unresolved。
|
||||
- 已实现:哈希 chunk 采用长缓存,缺失资源不缓存;HTML 显式 `no-cache, must-revalidate`。静态容器发布保留当前与上一发布 chunk,并在保留窗口内清理更旧资源;Vite preload 失败只自动恢复一次,之后交由路由错误页。已有数据卷不会凭空恢复首次部署前已删的 chunk。
|
||||
- 已实现:媒体元数据请求按账号 scope/generation 隔离迟到响应;画布内容 hash 对 viewport-only 副本复用;视口更新走轻量路径;loading 节点共享画布级 ticker,页面隐藏时暂停该 ticker。
|
||||
- [ ] 先备份隔离/测试数据库,验证资源缺失返回结构化冲突、同一 mutationId 重放幂等、字段基线冲突和删除后迟到更新拒绝;确认事务失败不会留下半条 receipt。未扫描或改写生产数据库。
|
||||
- [ ] 使用发布测试卷连续发布三版以上:旧 tab 延迟触发旧 chunk 后仍可加载;验证 HTML 与哈希资源 Cache-Control、旧 chunk 404 不被 SPA fallback 改写,以及浏览器一次性恢复不循环。当前没有 CDN/Ingress 线上响应证据,Firefox MIME 具体响应类型未确认。
|
||||
- [ ] Firefox/Chrome/Safari 实际页面走关键 lazy route;检查离线草稿、登录切换和错误重试行为。尚未做真实浏览器/CDN 验收。
|
||||
- [ ] Firefox/Chrome/Safari 实际页面走关键 lazy route;检查离线 journal、登录切换和自动重放行为。尚未做真实浏览器/CDN 验收。
|
||||
- [ ] 使用 React Profiler 与长时间运行的大画布记录任务更新、节点数/可见数、主线程长任务和页面隐藏行为。当前只做结构性降热点,不推断整画布必然全量重渲染或已达到某个帧率。
|
||||
|
||||
## 完整 AI 拆图
|
||||
@@ -618,14 +628,13 @@ MiniMax Hailuo Video V2 / H3 插件更新至 `2.0.1`,创建和查询均优先
|
||||
- [ ] 使用 Artbox 的 NewAPI 通道 2 保存“视频 Token”,完成无用量视频任务后确认公式结算、10% 余量退回、来源标注;重复轮询/回调不重复扣费。
|
||||
- [ ] PostgreSQL 部署验证 schema v25;新代码未启动或未迁移时不要用旧后端保存非 Ark Token 价格。历史无公式快照的收费订单缺少用量仍进入待核对。
|
||||
|
||||
## Agent 历史事件重放导致画布反复冲突
|
||||
## Agent 事件校准与 operations journal 恢复
|
||||
|
||||
旧会话的画布增量可能缺少版本号。页面刷新重放事件时,原实现先标记冲突;后续完整快照即使确认内容一致,也提前返回而不清除冲突。现在增量拒绝只触发快照校准,由完整快照确认真实冲突;内容一致时更新同步基线并恢复已同步状态。云端仍为已核对的同一基线时,保留待保存的本地编辑,不误判为并发修改。真实冲突继续保留草稿并阻止覆盖,不重放无版本增量,不修改历史数据。
|
||||
旧会话的画布增量可能缺少版本号或发生断流。现在增量缺口只触发完整画布校准;客户端保留已确认基线和未确认 operations,请求恢复时复用原 `mutationId` 与原始 payload。不同字段可合并,同字段或已删除对象不会被静默覆盖或重建。
|
||||
|
||||
- [x] 47 项画布版本、Agent 增量合并、事件调度与刷新测试通过,覆盖加载云端、保存、重建会话后三次重放旧事件,以及版本缺口、未核对离线草稿与真实冲突保护。
|
||||
- [x] 前端 `bun run build` 通过;同时补齐 Agent 会话预览缺少的 `markdownPlainText` 导入。
|
||||
- [x] 隔离浏览器使用实际前端同步模块与 IndexedDB、模拟云端 API,执行保存后三次整页刷新和旧事件重放:均保持已同步,未增加草稿或重复提交。不访问真实账号数据。
|
||||
- [ ] 登录真实账号验证问题画布:加载云端、保存、刷新后不再因旧 Agent 事件回到冲突;已有草稿仍可读取。自动化浏览器当前未登录,尚未完成该账号的页面验收。
|
||||
- [x] 画布 operations、Agent 增量合并、事件调度与刷新测试通过,覆盖版本缺口、响应丢失、未确认请求重放、删除后迟到更新和幂等回执。
|
||||
- [x] 前端类型检查与生产构建通过;隔离浏览器使用实际同步模块与 IndexedDB 模拟刷新恢复,未产生重复提交。
|
||||
- [ ] 登录真实账号验证断网、刷新和 Agent 事件缺口:同步面板自动恢复,未确认操作只提交一次,删除节点后迟到结果不复活节点。
|
||||
|
||||
## 画布 Agent 读取参数纠错
|
||||
|
||||
@@ -716,18 +725,13 @@ PR #507 核心能力已按主分支实现保留,并补齐小视口尺寸约束
|
||||
- [ ] 同一张已录入方舟素材 ID 的参考图用于 Agent Plan / 方舟 Seedance 视频生成时,仍可走 `asset://` 并跳过重复上传。
|
||||
- [ ] 官方 `volcengine-ark-image` / `volcengine-ark-video` 行为不变。
|
||||
|
||||
## 画布保存保护与版本记录
|
||||
## 画布 operations 持久化与恢复验收
|
||||
|
||||
已增加版本 CAS、冲突草稿、视口与内容分离、打开时核对云端、历史快照和恢复,以及右侧历史树和独立只读预览。上游云端 Agent 与创作任务使用同一版本和历史事务。专项测试覆盖并发旧写入、断档增量、草稿写入失败、恢复冲突、历史权限、保留数量和历史媒体删除保护。Schema 顺延为 v23,不占用已发布的 v16 Agent 记忆版本。
|
||||
画布写入已统一为字段级、对象级 operations。客户端先把未确认请求写入账号隔离 journal,服务端在同一事务中提交画布 mutation 与 `canvas_mutation_receipts`;响应丢失、断网、刷新和后台重试都复用原 `mutationId` 与原始 payload。内部维护快照只用于资源保护和审计,不作为用户可见的历史树、预览或恢复入口。
|
||||
|
||||
隔离 SQLite/PostgreSQL 的迁移与版本/快照测试已通过;前端构建、类型检查与 lint 通过。真实 Chrome 的组件测试(合成数据与模拟接口)通过了明暗主题、桌面预览缩放、草稿查看、窄屏抽屉、恢复确认与无内容写请求检查;完整登录态和真实生成渠道仍按下列清单验收。
|
||||
|
||||
- [ ] 双标签页编辑同一画布:旧页平移/缩放不发内容 PUT,旧页内容保存收到冲突后保留草稿,另一画布仍可正常保存。
|
||||
- [ ] 出现「版本冲突 · 未同步」后点「加载云端最新版本」:画布不整页卸掉,状态变为已保存或等待保存;平移/缩放不能再次卡死加载。
|
||||
- [ ] 在有未同步编辑时加载最新版或恢复历史,确认本地草稿可下载,恢复后版本递增且恢复前内容仍可找到。
|
||||
- [ ] 明暗主题、桌面和窄屏下检查右侧历史树、草稿页、预览缩放和恢复确认;预览期间快捷键和拖拽不能修改当前编辑器,返回当前画布后可继续生成和编辑。
|
||||
- [ ] 使用真实受控模型验收 Agent 生成任务完成与本地编辑同时发生时的冲突提示;自动化测试不调用收费渠道。
|
||||
- [ ] 既有部署执行 schema 23 迁移并刷新前端,确认旧画布正文保留;历史只从升级后积累,不能恢复升级前已被覆盖的内容。
|
||||
- [x] 后端覆盖显式创建、字段合并、对象基线、幂等回执、原子事务以及删除后迟到更新不重建节点。
|
||||
- [x] 前端覆盖未确认请求 journal、刷新恢复、自动重放、远端完整快照与本地未确认 mutation 合并。
|
||||
- [ ] 双标签页、断网、响应丢失、刷新和 Agent 媒体回写的真实浏览器验收:状态自动恢复,同字段冲突不覆盖远端修改,删除节点后迟到结果不复活节点。
|
||||
|
||||
## 首页常驻滚动通知(2026-09-18)
|
||||
|
||||
@@ -958,12 +962,11 @@ PR #507 核心能力已按主分支实现保留,并补齐小视口尺寸约束
|
||||
- 已补充后端回归用例,覆盖任务状态、输入引用、画布引用、删除事务 Outbox、历史记录保留和自动清理边界;测试包编译通过,本地数据库测试因 `CGO_ENABLED=0` 无法初始化 SQLite,尚未验证通过。
|
||||
- 待部署验收:未绑定画布的生成图片可单个及批量彻底删除;被画布或其他任务输入引用时仍提示来源。删除后任务历史中的原文件不再可用,共享素材仍保留其资源。
|
||||
|
||||
## 画布手动保存与强制覆盖保存
|
||||
## 画布统一 operations 写入与媒体保护
|
||||
|
||||
- 画布左上角菜单新增「保存」(与 ⌘/Ctrl+S 等价,本地落盘后同步云端,适配平板无键盘场景)与「强制覆盖保存」(确认弹窗后以本地内容覆盖云端,并自动修复画布媒体与素材库的绑定)。
|
||||
- 根因修复:同节点原地重生成(如视频节点改提示词后重新生成)走兜底写回路径时,节点保留旧 assetId 却指向新资源,后端画布媒体校验拒绝后,自动修复被节点自身声明掩盖,形成“自动重试但永远失败”。现节点声明不再覆盖素材库真实绑定,错误配对会在下一次自动同步时自愈。
|
||||
- 强制覆盖语义:按服务端素材记录(与本地缓存合并)校验所有画布媒体节点与时间线片段的素材绑定,不一致时重绑到引用同一资源的素材或按节点新建,再按“素材先于画布”整体推送;素材远端版本冲突时采纳远端为基线继续用本地覆盖。后端不变式与接口未改动。
|
||||
- 已通过 `web/test/canvas-asset-repair.test.ts`(8 例)与前端生产构建。待浏览器实测:改提示词原地重生成视频后不再出现“画布媒体与素材库记录不一致”的持续报错;出现历史遗留报错时「强制覆盖保存」能立即恢复且后续自动同步不再报错;平板设备上「保存」菜单可用。
|
||||
- 画布手工编辑、Agent、媒体终态回写、预演台、创作提交和导入均通过统一 operations 服务提交;不存在整批快照覆盖入口。
|
||||
- 素材和画布按“资源先确认、画布后提交”顺序同步。资源缺失或绑定不一致时保留本地内容并进入自动恢复队列,不通过用户选择云端覆盖本地,也不重建来源不明的媒体或插件节点。
|
||||
- 已通过 operations、资源引用、幂等重放和删除顺序专项测试;真实浏览器仍需验证断网恢复、媒体回写和刷新后的状态投影。
|
||||
|
||||
## 欢迎页开放开关
|
||||
|
||||
@@ -1852,14 +1855,12 @@ PR #507 核心能力已按主分支实现保留,并补齐小视口尺寸约束
|
||||
- [ ] 在存储资源页尝试删除当前浅色 Logo、深色 Logo、视频和封面,确认显示“外观”引用并保留文件;解除绑定后可正常删除。
|
||||
- [ ] 将公开配置接口模拟为超时或 5xx,确认 4 秒内结束等待并完整回退内置外观,应用仍可进入。
|
||||
|
||||
## 画布导入同步、素材回收站与历史
|
||||
## 画布导入同步、素材回收站与删除保护
|
||||
|
||||
- [x] 画布压缩包导入会先校验媒体完整性,并统一通过远端同步入口上传资源;失败时保持脏状态和自动重试,不再把浏览器本地 storage key 误报为已同步。
|
||||
- [x] 画布压缩包导入先校验媒体完整性,资源上传和画布写入统一进入 operations journal;失败时保留未确认请求并自动重放,不把浏览器本地 storage key 标记为云端事实。
|
||||
- [x] 素材回收站使用独立归档状态;彻底删除复用服务端引用校验与资源删除 Outbox,自动过期清理不会旁路业务引用。
|
||||
- [x] 已删除画布历史改为按用户 scope 存入 IndexedDB;删除失败不记录历史,共享素材不会因删除单个画布被错误归档。
|
||||
- [ ] 使用两个账号分别删除画布并切换登录,确认历史记录和回收站素材不串账号;刷新后记录仍在,清理历史只影响当前账号。
|
||||
- [ ] 删除仍被其他画布或项目引用的回收站素材,确认服务端拒绝并显示引用来源;解除引用后彻底删除,确认资源记录进入 Outbox 并最终清理物理对象。
|
||||
- [ ] 导入包含图片、视频、音频的真实画布压缩包,分别模拟上传中断和服务端保存失败,确认进度遮罩最终关闭、页面可离开且恢复网络后自动重试。
|
||||
- [x] 画布删除后迟到的媒体或编辑更新不会重新创建画布或节点;只有显式 create operation 可以创建实体。
|
||||
- [ ] 使用两个账号、两个标签页和断网恢复验收导入、删除、刷新与同步状态;确认来源未知的插件包和媒体修改不被清理。
|
||||
|
||||
## 邮箱找回密码
|
||||
|
||||
|
||||
Reference in New Issue
Block a user