feat: add edutainment drawing and visual package flows
This commit is contained in:
@@ -1,4 +1,12 @@
|
||||
import { ArrowLeft, CheckCircle2, Loader2, Play, Save, Tag } from 'lucide-react';
|
||||
import {
|
||||
ArrowLeft,
|
||||
CheckCircle2,
|
||||
Loader2,
|
||||
Play,
|
||||
RefreshCw,
|
||||
Save,
|
||||
Tag,
|
||||
} from 'lucide-react';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import type { BabyObjectMatchDraft } from '../../../packages/shared/src/contracts/edutainmentBabyObject';
|
||||
@@ -17,6 +25,7 @@ type BabyObjectMatchResultViewProps = {
|
||||
onSaveDraft?: (draft: BabyObjectMatchDraft) => void;
|
||||
onPublish?: (draft: BabyObjectMatchDraft) => void;
|
||||
onStartTestRun?: (draft: BabyObjectMatchDraft) => void;
|
||||
onRegenerateAssets?: (draft: BabyObjectMatchDraft) => void;
|
||||
};
|
||||
|
||||
function normalizeDraftForAction(draft: BabyObjectMatchDraft) {
|
||||
@@ -27,6 +36,14 @@ function normalizeDraftForAction(draft: BabyObjectMatchDraft) {
|
||||
};
|
||||
}
|
||||
|
||||
const REQUIRED_VISUAL_ASSET_KINDS = [
|
||||
'background',
|
||||
'ui-frame',
|
||||
'gift-box',
|
||||
'basket',
|
||||
'smoke-puff',
|
||||
] as const;
|
||||
|
||||
export function BabyObjectMatchResultView({
|
||||
draft,
|
||||
isBusy = false,
|
||||
@@ -35,12 +52,29 @@ export function BabyObjectMatchResultView({
|
||||
onSaveDraft,
|
||||
onPublish,
|
||||
onStartTestRun,
|
||||
onRegenerateAssets,
|
||||
}: BabyObjectMatchResultViewProps) {
|
||||
const normalizedDraft = useMemo(() => normalizeDraftForAction(draft), [draft]);
|
||||
const hasGeneratedAssets =
|
||||
normalizedDraft.itemAssets.every(
|
||||
(asset) =>
|
||||
asset.generationProvider === 'vector-engine-gpt-image-2' &&
|
||||
asset.imageSrc.startsWith('data:image/png;base64,'),
|
||||
) &&
|
||||
Boolean(normalizedDraft.visualPackage) &&
|
||||
REQUIRED_VISUAL_ASSET_KINDS.every((kind) =>
|
||||
normalizedDraft.visualPackage!.assets.some(
|
||||
(asset) =>
|
||||
asset.assetKind === kind &&
|
||||
asset.generationProvider === 'vector-engine-gpt-image-2' &&
|
||||
asset.imageSrc.startsWith('data:image/png;base64,'),
|
||||
),
|
||||
);
|
||||
const publishReady =
|
||||
normalizedDraft.itemNames.every((itemName) => itemName.trim()) &&
|
||||
normalizedDraft.itemAssets.every((asset) => asset.imageSrc.trim()) &&
|
||||
hasBabyObjectMatchRequiredTag(normalizedDraft.themeTags);
|
||||
hasBabyObjectMatchRequiredTag(normalizedDraft.themeTags) &&
|
||||
hasGeneratedAssets;
|
||||
const isPublished = normalizedDraft.publicationStatus === 'published';
|
||||
|
||||
return (
|
||||
@@ -123,9 +157,15 @@ export function BabyObjectMatchResultView({
|
||||
{error}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{!hasGeneratedAssets ? (
|
||||
<div className="platform-banner mt-3 rounded-2xl text-sm leading-6">
|
||||
当前作品仍是占位资源,请重新生成 image-2 资源后再试玩或发布。
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div className="mt-3 grid shrink-0 gap-2 pb-[max(0.25rem,env(safe-area-inset-bottom))] sm:grid-cols-3">
|
||||
<div className="mt-3 grid shrink-0 gap-2 pb-[max(0.25rem,env(safe-area-inset-bottom))] sm:grid-cols-4">
|
||||
<button
|
||||
type="button"
|
||||
disabled={isBusy || !onSaveDraft}
|
||||
@@ -137,7 +177,20 @@ export function BabyObjectMatchResultView({
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
disabled={isBusy || !onStartTestRun}
|
||||
disabled={isBusy || !onRegenerateAssets}
|
||||
onClick={() => onRegenerateAssets?.(normalizedDraft)}
|
||||
className="platform-button platform-button--secondary justify-center disabled:cursor-not-allowed disabled:opacity-55"
|
||||
>
|
||||
{isBusy ? (
|
||||
<Loader2 className="h-4 w-4 animate-spin" />
|
||||
) : (
|
||||
<RefreshCw className="h-4 w-4" />
|
||||
)}
|
||||
重新生成资源
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
disabled={isBusy || !hasGeneratedAssets || !onStartTestRun}
|
||||
onClick={() => onStartTestRun?.(normalizedDraft)}
|
||||
className="platform-button platform-button--secondary justify-center disabled:cursor-not-allowed disabled:opacity-55"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user