Add VectorEngine image generation config and raise request timeouts (env + scripts) from 180000 to 1000000ms. Introduce a reusable CreativeImageInputPanel component with tests and wire up mobile keyboard-focus helpers; update generation views and related tests (CustomWorldGenerationView, BarkBattle editor, Match3D, Puzzle flows). Improve API error handling / VectorEngine request guidance (packages/shared http.ts and docs), and apply multiple backend/frontend fixes for puzzle/match3d/prompt handling. Also include extensive docs and decision-log updates describing UI/UX decisions and verification steps.
285 lines
7.9 KiB
TypeScript
285 lines
7.9 KiB
TypeScript
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<Match3DWorksResponse>(
|
|
MATCH3D_WORKS_API_BASE,
|
|
{ method: 'GET' },
|
|
'读取抓大鹅作品列表失败',
|
|
{ retry: MATCH3D_WORKS_READ_RETRY },
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 读取公开抓大鹅作品列表。
|
|
*/
|
|
export function listMatch3DGallery() {
|
|
return requestJson<Match3DWorksResponse>(
|
|
MATCH3D_GALLERY_API_BASE,
|
|
{ method: 'GET' },
|
|
'读取抓大鹅广场失败',
|
|
{
|
|
retry: MATCH3D_WORKS_READ_RETRY,
|
|
skipAuth: true,
|
|
skipRefresh: true,
|
|
},
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 读取抓大鹅作品详情。
|
|
*/
|
|
export function getMatch3DWorkDetail(profileId: string) {
|
|
return requestJson<Match3DWorkDetailResponse>(
|
|
`${MATCH3D_WORKS_API_BASE}/${encodeURIComponent(profileId)}`,
|
|
{ method: 'GET' },
|
|
'读取抓大鹅作品详情失败',
|
|
{ retry: MATCH3D_WORKS_READ_RETRY },
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 保存结果页可编辑字段。
|
|
*/
|
|
export function updateMatch3DWork(
|
|
profileId: string,
|
|
payload: PutMatch3DWorkRequest,
|
|
) {
|
|
return requestJson<Match3DWorkMutationResponse>(
|
|
`${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<Match3DWorkMutationResponse>(
|
|
`${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<PersistMatch3DGeneratedModelResponse>(
|
|
`${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<GenerateMatch3DCoverImageResponse>(
|
|
`${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<GenerateMatch3DBackgroundImageResponse>(
|
|
`${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<GenerateMatch3DContainerImageResponse>(
|
|
`${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<GenerateMatch3DItemAssetsResponse>(
|
|
`${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<GenerateMatch3DWorkTagsResponse>(
|
|
`${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<Match3DWorkMutationResponse>(
|
|
`${MATCH3D_WORKS_API_BASE}/${encodeURIComponent(profileId)}/publish`,
|
|
{ method: 'POST' },
|
|
'发布抓大鹅作品失败',
|
|
{ retry: MATCH3D_WORKS_WRITE_RETRY },
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 删除当前用户的抓大鹅作品,并返回删除后的列表。
|
|
*/
|
|
export function deleteMatch3DWork(profileId: string) {
|
|
return requestJson<Match3DWorksResponse>(
|
|
`${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,
|
|
};
|