落地方洞挑战图片与运行态交互
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
kdletters
2026-05-06 12:51:28 +08:00
parent 60b667a9d1
commit d06107f2c6
51 changed files with 2590 additions and 989 deletions

View File

@@ -64,9 +64,7 @@ import type {
SquareHoleSessionResponse,
SquareHoleSessionSnapshot,
} from '../../../packages/shared/src/contracts/squareHoleAgent';
import type {
SquareHoleRunSnapshot,
} from '../../../packages/shared/src/contracts/squareHoleRuntime';
import type { SquareHoleRunSnapshot } from '../../../packages/shared/src/contracts/squareHoleRuntime';
import type {
SquareHoleWorkProfile,
SquareHoleWorkSummary,
@@ -1703,7 +1701,9 @@ export function PlatformEntryFlowShellImpl({
void refreshBigFishGallery();
openPublishShareModal({
title: response.session.draft?.title ?? '大鱼吃小鱼',
publicWorkCode: buildBigFishPublicWorkCode(response.session.sessionId),
publicWorkCode: buildBigFishPublicWorkCode(
response.session.sessionId,
),
stage: 'big-fish-runtime',
});
}
@@ -1889,8 +1889,10 @@ export function PlatformEntryFlowShellImpl({
setSquareHoleGenerationState((current) => ({
...(current ?? createMiniGameDraftGenerationState('square-hole')),
phase: 'ready',
completedAssetCount: item.shapeOptions.length + 2,
totalAssetCount: item.shapeOptions.length + 2,
completedAssetCount:
item.shapeOptions.length + item.holeOptions.length + 2,
totalAssetCount:
item.shapeOptions.length + item.holeOptions.length + 2,
error: null,
}));
await refreshSquareHoleShelf().catch(() => undefined);
@@ -1906,8 +1908,10 @@ export function PlatformEntryFlowShellImpl({
phase: 'failed',
error: errorMessage,
}));
setSquareHoleProfile(buildSquareHoleProfileFromSession(response.session));
setSelectionStage('square-hole-generating');
setSquareHoleProfile(
buildSquareHoleProfileFromSession(response.session),
);
setSelectionStage('square-hole-result');
}
return;
}
@@ -1918,14 +1922,18 @@ export function PlatformEntryFlowShellImpl({
setSquareHoleGenerationState((current) => ({
...(current ?? createMiniGameDraftGenerationState('square-hole')),
phase: 'ready',
completedAssetCount: item.shapeOptions.length + 2,
totalAssetCount: item.shapeOptions.length + 2,
completedAssetCount:
item.shapeOptions.length + item.holeOptions.length + 2,
totalAssetCount:
item.shapeOptions.length + item.holeOptions.length + 2,
error: null,
}));
await refreshSquareHoleShelf().catch(() => undefined);
setSelectionStage('square-hole-result');
} catch {
setSquareHoleProfile(buildSquareHoleProfileFromSession(response.session));
setSquareHoleProfile(
buildSquareHoleProfileFromSession(response.session),
);
setSelectionStage('square-hole-result');
}
},
@@ -2031,7 +2039,9 @@ export function PlatformEntryFlowShellImpl({
);
openPublishShareModal({
title: galleryDetail.item.workTitle || galleryDetail.item.levelName,
publicWorkCode: buildPuzzlePublicWorkCode(galleryDetail.item.profileId),
publicWorkCode: buildPuzzlePublicWorkCode(
galleryDetail.item.profileId,
),
stage: 'puzzle-gallery-detail',
});
}
@@ -2087,8 +2097,7 @@ export function PlatformEntryFlowShellImpl({
const setSquareHoleError = squareHoleFlow.setError;
const isSquareHoleBusy = squareHoleFlow.isBusy;
const streamingSquareHoleReplyText = squareHoleFlow.streamingReplyText;
const setStreamingSquareHoleReplyText =
squareHoleFlow.setStreamingReplyText;
const setStreamingSquareHoleReplyText = squareHoleFlow.setStreamingReplyText;
const isStreamingSquareHoleReply = squareHoleFlow.isStreamingReply;
const setIsStreamingSquareHoleReply = squareHoleFlow.setIsStreamingReply;
@@ -2310,10 +2319,7 @@ export function PlatformEntryFlowShellImpl({
const handleCreationHubCreateType = useCallback(
(type: PlatformCreationTypeId) => {
if (
type === 'airp' ||
type === 'visual-novel'
) {
if (type === 'airp' || type === 'visual-novel') {
return;
}
@@ -2796,9 +2802,7 @@ export function PlatformEntryFlowShellImpl({
setPuzzleRuntimeReturnStage('puzzle-result');
setSelectionStage('puzzle-runtime');
} catch (error) {
setPuzzleError(
resolvePuzzleErrorMessage(error, '启动拼图试玩失败。'),
);
setPuzzleError(resolvePuzzleErrorMessage(error, '启动拼图试玩失败。'));
} finally {
setIsPuzzleBusy(false);
}
@@ -2885,7 +2889,11 @@ export function PlatformEntryFlowShellImpl({
);
const dragPuzzlePiece = useCallback(
async (payload: { pieceId: string; targetRow: number; targetCol: number }) => {
async (payload: {
pieceId: string;
targetRow: number;
targetCol: number;
}) => {
if (!puzzleRun || isPuzzleBusy) {
return;
}
@@ -3014,7 +3022,9 @@ export function PlatformEntryFlowShellImpl({
puzzleRunRef.current = run;
setPuzzleRun(run);
} catch (error) {
setPuzzleError(resolvePuzzleErrorMessage(error, '重新开始拼图关卡失败。'));
setPuzzleError(
resolvePuzzleErrorMessage(error, '重新开始拼图关卡失败。'),
);
} finally {
setIsPuzzleBusy(false);
}
@@ -3220,45 +3230,50 @@ export function PlatformEntryFlowShellImpl({
],
);
const remodelCurrentPuzzleRuntimeWork = useCallback((profileId: string) => {
const targetProfileId = profileId.trim();
if (!targetProfileId || isPublicWorkDetailBusy || isPuzzleBusy) {
return;
}
const remodelCurrentPuzzleRuntimeWork = useCallback(
(profileId: string) => {
const targetProfileId = profileId.trim();
if (!targetProfileId || isPublicWorkDetailBusy || isPuzzleBusy) {
return;
}
runProtectedAction(() => {
setIsPublicWorkDetailBusy(true);
setIsPuzzleBusy(true);
setPuzzleError(null);
setPublicWorkDetailError(null);
runProtectedAction(() => {
setIsPublicWorkDetailBusy(true);
setIsPuzzleBusy(true);
setPuzzleError(null);
setPublicWorkDetailError(null);
void remixPuzzleGalleryWork(targetProfileId)
.then((response) => {
puzzleFlow.setSession(response.session);
setPuzzleOperation(null);
setPuzzleRun(null);
enterCreateTab();
setSelectionStage('puzzle-result');
})
.catch((error) => {
setPuzzleError(resolvePuzzleErrorMessage(error, '改造拼图作品失败。'));
})
.finally(() => {
setIsPublicWorkDetailBusy(false);
setIsPuzzleBusy(false);
});
});
}, [
enterCreateTab,
isPublicWorkDetailBusy,
isPuzzleBusy,
puzzleFlow,
resolvePuzzleErrorMessage,
runProtectedAction,
setIsPuzzleBusy,
setPuzzleError,
setSelectionStage,
]);
void remixPuzzleGalleryWork(targetProfileId)
.then((response) => {
puzzleFlow.setSession(response.session);
setPuzzleOperation(null);
setPuzzleRun(null);
enterCreateTab();
setSelectionStage('puzzle-result');
})
.catch((error) => {
setPuzzleError(
resolvePuzzleErrorMessage(error, '改造拼图作品失败。'),
);
})
.finally(() => {
setIsPublicWorkDetailBusy(false);
setIsPuzzleBusy(false);
});
});
},
[
enterCreateTab,
isPublicWorkDetailBusy,
isPuzzleBusy,
puzzleFlow,
resolvePuzzleErrorMessage,
runProtectedAction,
setIsPuzzleBusy,
setPuzzleError,
setSelectionStage,
],
);
const leaveAgentWorkspace = useCallback(() => {
enterCreateTab();
@@ -4134,7 +4149,9 @@ export function PlatformEntryFlowShellImpl({
const { item: profile } = await getSquareHoleWorkDetail(item.profileId);
setSquareHoleProfile(profile);
} catch (error) {
setSquareHoleProfile(buildSquareHoleProfileFromSession(restoredSession));
setSquareHoleProfile(
buildSquareHoleProfileFromSession(restoredSession),
);
setSquareHoleError(
resolveSquareHoleErrorMessage(error, '读取方洞挑战作品详情失败。'),
);
@@ -5701,7 +5718,9 @@ export function PlatformEntryFlowShellImpl({
className="flex h-full min-h-0 flex-col"
>
<Suspense
fallback={<LazyPanelFallback label="正在加载方洞挑战生成面板..." />}
fallback={
<LazyPanelFallback label="正在加载方洞挑战生成面板..." />
}
>
<CustomWorldGenerationView
settingText={
@@ -5736,59 +5755,60 @@ export function PlatformEntryFlowShellImpl({
</motion.div>
)}
{selectionStage === 'square-hole-result' && squareHoleSession?.draft && (
<motion.div
key="square-hole-result"
initial={{ opacity: 0, y: 12 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -12 }}
className="flex h-full min-h-0 flex-col"
>
<Suspense
fallback={<LazyPanelFallback label="正在加载方洞挑战结果..." />}
{selectionStage === 'square-hole-result' &&
squareHoleSession?.draft && (
<motion.div
key="square-hole-result"
initial={{ opacity: 0, y: 12 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -12 }}
className="flex h-full min-h-0 flex-col"
>
<SquareHoleResultView
profile={
squareHoleProfile ??
buildSquareHoleProfileFromSession(squareHoleSession)!
}
draft={squareHoleSession.draft}
isBusy={isSquareHoleBusy}
error={squareHoleError}
onBack={() => {
setSelectionStage('square-hole-agent-workspace');
}}
onSaved={(profile) => {
setSquareHoleProfile(profile);
}}
onPublished={(profile) => {
setSquareHoleProfile(profile);
void Promise.allSettled([
refreshSquareHoleShelf(),
refreshSquareHoleGallery(),
]);
openPublicWorkDetail(
mapSquareHoleWorkToPublicWorkDetail(profile),
);
openPublishShareModal({
title: profile.gameName,
publicWorkCode: buildSquareHolePublicWorkCode(
profile.profileId,
),
stage: 'work-detail',
});
}}
onStartTestRun={(profile) => {
setSquareHoleProfile(profile);
void startSquareHoleRunFromProfile(
profile,
'square-hole-result',
);
}}
/>
</Suspense>
</motion.div>
)}
<Suspense
fallback={<LazyPanelFallback label="正在加载方洞挑战结果..." />}
>
<SquareHoleResultView
profile={
squareHoleProfile ??
buildSquareHoleProfileFromSession(squareHoleSession)!
}
draft={squareHoleSession.draft}
isBusy={isSquareHoleBusy}
error={squareHoleError}
onBack={() => {
setSelectionStage('square-hole-agent-workspace');
}}
onSaved={(profile) => {
setSquareHoleProfile(profile);
}}
onPublished={(profile) => {
setSquareHoleProfile(profile);
void Promise.allSettled([
refreshSquareHoleShelf(),
refreshSquareHoleGallery(),
]);
openPublicWorkDetail(
mapSquareHoleWorkToPublicWorkDetail(profile),
);
openPublishShareModal({
title: profile.gameName,
publicWorkCode: buildSquareHolePublicWorkCode(
profile.profileId,
),
stage: 'work-detail',
});
}}
onStartTestRun={(profile) => {
setSquareHoleProfile(profile);
void startSquareHoleRunFromProfile(
profile,
'square-hole-result',
);
}}
/>
</Suspense>
</motion.div>
)}
{selectionStage === 'square-hole-runtime' && (
<motion.div