This commit is contained in:
2026-05-14 13:40:50 +08:00
parent 5a55180b78
commit 2dc9d752e4
24 changed files with 1873 additions and 98 deletions

View File

@@ -164,6 +164,8 @@ import {
} from '../../services/match3d-works';
import {
hasMatch3DGeneratedImageAsset,
mergeMatch3DGeneratedItemAssetsForRuntime,
normalizeMatch3DGeneratedItemAssetsForRuntime,
preloadMatch3DGeneratedRuntimeAssets,
} from '../../services/match3dGeneratedModelCache';
import {
@@ -643,7 +645,9 @@ function mapPublicWorkDetailToMatch3DWork(
entry.generatedItemAssets
?.map((asset) => asset.backgroundAsset ?? null)
.find(Boolean) ?? null,
generatedItemAssets: entry.generatedItemAssets ?? [],
generatedItemAssets: normalizeMatch3DGeneratedItemAssetsForRuntime(
entry.generatedItemAssets ?? [],
),
};
}
@@ -678,7 +682,9 @@ function buildMatch3DProfileFromSession(
backgroundImageSrc: draft.backgroundImageSrc ?? null,
backgroundImageObjectKey: draft.backgroundImageObjectKey ?? null,
generatedBackgroundAsset: draft.generatedBackgroundAsset ?? null,
generatedItemAssets: draft.generatedItemAssets,
generatedItemAssets: normalizeMatch3DGeneratedItemAssetsForRuntime(
draft.generatedItemAssets,
),
};
}
@@ -702,7 +708,7 @@ function resolveMatch3DRuntimeGeneratedItemAssets(
if (runProfileId && profile?.profileId === runProfileId) {
if (hasMatch3DRuntimeAsset(profileAssets)) {
return profileAssets;
return normalizeMatch3DGeneratedItemAssetsForRuntime(profileAssets);
}
if (
@@ -711,11 +717,14 @@ function resolveMatch3DRuntimeGeneratedItemAssets(
publicWorkDetail.profileId === runProfileId
) {
return hasMatch3DRuntimeAsset(publicDetailAssets)
? publicDetailAssets
: profileAssets;
? mergeMatch3DGeneratedItemAssetsForRuntime(
publicDetailAssets,
profileAssets,
)
: normalizeMatch3DGeneratedItemAssetsForRuntime(profileAssets);
}
return profileAssets;
return normalizeMatch3DGeneratedItemAssetsForRuntime(profileAssets);
}
if (
@@ -724,13 +733,15 @@ function resolveMatch3DRuntimeGeneratedItemAssets(
isMatch3DGalleryEntry(publicWorkDetail) &&
publicWorkDetail.profileId === runProfileId
) {
return publicDetailAssets;
return normalizeMatch3DGeneratedItemAssetsForRuntime(publicDetailAssets);
}
if (hasMatch3DRuntimeAsset(profileAssets)) {
return profileAssets;
return normalizeMatch3DGeneratedItemAssetsForRuntime(profileAssets);
}
return publicDetailAssets.length > 0 ? publicDetailAssets : profileAssets;
return publicDetailAssets.length > 0
? normalizeMatch3DGeneratedItemAssetsForRuntime(publicDetailAssets)
: normalizeMatch3DGeneratedItemAssetsForRuntime(profileAssets);
}
function resolveActiveMatch3DRuntimeProfile(
@@ -2551,6 +2562,23 @@ export function PlatformEntryFlowShellImpl({
activePuzzleGenerationSessionIdRef.current === sessionId
);
}, []);
const isDraftNoticeGenerating = useCallback(
(kind: CreationWorkShelfKind, ids: Array<string | null | undefined>) => {
return collectDraftNoticeKeys(kind, ids).some(
(key) => draftGenerationNotices[key]?.status === 'generating',
);
},
[draftGenerationNotices],
);
const isDraftNoticeReadyUnread = useCallback(
(kind: CreationWorkShelfKind, ids: Array<string | null | undefined>) => {
return collectDraftNoticeKeys(kind, ids).some((key) => {
const notice = draftGenerationNotices[key];
return notice?.status === 'ready' && !notice.seen;
});
},
[draftGenerationNotices],
);
const resolveBigFishErrorMessage = useCallback(
(error: unknown, fallback: string) =>
@@ -3584,9 +3612,10 @@ export function PlatformEntryFlowShellImpl({
const { item } = await getMatch3DWorkDetail(profileId);
runtimeProfile = {
...item,
generatedItemAssets:
response.session.draft?.generatedItemAssets ??
generatedItemAssets: mergeMatch3DGeneratedItemAssetsForRuntime(
response.session.draft?.generatedItemAssets,
item.generatedItemAssets,
),
};
setMatch3DProfile(runtimeProfile);
await refreshMatch3DShelf().catch(() => undefined);
@@ -4201,8 +4230,15 @@ export function PlatformEntryFlowShellImpl({
const resetAutoSaveTrackingToIdle =
autosaveCoordinator.resetAutoSaveTrackingToIdle;
const activeMatch3DBackgroundCompileTask =
getMatch3DBackgroundCompileTask(match3dSession?.sessionId);
const activeMatch3DGenerationSessionId =
selectionStage === 'match3d-generating'
? (activeMatch3DGenerationSessionIdRef.current ??
match3dSession?.sessionId ??
null)
: null;
const activeMatch3DBackgroundCompileTask = getMatch3DBackgroundCompileTask(
activeMatch3DGenerationSessionId,
);
const match3dGenerationViewState =
activeMatch3DBackgroundCompileTask?.generationState ??
match3dGenerationState;
@@ -4217,8 +4253,14 @@ export function PlatformEntryFlowShellImpl({
isMiniGameDraftGenerating(
activeMatch3DBackgroundCompileTask?.generationState ?? null,
);
const activePuzzleGenerationSessionId =
selectionStage === 'puzzle-generating'
? (activePuzzleGenerationSessionIdRef.current ??
puzzleSession?.sessionId ??
null)
: null;
const activePuzzleBackgroundCompileTask = getPuzzleBackgroundCompileTask(
puzzleSession?.sessionId,
activePuzzleGenerationSessionId,
);
const puzzleGenerationViewState =
activePuzzleBackgroundCompileTask?.generationState ?? puzzleGenerationState;
@@ -4634,9 +4676,10 @@ export function PlatformEntryFlowShellImpl({
const { item } = await getMatch3DWorkDetail(profileId);
runtimeProfile = {
...item,
generatedItemAssets:
response.session.draft?.generatedItemAssets ??
generatedItemAssets: mergeMatch3DGeneratedItemAssetsForRuntime(
response.session.draft?.generatedItemAssets,
item.generatedItemAssets,
),
};
if (isViewingMatch3DGeneration(nextSession.sessionId)) {
setMatch3DProfile(runtimeProfile);
@@ -6211,11 +6254,23 @@ export function PlatformEntryFlowShellImpl({
if (!hasMatch3DRuntimeAsset(profile.generatedItemAssets)) {
try {
const { item } = await getMatch3DWorkDetail(profile.profileId);
runtimeProfile = item;
runtimeProfile = {
...item,
generatedItemAssets: mergeMatch3DGeneratedItemAssetsForRuntime(
item.generatedItemAssets,
profile.generatedItemAssets,
),
};
} catch {
// 中文注释:详情补读只为拿完整生成素材;失败时继续按摘要开局,避免推荐流卡死。
}
}
runtimeProfile = {
...runtimeProfile,
generatedItemAssets: normalizeMatch3DGeneratedItemAssetsForRuntime(
runtimeProfile.generatedItemAssets,
),
};
await preloadMatch3DGeneratedRuntimeAssets(
runtimeProfile.generatedItemAssets,
{ expireSeconds: 300 },
@@ -8019,9 +8074,15 @@ export function PlatformEntryFlowShellImpl({
return;
}
const backgroundTask = getPuzzleBackgroundCompileTask(
item.sourceSessionId,
);
const activeGenerationState =
backgroundTask?.generationState ?? puzzleGenerationViewState;
if (
item.sourceSessionId === puzzleSession?.sessionId &&
isMiniGameDraftGenerating(puzzleGenerationViewState)
isMiniGameDraftGenerating(activeGenerationState)
) {
enterCreateTab();
selectionStageRef.current = 'puzzle-generating';
@@ -8030,9 +8091,6 @@ export function PlatformEntryFlowShellImpl({
return;
}
const backgroundTask = getPuzzleBackgroundCompileTask(
item.sourceSessionId,
);
if (
backgroundTask &&
isMiniGameDraftGenerating(backgroundTask.generationState)
@@ -8086,31 +8144,78 @@ export function PlatformEntryFlowShellImpl({
item: Match3DWorkSummary,
options: { forceDraft?: boolean } = {},
) => {
const noticeKeys = collectDraftNoticeKeys('match3d', [
item.workId,
item.profileId,
item.sourceSessionId,
]);
const hasUnreadReadyNotice = isDraftNoticeReadyUnread('match3d', [
item.workId,
item.profileId,
item.sourceSessionId,
]);
setMatch3DRun(null);
setMatch3DError(null);
setMatch3DProfile(null);
setMatch3DRuntimeProfile(null);
markDraftNoticeSeen(
collectDraftNoticeKeys('match3d', [
item.workId,
item.profileId,
item.sourceSessionId,
]),
);
if (item.publicationStatus === 'published' && !options.forceDraft) {
markDraftNoticeSeen(noticeKeys);
openPublicWorkDetail(mapMatch3DWorkToPublicWorkDetail(item));
return;
}
if (!item.sourceSessionId?.trim()) {
markDraftNoticeSeen(noticeKeys);
setMatch3DError('这份抓大鹅草稿缺少会话信息,请重新开始创作。');
return;
}
const isMarkedGenerating = isDraftNoticeGenerating('match3d', [
item.workId,
item.profileId,
item.sourceSessionId,
]);
const backgroundTask = getMatch3DBackgroundCompileTask(
item.sourceSessionId,
);
const activeGenerationState =
backgroundTask?.generationState ?? match3dGenerationViewState;
if (hasUnreadReadyNotice) {
try {
const { session: latestSession } =
await match3dCreationClient.getSession(item.sourceSessionId);
setMatch3DSession(latestSession);
setMatch3DFormDraftPayload(null);
const profileId = latestSession.draft?.profileId ?? item.profileId;
const { item: profile } = await getMatch3DWorkDetail(profileId);
match3dFlow.setIsBusy(false);
const started = await startMatch3DRunFromProfile(
profile,
'match3d-result',
);
if (!started) {
setMatch3DProfile(profile);
enterCreateTab();
setSelectionStage('match3d-result');
}
markDraftNoticeSeen(noticeKeys);
return;
} catch (error) {
setMatch3DError(
resolveMatch3DErrorMessage(error, '启动抓大鹅试玩失败。'),
);
markDraftNoticeSeen(noticeKeys);
await refreshMatch3DShelf().catch(() => undefined);
return;
}
}
if (
item.sourceSessionId === match3dSession?.sessionId &&
isMiniGameDraftGenerating(match3dGenerationViewState)
isMiniGameDraftGenerating(activeGenerationState)
) {
enterCreateTab();
selectionStageRef.current = 'match3d-generating';
@@ -8119,9 +8224,6 @@ export function PlatformEntryFlowShellImpl({
return;
}
const backgroundTask = getMatch3DBackgroundCompileTask(
item.sourceSessionId,
);
if (
backgroundTask &&
isMiniGameDraftGenerating(backgroundTask.generationState)
@@ -8139,6 +8241,32 @@ export function PlatformEntryFlowShellImpl({
return;
}
if (isMarkedGenerating) {
try {
const { session: latestSession } =
await match3dCreationClient.getSession(item.sourceSessionId);
setMatch3DSession(latestSession);
setMatch3DFormDraftPayload(null);
setMatch3DProfile(null);
setMatch3DGenerationState(
createMiniGameDraftGenerationState('match3d'),
);
enterCreateTab();
selectionStageRef.current = 'match3d-generating';
activeMatch3DGenerationSessionIdRef.current = item.sourceSessionId;
setSelectionStage('match3d-generating');
return;
} catch (error) {
setMatch3DError(
resolveMatch3DErrorMessage(error, '读取抓大鹅创作草稿失败。'),
);
await refreshMatch3DShelf().catch(() => undefined);
return;
}
}
markDraftNoticeSeen(noticeKeys);
const restoredSession = await match3dFlow.restoreDraft(
item.sourceSessionId,
);
@@ -8163,6 +8291,8 @@ export function PlatformEntryFlowShellImpl({
[
enterCreateTab,
getMatch3DBackgroundCompileTask,
isDraftNoticeGenerating,
isDraftNoticeReadyUnread,
markDraftNoticeSeen,
match3dFlow,
match3dGenerationViewState,
@@ -8173,6 +8303,7 @@ export function PlatformEntryFlowShellImpl({
setMatch3DFormDraftPayload,
setMatch3DError,
setSelectionStage,
startMatch3DRunFromProfile,
],
);
@@ -10190,7 +10321,7 @@ export function PlatformEntryFlowShellImpl({
fallback={<LazyPanelFallback label="正在加载拼图创作..." />}
>
<PuzzleAgentWorkspace
session={puzzleSession}
session={null}
isBusy={isStreamingPuzzleReply}
error={puzzleError}
onBack={leavePuzzleFlow}