feat: 前端改为通过签名地址读取生成资源

This commit is contained in:
2026-04-21 16:45:05 +08:00
parent fcaf7bdb38
commit 78dcad1222
26 changed files with 779 additions and 76 deletions

View File

@@ -115,7 +115,7 @@
结论:
- 所有图片、动画、精灵表、场景图、封面图、视频参考素材都存 OSS。
- SpacetimeDB 只存对象键、版本、尺寸、状态、逻辑元数据,不存二进制。
- SpacetimeDB 只存 `bucket`对象键、版本、尺寸、状态、逻辑元数据,不存二进制。
- Axum 负责下发直传凭证、校验上传结果、补写元数据。
## 4. 目标总体架构
@@ -429,7 +429,10 @@ server-rs/
1. 任务状态在 SpacetimeDB。
2. 二进制对象在 OSS。
3. 所有业务实体只引用 `asset_object_key / cdn_url / version / hash`
3. `asset_object` 的正式真相字段固定为 `bucket + object_key`
4. 所有 URL 都只作为派生读模型,不作为对象主键存储。
5. `asset_object` 的首版字段、访问级别与索引设计见:
- [SPACETIMEDB_ASSET_OBJECT_TABLE_DESIGN_2026-04-21.md](./SPACETIMEDB_ASSET_OBJECT_TABLE_DESIGN_2026-04-21.md)
## 8.2 public / private 原则
@@ -603,20 +606,27 @@ workflow-cache/{workflow_type}/{workflow_id}.json
1. `server-rs/crates/platform-oss` 已提供 `PostObject` 直传签名能力。
2. `server-rs/crates/api-server` 已暴露 `POST /api/assets/direct-upload-tickets`
3. 该接口当前输出:
3. `server-rs/crates/platform-oss` 已提供私有对象 `GET` 短期签名 URL 能力。
4. `server-rs/crates/api-server` 已暴露 `GET /api/assets/read-url`
5. 上传接口当前输出:
- `bucket`
- `objectKey`
- `legacyPublicPath`
- `publicUrl`
- `formFields`
- `expiresAt`
4. 当前签名链路优先兼容旧公开前缀
6. 读取接口当前支持
- `objectKey`
- `legacyPublicPath`
- `expireSeconds`
7. 当前 bucket 已明确为私有读写,因此 `publicUrl` 不再作为正式对象真相输出。
8. 当前签名链路优先兼容旧公开前缀:
- `/generated-character-drafts/*`
- `/generated-characters/*`
- `/generated-animations/*`
- `/generated-custom-world-scenes/*`
- `/generated-custom-world-covers/*`
- `/generated-qwen-sprites/*`
5. `STS`、服务端上传 helper、对象确认与业务绑定仍在后续阶段补齐。
9. `STS`、服务端上传 helper、对象确认与业务绑定仍在后续阶段补齐。
## 11.3 元数据与标签
@@ -639,9 +649,9 @@ workflow-cache/{workflow_type}/{workflow_id}.json
建议:
1. 业务表里统一存 `object_key`
2. 对外输出 `cdn_url`
3. 私有对象额外输出短期签名 URL
1. 业务表里统一存 `bucket + object_key`
2. 对外输出 `cdn_url` 或签名 URL
3. 私有对象默认输出短期签名 URL,而不是假设匿名公开读
为了兼容当前前端相对路径使用习惯,第一阶段可以让 Axum 或 CDN 兼容以下历史前缀:
@@ -652,6 +662,19 @@ workflow-cache/{workflow_type}/{workflow_id}.json
5. `/generated-custom-world-covers/*`
6. `/generated-qwen-sprites/*`
补充约束:
1. 当前 `xushi-dev` bucket 已明确为私有读写,因此这些旧前缀在第一阶段只代表兼容路径习惯,不代表对象可匿名读取。
2. Web 端若拿到的是历史 `/generated-*` 路径,必须先调用 `GET /api/assets/read-url` 换取 `signedUrl`,不能直接把该路径当成正式可读 URL。
3. 前端工程内凡是图片、背景图、封面图、角色图、场景图等展示入口,只要可能接收到 `/generated-*`,都必须统一走资源解析层:
- 列表/卡片/普通 `<img>` 优先复用 `src/services/assetReadUrlService.ts`
- 组件内优先复用 `src/hooks/useResolvedAssetReadUrl.ts`
- 通用图片标签优先复用 `src/components/ResolvedAssetImage.tsx`
- 当前已完成的高优先级入口包括:`CharacterAnimator``CharacterPanel``CompanionCampModal``CharacterSelectionFlow``MapModal``GameCanvasSceneLayer``GameCanvasShared``GameCanvasEntityLayer``CustomWorldResultView``CustomWorldEntityEditorModal``CustomWorldRoleAssetStudioModal``CustomWorldAgentDraftDetailPanel``PlatformHomeView``PlatformWorldDetailView``QwenSpriteSheetTool`
4. 对私有 OSS 资源,前端在签名地址返回前不能先回退渲染原始 `/generated-*` 路径,否则浏览器会先发起一次无签名请求并触发 `403`
2. 具体对象引用设计见:
- [SPACETIMEDB_ASSET_OBJECT_STORAGE_DESIGN_2026-04-21.md](./SPACETIMEDB_ASSET_OBJECT_STORAGE_DESIGN_2026-04-21.md)
## 12. 关键业务流设计
## 12.1 Story Action