This commit is contained in:
2026-05-01 22:16:01 +08:00
parent 8d46c05129
commit 33dd105630
36 changed files with 1999 additions and 236 deletions

View File

@@ -655,6 +655,7 @@ function buildPuzzleCompileActionFromFormPayload(
...(workDescription ? { workDescription } : {}),
...(pictureDescription ? { pictureDescription } : {}),
referenceImageSrc: payload?.referenceImageSrc || null,
imageModel: payload?.imageModel ?? null,
candidateCount: 1,
};
}
@@ -687,6 +688,7 @@ function buildPuzzleFormPayloadFromSession(
workDescription,
pictureDescription,
referenceImageSrc: null,
imageModel: null,
};
}
@@ -714,6 +716,10 @@ function buildPuzzleFormPayloadFromAction(
payload.action === 'compile_puzzle_draft'
? (payload.referenceImageSrc ?? null)
: null,
imageModel:
payload.action === 'compile_puzzle_draft'
? (payload.imageModel ?? null)
: null,
};
}
@@ -941,8 +947,9 @@ export function PlatformEntryFlowShellImpl({
const [match3dProfile, setMatch3DProfile] =
useState<Match3DWorkProfile | null>(null);
const [match3dRun, setMatch3DRun] = useState<Match3DRunSnapshot | null>(null);
const [match3dRuntimeReturnStage, setMatch3DRuntimeReturnStage] =
useState<'match3d-result' | 'work-detail'>('match3d-result');
const [match3dRuntimeReturnStage, setMatch3DRuntimeReturnStage] = useState<
'match3d-result' | 'work-detail'
>('match3d-result');
const [isMatch3DLoadingLibrary, setIsMatch3DLoadingLibrary] = useState(false);
const [bigFishRun, setBigFishRun] =
useState<BigFishRuntimeSnapshotResponse | null>(null);
@@ -993,8 +1000,10 @@ export function PlatformEntryFlowShellImpl({
const [deletingCreationWorkId, setDeletingCreationWorkId] = useState<
string | null
>(null);
const [claimingPuzzlePointIncentiveProfileId, setClaimingPuzzlePointIncentiveProfileId] =
useState<string | null>(null);
const [
claimingPuzzlePointIncentiveProfileId,
setClaimingPuzzlePointIncentiveProfileId,
] = useState<string | null>(null);
const isBigFishCreationVisible = isPlatformCreationTypeVisible('big-fish');
const [profilePlayStats, setProfilePlayStats] =
useState<ProfilePlayStatsResponse | null>(null);
@@ -1099,7 +1108,9 @@ export function PlatformEntryFlowShellImpl({
return galleryResponse.items;
} catch (error) {
setMatch3DGalleryEntries([]);
setMatch3DError(resolveMatch3DErrorMessage(error, '读取抓大鹅广场失败。'));
setMatch3DError(
resolveMatch3DErrorMessage(error, '读取抓大鹅广场失败。'),
);
return [];
}
}, [resolveMatch3DErrorMessage]);
@@ -1293,7 +1304,11 @@ export function PlatformEntryFlowShellImpl({
);
return mergePlatformPublicGalleryEntries(
platformBootstrap.publishedGalleryEntries,
[...bigFishPublicEntries, ...match3dPublicEntries, ...puzzlePublicEntries],
[
...bigFishPublicEntries,
...match3dPublicEntries,
...puzzlePublicEntries,
],
).slice(0, 6);
}, [
isBigFishCreationVisible,
@@ -1665,24 +1680,6 @@ export function PlatformEntryFlowShellImpl({
await bigFishFlow.openWorkspace();
}, [bigFishFlow]);
const openMatch3DAgentWorkspace = useCallback(async () => {
setMatch3DSession(null);
setMatch3DProfile(null);
setMatch3DRun(null);
setMatch3DError(null);
setStreamingMatch3DReplyText('');
setIsStreamingMatch3DReply(false);
await match3dFlow.openWorkspace();
}, [
match3dFlow,
setIsStreamingMatch3DReply,
setMatch3DError,
setMatch3DProfile,
setMatch3DRun,
setMatch3DSession,
setStreamingMatch3DReplyText,
]);
const openPuzzleAgentWorkspace = useCallback(async () => {
setPuzzleRun(null);
setPuzzleOperation(null);
@@ -1729,6 +1726,7 @@ export function PlatformEntryFlowShellImpl({
workTitle: payload.workTitle ?? payload.seedText ?? '',
workDescription: payload.workDescription ?? '',
pictureDescription: payload.pictureDescription ?? '',
imageModel: payload.imageModel ?? null,
});
setPuzzleOperation(response.operation);
puzzleFlow.setSession(response.session);
@@ -1826,12 +1824,7 @@ export function PlatformEntryFlowShellImpl({
const handleCreationHubCreateType = useCallback(
(type: PlatformCreationTypeId) => {
if (
type === 'rpg' ||
type === 'match3d' ||
type === 'airp' ||
type === 'visual-novel'
) {
if (type === 'match3d' || type === 'airp' || type === 'visual-novel') {
return;
}
@@ -1839,6 +1832,13 @@ export function PlatformEntryFlowShellImpl({
return;
}
if (type === 'rpg') {
runProtectedAction(() => {
void sessionController.openRpgAgentWorkspace();
});
return;
}
if (type === 'big-fish') {
runProtectedAction(() => {
void openBigFishAgentWorkspace();
@@ -1857,6 +1857,7 @@ export function PlatformEntryFlowShellImpl({
openPuzzleAgentWorkspace,
prepareCreationLaunch,
runProtectedAction,
sessionController,
],
);
@@ -2332,8 +2333,8 @@ export function PlatformEntryFlowShellImpl({
propKind === 'extendTime'
? extendLocalPuzzleTime(currentRun)
: propKind === 'freezeTime'
? applyLocalPuzzleFreezeTime(currentRun)
: setLocalPuzzlePaused(currentRun, propKind === 'reference');
? applyLocalPuzzleFreezeTime(currentRun)
: setLocalPuzzlePaused(currentRun, propKind === 'reference');
puzzleRunRef.current = nextRun;
setPuzzleRun(nextRun);
return nextRun;
@@ -2367,7 +2368,9 @@ export function PlatformEntryFlowShellImpl({
selectedPuzzleDetail,
);
if (isLocalPuzzleRun(puzzleRun)) {
const nextRun = restartLocalPuzzleLevel(puzzleRunRef.current ?? puzzleRun);
const nextRun = restartLocalPuzzleLevel(
puzzleRunRef.current ?? puzzleRun,
);
puzzleRunRef.current = nextRun;
setPuzzleRun(nextRun);
return;
@@ -2531,68 +2534,68 @@ export function PlatformEntryFlowShellImpl({
setPuzzleError,
]);
const advancePuzzleLevel = useCallback(async (target?: {
profileId?: string;
levelId?: string | null;
}) => {
if (!puzzleRun || isPuzzleBusy || isPuzzleLeaderboardBusy) {
return;
}
const currentLevel = puzzleRun.currentLevel;
if (!currentLevel || currentLevel.status !== 'cleared') {
return;
}
setIsPuzzleBusy(true);
setIsPuzzleNextLevelGenerating(true);
setPuzzleError(null);
try {
const targetProfileId = target?.profileId?.trim();
if (
targetProfileId &&
targetProfileId !== currentLevel.profileId &&
puzzleRun.nextLevelMode === 'similarWorks'
) {
await startPuzzleRunFromProfile(
targetProfileId,
'puzzle-gallery-detail',
undefined,
false,
null,
);
const advancePuzzleLevel = useCallback(
async (target?: { profileId?: string; levelId?: string | null }) => {
if (!puzzleRun || isPuzzleBusy || isPuzzleLeaderboardBusy) {
return;
}
const { run } = isLocalPuzzleRun(puzzleRun)
? await advanceLocalPuzzleNextLevel({
run: puzzleRun,
sourceSessionId:
selectedPuzzleDetail?.sourceSessionId ??
puzzleSession?.sessionId ??
null,
})
: await advancePuzzleNextLevel(puzzleRun.runId);
setPuzzleRun(run);
if (!isLocalPuzzleRun(puzzleRun)) {
void platformBootstrap.refreshSaveArchives();
const currentLevel = puzzleRun.currentLevel;
if (!currentLevel || currentLevel.status !== 'cleared') {
return;
}
} catch (error) {
setPuzzleError(resolvePuzzleErrorMessage(error, '准备下一关失败。'));
} finally {
setIsPuzzleNextLevelGenerating(false);
setIsPuzzleBusy(false);
}
}, [
isPuzzleBusy,
isPuzzleLeaderboardBusy,
platformBootstrap,
puzzleRun,
puzzleSession,
resolvePuzzleErrorMessage,
selectedPuzzleDetail,
startPuzzleRunFromProfile,
]);
setIsPuzzleBusy(true);
setIsPuzzleNextLevelGenerating(true);
setPuzzleError(null);
try {
const targetProfileId = target?.profileId?.trim();
if (
targetProfileId &&
targetProfileId !== currentLevel.profileId &&
puzzleRun.nextLevelMode === 'similarWorks'
) {
await startPuzzleRunFromProfile(
targetProfileId,
'puzzle-gallery-detail',
undefined,
false,
null,
);
return;
}
const { run } = isLocalPuzzleRun(puzzleRun)
? await advanceLocalPuzzleNextLevel({
run: puzzleRun,
sourceSessionId:
selectedPuzzleDetail?.sourceSessionId ??
puzzleSession?.sessionId ??
null,
})
: await advancePuzzleNextLevel(puzzleRun.runId);
setPuzzleRun(run);
if (!isLocalPuzzleRun(puzzleRun)) {
void platformBootstrap.refreshSaveArchives();
}
} catch (error) {
setPuzzleError(resolvePuzzleErrorMessage(error, '准备下一关失败。'));
} finally {
setIsPuzzleNextLevelGenerating(false);
setIsPuzzleBusy(false);
}
},
[
isPuzzleBusy,
isPuzzleLeaderboardBusy,
platformBootstrap,
puzzleRun,
puzzleSession,
resolvePuzzleErrorMessage,
selectedPuzzleDetail,
startPuzzleRunFromProfile,
],
);
const leaveAgentWorkspace = useCallback(() => {
enterCreateTab();
@@ -2935,14 +2938,10 @@ export function PlatformEntryFlowShellImpl({
.then((response) => {
const updatedWork = response.item;
setPuzzleWorks((current) =>
current.map((item) =>
mergePuzzleWorkSummary(item, updatedWork),
),
current.map((item) => mergePuzzleWorkSummary(item, updatedWork)),
);
setPuzzleGalleryEntries((current) =>
current.map((item) =>
mergePuzzleWorkSummary(item, updatedWork),
),
current.map((item) => mergePuzzleWorkSummary(item, updatedWork)),
);
setSelectedPuzzleDetail((current) =>
current ? mergePuzzleWorkSummary(current, updatedWork) : current,
@@ -3316,7 +3315,9 @@ export function PlatformEntryFlowShellImpl({
return;
}
const restoredSession = await match3dFlow.restoreDraft(item.sourceSessionId);
const restoredSession = await match3dFlow.restoreDraft(
item.sourceSessionId,
);
if (!restoredSession) {
await refreshMatch3DShelf().catch(() => undefined);
return;
@@ -3395,7 +3396,9 @@ export function PlatformEntryFlowShellImpl({
if (isPuzzleGalleryEntry(selectedPublicWorkDetail)) {
const work = mapPublicWorkDetailToPuzzleWork(selectedPublicWorkDetail);
if (!work) {
setPublicWorkDetailError('当前拼图作品信息不完整,暂时无法进入玩法。');
setPublicWorkDetailError(
'当前拼图作品信息不完整,暂时无法进入玩法。',
);
return;
}
setPublicWorkDetailError(null);
@@ -3411,7 +3414,9 @@ export function PlatformEntryFlowShellImpl({
if (isMatch3DGalleryEntry(selectedPublicWorkDetail)) {
const work = mapPublicWorkDetailToMatch3DWork(selectedPublicWorkDetail);
if (!work) {
setPublicWorkDetailError('当前抓大鹅作品信息不完整,暂时无法进入玩法。');
setPublicWorkDetailError(
'当前抓大鹅作品信息不完整,暂时无法进入玩法。',
);
return;
}
setPublicWorkDetailError(null);
@@ -4487,7 +4492,9 @@ export function PlatformEntryFlowShellImpl({
className="flex h-full min-h-0 flex-col"
>
<Suspense
fallback={<LazyPanelFallback label="正在加载抓大鹅共创工作区..." />}
fallback={
<LazyPanelFallback label="正在加载抓大鹅共创工作区..." />
}
>
<Match3DAgentWorkspace
session={match3dSession}
@@ -4520,7 +4527,8 @@ export function PlatformEntryFlowShellImpl({
>
<Match3DResultView
profile={
match3dProfile ?? buildMatch3DProfileFromSession(match3dSession)!
match3dProfile ??
buildMatch3DProfileFromSession(match3dSession)!
}
draft={match3dSession.draft}
isBusy={isMatch3DBusy}
@@ -4537,7 +4545,9 @@ export function PlatformEntryFlowShellImpl({
refreshMatch3DShelf(),
refreshMatch3DGallery(),
]);
openPublicWorkDetail(mapMatch3DWorkToPublicWorkDetail(profile));
openPublicWorkDetail(
mapMatch3DWorkToPublicWorkDetail(profile),
);
}}
onStartTestRun={(profile) => {
setMatch3DProfile(profile);
@@ -4565,7 +4575,9 @@ export function PlatformEntryFlowShellImpl({
error={match3dError}
onBack={() => {
if (match3dRun?.runId && match3dRun.status === 'running') {
void stopMatch3DRun(match3dRun.runId).catch(() => undefined);
void stopMatch3DRun(match3dRun.runId).catch(
() => undefined,
);
}
setSelectionStage(match3dRuntimeReturnStage);
}}
@@ -4596,7 +4608,9 @@ export function PlatformEntryFlowShellImpl({
onClickItem={(payload) => {
const runId = payload.runId ?? match3dRun?.runId;
if (!runId) {
return Promise.reject(new Error('抓大鹅运行态缺少 runId。'));
return Promise.reject(
new Error('抓大鹅运行态缺少 runId。'),
);
}
return clickMatch3DItem(runId, payload);
}}
@@ -5084,7 +5098,9 @@ export function PlatformEntryFlowShellImpl({
setShowCreationTypeModal(false);
}}
onSelectRpg={() => {
// RPG 创作入口当前为敬请期待;保留回调防御,避免旧入口绕过锁定态。
runProtectedAction(() => {
void sessionController.openRpgAgentWorkspace();
});
}}
onSelectBigFish={() => {
runProtectedAction(() => {