「所有资源」页的决策与验收判据跟上当前形态:分带几何口径 + 两页共用同一份布局数据

- decision-log 新增「各栏目按分带铺在同一张画布上」:记分带几何(buildResourceBookAllLayout + resourceBookAllTitlebarRects 复用总览标题栏渲染路径)与冻结口径(只在项目/排序/可见资源集变化时重算,拖动不重算;签名不含 token 的理由),以及本轮不动的三处"仍是另一套"(依赖连线 / 空态分带 / 总览缩略卡网格)与它们的后续顺序
- decision-log 新增「两页共用同一份布局数据」:记裁决(不开独立空间、写回同一 mode 同一 sidecar 的同一 section、提交前减带原点)、"为什么不会写偏"的依据、与"历史手动坐标只读恢复/不删除/不重置/不迁移"不冲突的理由,以及用户可自证的往返判据
- 验收文档 S7 行判据改写:旧判据 data-resource-book-all-page / data-resource-book-all-host 已随网格分支删除,改钉 .game-resource-book-scene-card[data-resource-book-category](每张资源恰好一个宿主)、.is-active[data-resource-book-category="all"] 与 .game-resource-book-view;补上"展开态可拖且在栏目页看到同一位置"这条往返判据
- 验收文档 S7 期望结果同步:由"汇总页"改为"与栏目页同一套画本场景、各栏目按竖向分带铺开"
This commit is contained in:
2026-09-11 23:40:12 +08:00
parent 0d98bd05cc
commit 85358b2ca5
2 changed files with 19 additions and 1 deletions
@@ -8441,3 +8441,21 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
- 验证方式:`resolveResourceCanvasToolbarActions` 单测由「角色资源只放行快速编辑与下载」**改写**为「放行 `['quick-edit','character-animation','download']`」(四不写:旧断言描述未接通状态,已被真实链路取代,不留墓碑),并新增三条反向守卫(非角色图片不放行 / 角色图未登记为正式素材不放行 / 非栅格角色图不放行);AGC 端到端新增「从角色资源卡生成动画」用例,断言 `editKind` / `generationMode` / `prompt` / `assetName` / `sourceAssetId` / 泥点价档位,并断言**参数入口不存在**。变异验证三条(均已实测红灯):去掉 `onOpenCharacterAnimationPanel` 接线 → 端到端用例找不到动画面板;把 `character-animation` 无条件放行 → 三条反向守卫红灯;把档位常量改成 `480p` → 泥点价断言红灯(`生成40泥点``80泥点`)。
- 需要同步的既有文档(**本次只报告,不改远程 Issue**):Issue #309 §三 C3 的「明确未做」与 §六、以及 PR #316 的「明确未做」第 1 条现在需要改写——`character-animation` 已接通,「改造」按"改造 = 快速编辑"收口,其余 6 项(裁扩 / 去背景 / 完美像素 / 拆分图集 / 提取素材 / 参考图选择)保持未接通且已给出逐项证据。这两处都是远程写操作,等用户确认后再动。
- 关联:Issue #309C3)、`apps/ai-game-creator-shell/src/features/resource-canvas/resourceCanvasToolbarModel.ts``apps/ai-game-creator-shell/src/view/project-development/{index.tsx,resourceEditModel.ts}``src/components/image-editor/ImageCanvasCharacterAnimationPanelView.tsx``apps/ai-game-creator-shell/tests/{resourceCanvasToolbarModel.test.ts,projectResourceLiveIntegration.test.tsx}``apps/ai-game-creator-shell/src-tauri/src/project/resource_editor.rs`:111-123 editKind 枚举、:1222-1230 create 分支硬拦、:2314-2351 CharacterAnimation 路由、:2444-2458 远端路由白名单)。
## 2026-09-11 「所有资源」页改走画本场景:各栏目按"分带"铺在同一张画布上,卡片与栏目页同一套
- 背景:用户报「现在的所有资源里为啥还是旧的样式,我希望它和普通画布一样」,并追加裁定「要的,所有的画布都一样」。此前「所有资源」是 `RESOURCE_BOOK_ALL_TARGET = 'all'` 那一页**自己的一条渲染分支**:整页 host(`data-resource-book-all-host`+ `.game-resource-all-*` 网格 + `renderCard(..., { draggable: false })`,与栏目页的"画本场景"(`.game-resource-book-scene-card` 宿主 + FLIP 转场)是两套。本次把那一页整条删除,交给同一份 `buildResourceBookScenePlan``ResourceBookScene` → 同一颗 `renderCard`
- 决策一(分带几何):卡片坐标是**栏目内局部坐标**(`resourceCanvasSectionExtent` 按 section 量;`reconcileResourceCanvasLayout` 按 section 分组后各自从近 0 开始),铺进同一张画布前必须各给一个带原点,否则各栏目全叠在原点。新增纯函数 `buildResourceBookAllLayout`:按栏目的总览顺序纵向排带,带宽高取该栏目**可见资源**的 extent(被筛掉的栏目不占屏,与旧网格页"只保留有资源的栏目"同口径),每带含"标题栏横带 + 卡片区"。标题栏矩形由 `resourceBookAllTitlebarRects` 给出,于是展开态复用总览态"按矩形把栏目标题栏钉在世界坐标上"的同一条渲染路径,`ResourceBookScene` 不需要知道"展开态"这个概念(**场景组件本次一行未改**)。展开态下 `all` 自己只出钉住的标题栏与全量计数,卡片由各**真实栏目**组承载:每张资源只属于一个栏目,所以每张卡在场景里仍然只有一个宿主(`card:*` 键不会撞车)。
- 决策二(冻结口径):带高来自 extent,而拖动会改 extent,所以带几何必须冻结——否则"拖上面一带的一张卡,后面所有带整体往下位移"。口径:**只在 `项目 / 排序 / 可见资源集` 变化时重算**,拖动不重算;实现是"签名 + ref 短路",签名**刻意不含 `resourceBookState.token`**——返回总览时 token 也会变,含它就会在 `returning-main` 的淡出期间重算一遍,正在淡出的卡会贴到新带上(因此返回总览改用"刚离开的那段子画布"记号 `resourceBookLastChildTargetRef`,并按带偏移位置淡出)。
- 不做什么:不碰转场层(`resourceBookController` 一行未改)、不复制平行样式(**本次零新增 CSS**,反而删掉 `.game-resource-all-*` 六条)、不改任何 `data-*` 可读属性名。总览态(8 张栏目缩略卡网格)、空项目那套分带占位(`game-resource-section-stack`)、依赖连线覆盖层(`ResourceDependencyOverlay`)这三处"仍是另一套"的面**本轮不动**,按风险从低到高(连线 → 空态 → 总览几何)列为后续。
- 验证方式:`resourceBookModel.test` 钉住展开态 presentation(真实栏目 `child``all` `null`)与"栏目页仍是原判据";`resourceBookLayout.test` 新增分带几何 / 标题栏矩形 / 换算 / 展开态计划四组断言,其中"每张资源在展开态只有一个宿主"钉住没有第二份宿主;appSurface 两处「所有资源」判据改钉画本场景(`.game-resource-book-scene-card[data-resource-book-category]``.is-active[data-resource-book-category="all"]`)并反向断言旧网格容器与宿主都不再存在。变异验证(均已实测红灯):把展开态 presentation 改回 `null`(等价旧形态)→ 模型用例与 appSurface 用例同时红;去掉"减带原点"→ 换算用例红。
- 关联文档:`docs/technical/【测试用例】AGC资源工作台V3端到端验收-2026-09-11.md`S7 行判据已按新形态改写)、`apps/ai-game-creator-shell/src/view/project-development/{resourceBookModel.ts,resourceBookLayout.ts,index.tsx}`
## 2026-09-11 「所有资源」页与栏目页共用同一份布局数据:拖动写回减掉带原点,不新增第二份空间
- 背景:展开态放开拖动后必须回答"拖这张卡写回哪一份数据"。直觉方案是给「所有资源」页开独立空间(新 mode,或 sidecar 内加 `all` 分区),但那与"同一张卡只有一份坐标"相冲,还要新增持久化口径、Rust 校验与迁移,属于平行系统。
- 决策:**没有也不需要独立空间**。拖动写回的是**同一 mode 的同一 sidecar**`.agent/workbench/resource-layouts/{dependency,type}.json``mode` = 当前排序模式)、**同一 `section = resource.category`**,只是提交前用 `resourceBookAllBandLocalPoint` 把"分带世界坐标"减回"栏目内局部坐标"。因此栏目页与「所有资源」页互相看见对方的位置:在任一页拖动,另一页立刻看到同一个新位置。
- 为什么不会写偏:换算只有一处出口且是纯函数(有单测钉住方向);减的是**渲染时用的同一份冻结分带几何**(同一个 `resourceBookAllLayout`),不是另算一份;`section` 取资源当前分类(永远不是 `all`),落盘值仍只可能是 `ProjectResourceCanvasCategory`Rust `validate_resource_layout_positions` 的既有校验继续成立。
- 与"历史手动坐标只读恢复、不删除、不重置、不迁移"的关系:**不冲突**。写侧只做"把这一张卡在它自己栏目里的坐标设为手动 + 新 x/y",正是栏目页拖动的同一操作(`moveResourceCanvasPosition` 只改该 `(resourceId, section)` 一条并置 `manuallyPlaced: true`);读时归并(`normalizeResourceCanvasPosition`)与"不触发 automatic 重排"的既有口径都未改动。
- 验证方式:`resourceBookAllBandLocalPoint` 两条单测(减带原点 / 栏目页与无带时原样返回);变异验证:去掉减带原点 → 用例红(实测 `{x:100,y:260}` vs 期望 `{x:100,y:160}`)。真机判据(用户可自证"同一份数据"):在展开态把某张卡拖到新位置 → 进它所属栏目页,同一张卡就在新位置;反向在栏目页拖一张 → 回展开态看它在带内同步。
- 关联文档:`docs/technical/【测试用例】AGC资源工作台V3端到端验收-2026-09-11.md`S7 判据含这条往返)、`apps/ai-game-creator-shell/src/view/project-development/{useProjectResourceCanvasLayout.ts,resourceBookLayout.ts,index.tsx}`
@@ -46,7 +46,7 @@
| 步骤 | 操作 | 期望结果 | 对应 PRD 条款 | 怎么判"过了" | 已知例外 / 未做项 |
| --- | --- | --- | --- | --- | --- |
| **S7** 栏目导航 | 点总览第 0 张「所有资源」卡 → 栏目缩略卡片进栏目 → 页内底部「下一页」 | 「所有资源」是汇总页(第 0 张);全部栏目(含空栏目)都可到达;左侧悬浮栏目大纲导航已删除;滚轮不切栏目 | L56、L512、L539541 | `[data-resource-book-all-page="true"]``[data-resource-book-all-host="true"]``[data-resource-book-view="main"\|"child"]`、当前栏目 `.game-resource-book-scene-titlebar.is-active[data-resource-book-category]` | 「所有资源」卡渲染真实预览属**未提交改动**`game-resource-book-preview-card`;旧构建只有占位摞 |
| **S7** 栏目导航 | 点总览第 0 张「所有资源」卡 → 栏目缩略卡片进栏目 → 页内底部「下一页」 | 「所有资源」是入口(第 0 张);进入后**与栏目页是同一套画本场景**——卡片宿主同为 `.game-resource-book-scene-card`、每张卡可拖、可滚轮缩放平移,各栏目按**竖向分带**铺在同一张画布上;全部栏目(含空栏目)都可到达;左侧悬浮栏目大纲导航已删除;滚轮不切栏目 | L56、L512、L539541 | `[data-resource-book-view="main"\|"child"]`、当前栏目 `.game-resource-book-scene-titlebar.is-active[data-resource-book-category]`(展开态这一条是 `data-resource-book-category="all"`,带「资源总览」收起入口)、卡片宿主 `.game-resource-book-scene-card[data-resource-book-category="<真实栏目>"]`(每张资源**恰好一个**宿主)、`[data-resource-book-section-scroll]`。**旧的独立网格判据已随分支删除**:`[data-resource-book-all-page="true"]` / `[data-resource-book-all-host="true"]` / `.game-resource-all-*` 都不应再出现。拖动的判据:在展开态拖一张卡,再进它所属栏目页看同一张卡**落在新位置**(两页共用同一份 `resource-layouts/{dependency,type}.json` 的栏目内局部坐标) | 「所有资源」卡渲染真实预览(`game-resource-book-preview-card`**已提交**`ea9668e4a`);旧构建只有占位摞。展开态的视口是内存态(不落盘),只有卡片坐标落盘 |
| **S8** 搜索 | 点右下角 `搜索资源` 按钮或按 `Ctrl/Cmd+F` → 输入 → Esc | 浮层收起**不清搜索条件**;`type=search` 原生 Esc 清空被 `preventDefault` 挡掉;存在搜索时 Dock 按钮高亮 | L55、L322(搜索只隐藏卡片、不重排坐标) | `button[aria-label="搜索资源"]``aria-expanded``title="搜索资源(Ctrl/Cmd+F"``.is-active`;输入框 `input[type=search][aria-label="搜索项目资源"]`,其 `id` 等于按钮的 `aria-controls` | 匹配字段 = **名称 / 路径 / 媒体类型 / 任务标题**,不含 `sourceLabel` |
| **S9** 选择与多选 | 单击卡片 → `Shift`/`Ctrl`/`Meta` 再点 → 空白处拖拽框选 | 点卡 = 选中并在卡片旁浮出工具条;三种修饰键等效追加;框选可见选框 | L51、L6162、L318319 | `data-resource-card-id` + class 含 `is-selected` + `aria-pressed="true"`;浮出容器 `role="toolbar"`(图片 `aria-label="图片工具栏"`,音频 `"素材工具栏"` | ⚠️ **PRD L61–62 要求的「打开详情」按钮在代码中不存在**(测试显式断言为 `null`),按 Issue #309 C3「取消资源详情面板与全屏编辑路由」判,不要判为缺失;真正入口是 `aria-label="选中资源:<栏目> <名>"` 按钮。**只读信息浮层已回归**(2026-09-11,工具条「信息」动作,见 `decision-log`):**C3 取消的仍只是可编辑详情面板与全屏编辑路由** |
| **S10** 快速编辑(图片) | 选中 PNG/JPEG/WEBP 卡 → 工具条「快速编辑」→ 输入 → 提交(提示词下方另有「AI 润色」) | 先 `normalize_local_project_raster_resource`,再 `derive_local_project_resource(editKind='image-reference')` → 服务端 `/api/editor/images/edits`;**产出一张新素材**,源素材与源文件不变,新资源带 `referenceResourceIds` 血缘 | L123、L193、L476478、L557#309 C3/C10 | 提交后 `assets[]` +1、卡片 +1 且 `data-resource-card-id` 为新 id;**源卡仍在且内容未变**;工具条真渲染的只有 `quick-edit``download`;「AI 润色」`aria-label="AI 润色"` + `aria-busy`,成功回填并出现「恢复原文」,失败保留原文并给「AI 润色失败,可重试」 | ① 服务端白名单 17 项(`editor_project.rs:4120-4141`),`character-animation`/`video`/`audio`/`document`/`code` 等**仍会 400**;② 工具条 7 个动作(重绘 / 裁剪扩图 / 去背景 / 像素完美 / 切图集 / 提取 UI 素材 / 角色动画)按 opt-in **不渲染**;③ 润色结果超 `resourceEditPromptMaxLength` 会**截断并提示「已按长度上限截断」**;④ 提示词变了(改写或润色回填)必须换 `operationId`/幂等键,否则 Rust `request_fingerprint` 判「已绑定到不同资源编辑请求」 |