import type { GenerateMatch3DBackgroundImageRequest, GenerateMatch3DBackgroundImageResponse, GenerateMatch3DContainerImageRequest, GenerateMatch3DContainerImageResponse, GenerateMatch3DCoverImageRequest, GenerateMatch3DCoverImageResponse, GenerateMatch3DItemAssetsRequest, GenerateMatch3DItemAssetsResponse, GenerateMatch3DWorkTagsRequest, GenerateMatch3DWorkTagsResponse, Match3DWorkDetailResponse, Match3DWorkMutationResponse, Match3DWorksResponse, PersistMatch3DGeneratedModelRequest, PersistMatch3DGeneratedModelResponse, PutMatch3DAudioAssetsRequest, PutMatch3DWorkRequest, } from '../../../packages/shared/src/contracts/match3dWorks'; import { type ApiRetryOptions, requestJson } from '../apiClient'; const MATCH3D_WORKS_API_BASE = '/api/creation/match3d/works'; const MATCH3D_GALLERY_API_BASE = '/api/runtime/match3d/gallery'; const VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS = 1_000_000; const MATCH3D_WORKS_READ_RETRY: ApiRetryOptions = { maxRetries: 1, baseDelayMs: 120, maxDelayMs: 360, }; const MATCH3D_WORKS_WRITE_RETRY: ApiRetryOptions = { maxRetries: 1, baseDelayMs: 120, maxDelayMs: 360, retryUnsafeMethods: true, }; /** * 读取当前用户的抓大鹅作品列表。 */ export function listMatch3DWorks() { return requestJson( MATCH3D_WORKS_API_BASE, { method: 'GET' }, '读取抓大鹅作品列表失败', { retry: MATCH3D_WORKS_READ_RETRY }, ); } /** * 读取公开抓大鹅作品列表。 */ export function listMatch3DGallery() { return requestJson( MATCH3D_GALLERY_API_BASE, { method: 'GET' }, '读取抓大鹅广场失败', { retry: MATCH3D_WORKS_READ_RETRY, skipAuth: true, skipRefresh: true, }, ); } /** * 读取抓大鹅作品详情。 */ export function getMatch3DWorkDetail(profileId: string) { return requestJson( `${MATCH3D_WORKS_API_BASE}/${encodeURIComponent(profileId)}`, { method: 'GET' }, '读取抓大鹅作品详情失败', { retry: MATCH3D_WORKS_READ_RETRY }, ); } /** * 保存结果页可编辑字段。 */ export function updateMatch3DWork( profileId: string, payload: PutMatch3DWorkRequest, ) { return requestJson( `${MATCH3D_WORKS_API_BASE}/${encodeURIComponent(profileId)}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }, '更新抓大鹅作品失败', { retry: MATCH3D_WORKS_WRITE_RETRY }, ); } /** * 保存抓大鹅结果页生成的素材快照。 */ export function updateMatch3DGeneratedItemAssets( profileId: string, payload: PutMatch3DAudioAssetsRequest, ) { return requestJson( `${MATCH3D_WORKS_API_BASE}/${encodeURIComponent(profileId)}/audio-assets`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }, '更新抓大鹅生成素材失败', { retry: MATCH3D_WORKS_WRITE_RETRY }, ); } export const updateMatch3DAudioAssets = updateMatch3DGeneratedItemAssets; /** * 将历史外部 GLB 链接转存为抓大鹅私有模型资产;新草稿不再调用。 */ export function persistMatch3DGeneratedModel( profileId: string, payload: PersistMatch3DGeneratedModelRequest, ) { return requestJson( `${MATCH3D_WORKS_API_BASE}/${encodeURIComponent(profileId)}/generated-models`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }, '保存抓大鹅历史模型失败', { retry: MATCH3D_WORKS_WRITE_RETRY, timeoutMs: 240_000, }, ); } /** * 生成并保存抓大鹅作品封面图。 */ export function generateMatch3DCoverImage( profileId: string, payload: GenerateMatch3DCoverImageRequest, ) { return requestJson( `${MATCH3D_WORKS_API_BASE}/${encodeURIComponent(profileId)}/cover-image`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }, '生成抓大鹅封面图失败', { retry: MATCH3D_WORKS_WRITE_RETRY, timeoutMs: VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS, }, ); } /** * 按画面描述重新生成并保存抓大鹅局内 UI 背景图。 */ export function generateMatch3DBackgroundImage( profileId: string, payload: GenerateMatch3DBackgroundImageRequest, ) { return requestJson( `${MATCH3D_WORKS_API_BASE}/${encodeURIComponent(profileId)}/background-image`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }, '生成抓大鹅背景图失败', { retry: MATCH3D_WORKS_WRITE_RETRY, timeoutMs: VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS, }, ); } /** * 按画面描述重新生成并保存抓大鹅局内容器形象。 */ export function generateMatch3DContainerImage( profileId: string, payload: GenerateMatch3DContainerImageRequest, ) { return requestJson( `${MATCH3D_WORKS_API_BASE}/${encodeURIComponent(profileId)}/container-image`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }, '生成抓大鹅容器形象失败', { retry: MATCH3D_WORKS_WRITE_RETRY, timeoutMs: VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS, }, ); } /** * 按名称批量生成抓大鹅 2D 五视角物品图片。 */ export function generateMatch3DItemAssets( profileId: string, payload: GenerateMatch3DItemAssetsRequest, ) { return requestJson( `${MATCH3D_WORKS_API_BASE}/${encodeURIComponent(profileId)}/item-assets`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }, '生成抓大鹅物品素材失败', { retry: MATCH3D_WORKS_WRITE_RETRY, timeoutMs: 20 * 60 * 1000, }, ); } /** * 根据当前作品名称与题材生成发布标签。 */ export function generateMatch3DWorkTags( payload: GenerateMatch3DWorkTagsRequest, ) { return requestJson( `${MATCH3D_WORKS_API_BASE}/tags`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }, '生成抓大鹅作品标签失败', { retry: MATCH3D_WORKS_WRITE_RETRY }, ); } /** * 发布抓大鹅作品。发布门槛由后端最终确认。 */ export function publishMatch3DWork(profileId: string) { return requestJson( `${MATCH3D_WORKS_API_BASE}/${encodeURIComponent(profileId)}/publish`, { method: 'POST' }, '发布抓大鹅作品失败', { retry: MATCH3D_WORKS_WRITE_RETRY }, ); } /** * 删除当前用户的抓大鹅作品,并返回删除后的列表。 */ export function deleteMatch3DWork(profileId: string) { return requestJson( `${MATCH3D_WORKS_API_BASE}/${encodeURIComponent(profileId)}`, { method: 'DELETE' }, '删除抓大鹅作品失败', { retry: MATCH3D_WORKS_WRITE_RETRY }, ); } export const match3dWorksClient = { delete: deleteMatch3DWork, generateBackgroundImage: generateMatch3DBackgroundImage, generateContainerImage: generateMatch3DContainerImage, generateCoverImage: generateMatch3DCoverImage, generateItemAssets: generateMatch3DItemAssets, generateTags: generateMatch3DWorkTags, getDetail: getMatch3DWorkDetail, listGallery: listMatch3DGallery, list: listMatch3DWorks, persistGeneratedModel: persistMatch3DGeneratedModel, publish: publishMatch3DWork, updateAudioAssets: updateMatch3DAudioAssets, updateGeneratedItemAssets: updateMatch3DGeneratedItemAssets, update: updateMatch3DWork, };