沉淀 AGC 画布现状与取数约束到共享记忆
- pitfalls.md 追加「AGC 走不了网页端 /api/editor 的取数链」:Tauri asset 协议 + CSP connect-src 未放行平台域名,且 dev 的 vite /api 代理会造成「能跑」假象 - pitfalls.md 追加「ImageCanvasStageView 是硬组合容器」:132 props(57 数据 + 75 回调)、无条件渲染 8 个子视图、83/132 需宿主伪造编辑器状态,且不透传 supportedActions - pitfalls.md 追加「AGC 资源画布真正自制的交互面」:resourceBookViewport.ts、resourceCanvasLayoutModel.ts 的 fit/normalize、index.tsx 3656-4090 指针段,并记录两条平移路径守卫不一致与右键菜单、chrome 样式缺口 - pitfalls.md 追加「资源画布工具条改造/角色动画按钮点了没反应」:空回调仍留在 supportedActions 里,按钮渲染但无人接
This commit is contained in:
@@ -5068,3 +5068,41 @@
|
|||||||
- 运行时结论(已核实,可放心):`hostBridge.ts` 的模块作用域只有常量与缓存声明,**没有导入即执行的副作用**;`window.wx` 只在函数体内访问,`ReactNativeWebView` 有 `typeof window !== 'undefined'` 守卫。所以这条链被编进 AGC bundle 是惰性的。
|
- 运行时结论(已核实,可放心):`hostBridge.ts` 的模块作用域只有常量与缓存声明,**没有导入即执行的副作用**;`window.wx` 只在函数体内访问,`ReactNativeWebView` 有 `typeof window !== 'undefined'` 守卫。所以这条链被编进 AGC bundle 是惰性的。
|
||||||
- 通用规则:**今后任何往 AGC 引 `src/components/image-editor/` 组件的改动,都要先检查这条链**(组件 → `ImageCanvasGenerationModel` → `apiClient` → `hostBridge`),并确认新增的跨端全局在 AGC 侧有声明。
|
- 通用规则:**今后任何往 AGC 引 `src/components/image-editor/` 组件的改动,都要先检查这条链**(组件 → `ImageCanvasGenerationModel` → `apiClient` → `hostBridge`),并确认新增的跨端全局在 AGC 侧有声明。
|
||||||
- 关联:`apps/ai-game-creator-shell/src/vite-env.d.ts`、`src/vite-env.d.ts`、`src/components/image-editor/ImageCanvasGenerationModel.ts`、`src/services/apiClient.ts`、`src/services/host-bridge/hostBridge.ts`。
|
- 关联:`apps/ai-game-creator-shell/src/vite-env.d.ts`、`src/vite-env.d.ts`、`src/components/image-editor/ImageCanvasGenerationModel.ts`、`src/services/apiClient.ts`、`src/services/host-bridge/hostBridge.ts`。
|
||||||
|
|
||||||
|
## AGC 走不了网页端 `/api/editor/...` 的取数链(Tauri asset 协议 + CSP 双约束)(2026-09-10)
|
||||||
|
|
||||||
|
- 现象:把网页端图片画布的服务模块(`src/services/image-editor/editorProjectClient.ts`)引到 AGC 后,`loadEditorProject` / `loadOrCreateRecentEditorProject` 一类调用在打包态(真机 Tauri 客户端)拉不到任何数据。
|
||||||
|
- 原因(两条独立约束,缺一不可绕过):
|
||||||
|
1. **相对路径**:该模块全部经 `src/services/apiClient.ts` 的 `requestJson` / `fetchWithApiAuth` 发请求,最终落到**裸 `window.fetch('/api/...')`**(相对路径 + `credentials: 'same-origin'`)。AGC 打包态页面来自 Tauri asset 协议(`frontendDist: ../dist`),相对 `/api/...` 打到 asset 协议自身,永远到不了 api-server。
|
||||||
|
2. **CSP**:`apps/ai-game-creator-shell/src-tauri/tauri.conf.json` 的 `connect-src` 只放行 `'self'`、`https://agc-dev.oss-rg-china-mainland.aliyuncs.com`、`http://127.0.0.1:*`、`ws://127.0.0.1:*`(`devCsp` 同口径)。`https://dev.genarrative.world` 与 `https://www.genarrative.world` **都不在名单里**——即便改成绝对地址也会被 WebView 拒掉。
|
||||||
|
- 处理(结论):AGC 访问平台接口**只能**经 `apps/ai-game-creator-shell/src/services/clientHttp.ts::fetchClientHttp`——它把相对路径解析成当前选定服务器的绝对地址,并改走 `@tauri-apps/plugin-http`(Rust 侧发请求,不受 WebView CSP 约束)。因此平台接口在 AGC 侧都要在 `src/services/clientApi.ts` / `src/services/clientAuth.ts` 里包一层宿主实现,例如 `loadEditorAssetLibrary()` 就是同一个 `/api/editor/assets/library` 端点另写的一份。
|
||||||
|
- **判据陷阱**:`npm run dev` 下 AGC 的 vite 配了 `/api` 代理(`apps/ai-game-creator-shell/vite.config.ts` 的 `server.proxy`),那些裸 `fetch('/api/...')` 在 dev 里**看起来能跑**。判断一个网页端模块能不能被 AGC 复用,必须按打包态(asset 协议 + CSP)推演,不能拿 dev 的现象当证据。
|
||||||
|
- 关联:`src/services/image-editor/editorProjectClient.ts`、`src/services/apiClient.ts`、`apps/ai-game-creator-shell/src/services/clientHttp.ts`、`apps/ai-game-creator-shell/src-tauri/tauri.conf.json`、`apps/ai-game-creator-shell/vite.config.ts`。
|
||||||
|
|
||||||
|
## `ImageCanvasStageView` 是硬组合容器,宿主取不到"只要画布"的那部分(2026-09-10)
|
||||||
|
|
||||||
|
- 事实:`src/components/image-editor/ImageCanvasStageView.tsx` 有 **132 个 props**(57 个数据/状态 + 75 个回调,可选仅 10 个),并**无条件渲染 8 个子视图**:`ImageCanvasWorldView`、`ImageCanvasSelectedLayerToolbarView`、`ImageCanvasUiAssetExtractionOverlayView`×2、`ImageCanvasContextMenusView`、`ImageCanvasPanelDockView`、`ImageCanvasTaskSidebarView`、`ImageCanvasBottomToolbarView`(另有开关控制的 `EditorAgentConversationPanelView`)。唯一消费者是 `ImageCanvasEditorShellView`。
|
||||||
|
- 按 props 取值来源分桶:**(a) 纯本地画布状态 49 / (b) 需编辑器状态机 65 / (c) 需后端鉴权 16 / (d) 需宿主文件能力 2**,即 (b)+(c)+(d) = 83(约 63%)需要宿主造出编辑器状态或后端能力才能满足。典型项:`isInteractionPaused`(真身是钱包/充值弹窗组合态)、`editorAgentAssets`(素材库 API)、`taskListRefreshKey` / `isTaskSidebarOpen`(`listExternalGenerationTasks`)、`isAgentConversationEnabled`(`loadFrontendRuntimeConfig()`)、`onSwitchTool`(OSS 上传)、`onExportContextLayer` / `onDownloadLayer`(zip / 下载宿主能力)。
|
||||||
|
- 又一条事实:`ImageCanvasStageView` **不透传** `supportedActions` / `extraActions`(它在 `:408-437` 直接渲染子工具条,props 列表里没有这两个字段)。所以宿主想让「自己没接通的工具条动作」不渲染,**只能绕过 StageView 直接挂 `ImageCanvasSelectedLayerToolbarView`**——AGC 现在就是这么做的。
|
||||||
|
- 结论:AGC 侧复用画布能力按**单个现成件**取用(`ImageCanvasSelectedLayerToolbarView` / `ImageCanvasQuickEditPanelView` / `packages/image-canvas-react` 的 `useImageCanvasStageController` / `ImageCanvasContextMenusView` / `packages/image-canvas-core` 的纯函数),不要整机挂 StageView。
|
||||||
|
- 顺带两条死代码,读代码时别被误导:`persistingAssetKindLayerIds` 在编辑器里从未被传值(`isPersistingAssetKind` 恒 false);`ImageCanvasContextMenusView` 的 `canvasClipboard` 是必填 prop,但组件内解构为 `_canvasClipboard` 后完全不用。
|
||||||
|
- 关联:`src/components/image-editor/ImageCanvasStageView.tsx`、`ImageCanvasContextMenusView.tsx`、`ImageCanvasEditorShellView.tsx`、`ImageCanvasEditorView.tsx`。
|
||||||
|
|
||||||
|
## AGC 资源画布真正自制的交互面(改画布 bug 前先看这里)(2026-09-10)
|
||||||
|
|
||||||
|
- 已经接成共享件的部分:`view/project-development/index.tsx` 用了 `@genarrative/image-canvas-core` 的 `createCanvasMarqueeState` / `getPointerClient` / `selectLayersInsideMarquee` / `resolveSelectedToolbarStyle` / `resolveQuickEditPanelStyle` / `MIN_SCALE` / `MAX_SCALE` / `resolveViewportFromWheel`,以及 `@genarrative/image-canvas-react` 的 `CanvasChromeButton` / `SelectionOverlay`;工具条与快速编辑浮层直接复用 `ImageCanvasSelectedLayerToolbarView` / `ImageCanvasQuickEditPanelView`。
|
||||||
|
- **仍然自制的部分**(都有自己的单测,改前先跑对应的 `apps/ai-game-creator-shell/tests/*`):
|
||||||
|
- `view/project-development/resourceBookViewport.ts`:`normalizeResourceBookViewport`、`zoomResourceBookViewport`、`panResourceBookViewport`、`keepResourceBookViewportAtReadableScale`、`ensureResourceBookContentVisible`、`resolveResourceBookWheelViewport`(最后一个只是给共享 `resolveViewportFromWheel` 加了一层 normalize)。
|
||||||
|
- `view/project-development/resourceCanvasLayoutModel.ts` 的 `normalizeInfiniteResourceCanvasViewport`(与 `resourceBookViewport.ts` 的 `normalizeResourceBookViewport` **是同一套语义的两份实现**)与 `fitResourceCanvasViewportToContent`:后者的 `maxScale` 默认放到 1.5,**不**像 core 的 `fitViewportToBounds` 那样封顶 1:1——这是刻意差异,别照着 core 去"对齐"。
|
||||||
|
- `index.tsx` 的指针/滚轮/缩放段(约 `:3656-4090`):`resetResourceCanvasViewport`、`fitResourceBook`、`zoomResourceBookBy`、`handleResourceBookMainPointerMove`、`handleResourceCanvasPointerDown` / `PointerMove`、`stopResourceCanvasPan`。
|
||||||
|
- 一处**行为不一致**(改平移相关 bug 时优先怀疑这里):主画布平移走 `panResourceBookViewport`(内部会 normalize),而分栏画布平移在 `index.tsx:4079-4087` 用**内联算式**直接算 `startViewport + delta`,不过 normalize。两条平移路径的守卫不一致。
|
||||||
|
- **右键菜单**:AGC 全仓没有任何画布右键菜单(`ContextMenu` 只出现在 UI 编辑器里)。接共享 `ImageCanvasContextMenusView` 会撞两件事:① 该组件**没有** `supportedActions` 一类的 opt-in(门控只有 `canCopyContextLayers` / `isCanvasClipboardCopyBlocked` / `contextShouldShowLayer` / `contextShouldUnlockLayer` / `contextMenuLayer.mediaType === 'image-sequence'` / `imageContextMenuLayer.assetKind === 'character'`),宿主无法声明"哪些动作我真实支持",要新增能力只能按可选 prop opt-in 的既定口径给共享组件加;② `.image-canvas-editor__context-menu*` / `__context-submenu*` 这些类 AGC **一条都没有**。
|
||||||
|
- **样式缺口量化**:AGC 的宿主 chrome 样式集中在 `apps/ai-game-creator-shell/src/features/resource-canvas/resourceCanvasChrome.css`(395 行,`main.tsx:3` 引入),目前只覆盖 **17 个** `image-canvas-editor__*` 类;而网页端 `src/index.css`(15542 行)里这套类有 **451 个、910 处**。样式靠手抄是"样式不齐 / 工具条折行"反复复发的根源,补样式时只补实际用到的那几个类。
|
||||||
|
- 关联:`apps/ai-game-creator-shell/src/view/project-development/resourceBookViewport.ts`、`resourceCanvasLayoutModel.ts`、`index.tsx`、`apps/ai-game-creator-shell/src/features/resource-canvas/resourceCanvasChrome.css`、`apps/ai-game-creator-shell/tests/resourceBookViewport.test.ts`、`apps/ai-game-creator-shell/tests/resourceCanvasLayoutModel.test.ts`。
|
||||||
|
|
||||||
|
## 资源画布工具条的「改造」「角色动画」按钮点了没反应(2026-09-10)
|
||||||
|
|
||||||
|
- 现象:选中一张可用资源卡后,浮出工具条上出现「改造」按钮(音频卡同样)或「角色动画」按钮,点击没有任何反应——属于"点了没反应的按钮"这一类。
|
||||||
|
- 原因:AGC 在 `view/project-development/index.tsx:5405-5417` 挂 `ImageCanvasSelectedLayerToolbarView` 时把 `onOpenRedrawPanel`(`:5406`)与 `onOpenCharacterAnimationPanel`(`:5416`)传成了**空回调**(同一处另有 6 个空回调:`onOpenCropExpandPanel` / `onRemoveBackground` / `onPerfectPixel` / `onSplitIconSpritesheet` / `onExtractUiDesignAssets` / `onDownloadLayer`),但 `features/resource-canvas/resourceCanvasToolbarModel.ts` 的 `resolveResourceCanvasToolbarActions` **仍然把 `redraw` 放进了 supportedActions**:图片/视频/音频只要 `canDeriveFromResource` 就加 `redraw`,`assetKind === 'character'` 再加 `character-animation`。于是这两个动作**渲染出来了但没人接**;其余动作没进集合,按钮不渲染,所以线上只在这两处暴露。
|
||||||
|
- 处理方向(尚未修):要么给这两个动作接上真实链路,要么把它们从 `resolveResourceCanvasToolbarActions` 的返回集合里去掉。判据是「渲染出来的动作必须真的能跑通」,而不是「先把按钮显示出来」。
|
||||||
|
- 关联:`apps/ai-game-creator-shell/src/view/project-development/index.tsx`、`apps/ai-game-creator-shell/src/features/resource-canvas/resourceCanvasToolbarModel.ts`、`src/components/image-editor/ImageCanvasSelectedLayerToolbarView.tsx`(`:87-90` 判定、`:300-311` 图片分支「改造」、`:289-300` 「角色动画」)。
|
||||||
|
|||||||
Reference in New Issue
Block a user