feat: complete bark battle draft publish flow

This commit is contained in:
2026-05-19 15:27:50 +08:00
parent 804f1e32be
commit 23fb895e82
24 changed files with 1710 additions and 159 deletions

View File

@@ -15,6 +15,7 @@ import {
import type { PublicUserSummary } from '../../../packages/shared/src/contracts/auth';
import type {
BarkBattleConfigEditorPayload,
BarkBattleDraftConfig,
BarkBattlePublishedConfig,
} from '../../../packages/shared/src/contracts/barkBattle';
import type {
@@ -409,6 +410,7 @@ type PuzzleOnboardingDraft = {
};
type BigFishRuntimeReturnStage = 'big-fish-result' | 'work-detail' | 'platform';
type BarkBattleRuntimeReturnStage = 'bark-battle-result' | 'platform';
type BigFishRuntimeSessionSource = 'draft' | 'work' | null;
type RecommendRuntimeKind =
| 'big-fish'
@@ -2092,6 +2094,13 @@ const BarkBattleConfigEditor = lazy(async () => {
};
});
const BarkBattleResultView = lazy(async () => {
const module = await import('../bark-battle-creation/BarkBattleResultView');
return {
default: module.BarkBattleResultView,
};
});
const BarkBattleRuntimeShell = lazy(async () => {
const module = await import('../../games/bark-battle/ui/BarkBattleRuntimeShell');
return {
@@ -2319,6 +2328,10 @@ export function PlatformEntryFlowShellImpl({
useState<MiniGameDraftGenerationState | null>(null);
const [barkBattlePublishedConfig, setBarkBattlePublishedConfig] =
useState<BarkBattlePublishedConfig | null>(null);
const [barkBattleDraftConfig, setBarkBattleDraftConfig] =
useState<BarkBattleDraftConfig | null>(null);
const [barkBattleRuntimeReturnStage, setBarkBattleRuntimeReturnStage] =
useState<BarkBattleRuntimeReturnStage>('platform');
const [barkBattleError, setBarkBattleError] = useState<string | null>(null);
const [isBarkBattleBusy, setIsBarkBattleBusy] = useState(false);
const [bigFishRun, setBigFishRun] =
@@ -5540,24 +5553,104 @@ export function PlatformEntryFlowShellImpl({
}, [squareHoleFlow]);
const leaveBarkBattleFlow = useCallback(() => {
setBarkBattleDraftConfig(null);
setBarkBattlePublishedConfig(null);
setBarkBattleRuntimeReturnStage('platform');
setBarkBattleError(null);
setIsBarkBattleBusy(false);
selectionStageRef.current = 'platform';
setSelectionStage('platform');
}, [setSelectionStage]);
const publishBarkBattleConfig = useCallback(
const createBarkBattleResultDraft = useCallback(
async (payload: BarkBattleConfigEditorPayload) => {
setBarkBattleError(null);
setIsBarkBattleBusy(true);
try {
const draft = await createBarkBattleDraft(payload);
setBarkBattleDraftConfig(draft);
setBarkBattlePublishedConfig(null);
setSelectionStage('bark-battle-result');
} catch (error) {
setBarkBattleError(
resolvePuzzleErrorMessage(error, '生成汪汪声浪草稿失败。'),
);
} finally {
setIsBarkBattleBusy(false);
}
},
[resolvePuzzleErrorMessage, setSelectionStage],
);
const buildBarkBattleDraftRuntimeConfig = useCallback(
(draft: BarkBattleDraftConfig): BarkBattlePublishedConfig => ({
workId: draft.workId ?? draft.draftId,
draftId: draft.draftId,
configVersion: draft.configVersion ?? 1,
rulesetVersion: draft.rulesetVersion ?? 'bark-battle-ruleset-v1',
playTypeId: 'bark-battle',
title: draft.title,
description: draft.description,
themePreset: draft.themePreset,
playerDogSkinPreset: draft.playerDogSkinPreset,
opponentDogSkinPreset: draft.opponentDogSkinPreset,
playerCharacterImageSrc: draft.playerCharacterImageSrc,
opponentCharacterImageSrc: draft.opponentCharacterImageSrc,
uiBackgroundImageSrc: draft.uiBackgroundImageSrc,
barkSoundSrc: draft.barkSoundSrc,
difficultyPreset: draft.difficultyPreset,
leaderboardEnabled: draft.leaderboardEnabled,
updatedAt: draft.updatedAt,
publishedAt: draft.updatedAt,
}),
[],
);
const testBarkBattleDraft = useCallback(
(draft: BarkBattleDraftConfig) => {
setBarkBattleError(null);
setBarkBattleRuntimeReturnStage('bark-battle-result');
setBarkBattlePublishedConfig(buildBarkBattleDraftRuntimeConfig(draft));
setSelectionStage('bark-battle-runtime');
},
[buildBarkBattleDraftRuntimeConfig, setSelectionStage],
);
const publishBarkBattleDraft = useCallback(
async (draft: BarkBattleDraftConfig) => {
setBarkBattleError(null);
const workId = draft.workId?.trim();
if (!workId) {
setBarkBattleError('这份汪汪声浪草稿缺少作品ID请重新生成草稿后再发布。');
return;
}
setIsBarkBattleBusy(true);
try {
const publishedSnapshot: BarkBattleConfigEditorPayload = {
title: draft.title,
description: draft.description,
themePreset: draft.themePreset,
playerDogSkinPreset: draft.playerDogSkinPreset,
opponentDogSkinPreset: draft.opponentDogSkinPreset,
...(draft.playerCharacterImageSrc
? { playerCharacterImageSrc: draft.playerCharacterImageSrc }
: {}),
...(draft.opponentCharacterImageSrc
? { opponentCharacterImageSrc: draft.opponentCharacterImageSrc }
: {}),
...(draft.uiBackgroundImageSrc
? { uiBackgroundImageSrc: draft.uiBackgroundImageSrc }
: {}),
...(draft.barkSoundSrc ? { barkSoundSrc: draft.barkSoundSrc } : {}),
difficultyPreset: draft.difficultyPreset,
leaderboardEnabled: draft.leaderboardEnabled,
};
const published = await publishBarkBattleWork({
draftId: draft.draftId,
workId: draft.workId,
publishedSnapshot: payload,
workId,
publishedSnapshot,
});
setBarkBattleRuntimeReturnStage('platform');
setBarkBattlePublishedConfig(published);
setSelectionStage('bark-battle-runtime');
} catch (error) {
@@ -10855,7 +10948,7 @@ export function PlatformEntryFlowShellImpl({
</div>
</div>
<div className="mt-3 min-h-0 flex-1 overflow-hidden">
<div className="mt-3 flex min-h-0 flex-1 flex-col overflow-hidden">
{activeCreationFormType === 'match3d' ? (
<Suspense
fallback={<LazyPanelFallback label="正在加载抓大鹅创作..." />}
@@ -10921,8 +11014,8 @@ export function PlatformEntryFlowShellImpl({
isBusy={isBarkBattleBusy}
error={barkBattleError}
onBack={leaveBarkBattleFlow}
onPublish={(payload) => {
void publishBarkBattleConfig(payload);
onPreview={(payload) => {
void createBarkBattleResultDraft(payload);
}}
showBackButton={false}
title={null}
@@ -12544,6 +12637,36 @@ export function PlatformEntryFlowShellImpl({
</motion.div>
)}
{selectionStage === 'bark-battle-result' && barkBattleDraftConfig && (
<motion.div
key="bark-battle-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="正在加载汪汪声浪草稿..." />}
>
<BarkBattleResultView
draft={barkBattleDraftConfig}
isBusy={isBarkBattleBusy}
error={barkBattleError}
onBack={() => {
enterCreateTab();
setActiveCreationFormType('bark-battle');
setSelectionStage('platform');
}}
onDraftChange={setBarkBattleDraftConfig}
onStartTestRun={testBarkBattleDraft}
onPublish={(draft) => {
void publishBarkBattleDraft(draft);
}}
/>
</Suspense>
</motion.div>
)}
{selectionStage === 'bark-battle-runtime' && barkBattlePublishedConfig && (
<motion.div
key="bark-battle-runtime"
@@ -12560,9 +12683,16 @@ export function PlatformEntryFlowShellImpl({
workId={barkBattlePublishedConfig.workId}
publishedConfig={barkBattlePublishedConfig}
onExit={() => {
enterCreateTab();
setActiveCreationFormType('bark-battle');
setSelectionStage('platform');
if (
barkBattleRuntimeReturnStage === 'bark-battle-result' &&
barkBattleDraftConfig
) {
setSelectionStage('bark-battle-result');
} else {
enterCreateTab();
setActiveCreationFormType('bark-battle');
setSelectionStage('platform');
}
}}
/>
</Suspense>