修复 AGC 图片快速编辑被平台 400 拒绝:来源类型表改为与共享契约对齐的静态图集合

- `ensure_editor_image_edit_source_kind_allowed` 的白名单换成静态图类型表 `EDITOR_IMAGE_EDIT_STATIC_IMAGE_ASSET_KINDS`(canonical 静态图类型 + 合法 legacy 类型)
- 保留 `mediaType == image` 的 AND 门,视频 / 音频 / 序列帧等非静态媒体照旧拒绝
- 覆盖实测被拒的 `art-spritesheet` / `ui`,以及 canonical 映射输入域 `art-spritesheet-slice` / `ui-prototype` / `game-art` / `game-background` / `character-art` / `illustration`
This commit is contained in:
2026-09-10 19:00:52 +08:00
parent 6a11032084
commit 9e59abde53
@@ -4105,24 +4105,50 @@ fn align_editor_image_edit_dimension(value: u32) -> u32 {
value.saturating_add(15) / 16 * 16
}
/// 图片快速编辑端点允许的**静态图**来源类型。
///
/// 口径依据 `packages/shared/src/contracts/gameCreationApp.ts` 的
/// `canonicalGameCreationAppAssetKind()`(等价实现见
/// `server-rs/crates/shared-contracts/src/game_creation_app.rs`):以「媒体类型为静态图的
/// canonical 类型」为权威集合,并额外收下合法 legacy 类型本身(平台还有别的写入口按本地
/// manifest 原始类型登记来源资源,客户端不会先做 canonical 归一)。
/// `canonicalGameCreationAppAssetKind()` 对未知值回退 `image`,因此两个入口都放行的这些值
/// 在共享契约里语义等价,静态图集合对 canonical 归一封闭,不会漏放合法静态图来源。
///
/// 必须与 `media_type == image` 一起构成 AND 门:视频、音频、序列帧等非静态媒体即使挂着
/// 图片类 assetKind 也照旧拒绝。
pub(crate) const EDITOR_IMAGE_EDIT_STATIC_IMAGE_ASSET_KINDS: [&str; 17] = [
// canonical 静态图类型
"image",
"scene",
"character",
"icon",
"icon-spritesheet",
"icon-spec",
"ui-design",
"publication-material",
"spec",
// 指向上述 canonical 类型的合法 legacy 类型
"game-background",
"character-art",
"game-art",
"illustration",
"art-spritesheet",
"art-spritesheet-slice",
"ui-prototype",
// AGC 本地 manifest 等在用的等价静态图类型
"ui",
];
pub(crate) fn ensure_editor_image_edit_source_kind_allowed(
asset_kind: Option<&str>,
media_type: Option<&str>,
) -> Result<(), AppError> {
let asset_kind = asset_kind.map(str::trim).filter(|value| !value.is_empty());
let media_type = media_type.map(str::trim).filter(|value| !value.is_empty());
let asset_kind_allowed = matches!(
asset_kind,
None | Some(
"spec"
| "character"
| "icon-spritesheet"
| "icon-spec"
| "publication-material"
| "ui-design"
| "scene"
)
);
let asset_kind_allowed = asset_kind.is_none_or(|asset_kind| {
EDITOR_IMAGE_EDIT_STATIC_IMAGE_ASSET_KINDS.contains(&asset_kind)
});
let media_type_allowed = matches!(media_type, None | Some("image"));
if asset_kind_allowed && media_type_allowed {
return Ok(());