This commit is contained in:
2026-04-24 12:21:33 +08:00
parent 3528980645
commit 70b5a7cf73
515 changed files with 14971 additions and 6831 deletions

View File

@@ -1,4 +1,4 @@
import {
import {
type ReactNode,
useDeferredValue,
useEffect,
@@ -54,6 +54,8 @@ interface CustomWorldEntityCatalogProps {
onProfileChange: (profile: CustomWorldProfile) => void;
onDeleteStoryNpcs?: (ids: string[]) => void;
onDeleteLandmarks?: (ids: string[]) => void;
onGenerateRoleAssets?: (roleId: string) => void;
onGenerateSceneAssets?: (sceneId: string, sceneKind: 'camp' | 'landmark') => void;
createActionLabel?: string;
onCreateAction?: () => void;
createActionDisabled?: boolean;
@@ -111,10 +113,11 @@ function SmallButton({
tone = 'default',
disabled = false,
}: {
onClick: () => void;
onClick: React.MouseEventHandler<HTMLButtonElement>;
children: ReactNode;
tone?: 'default' | 'sky' | 'rose';
disabled?: boolean;
actions?: ReactNode;
}) {
const toneClassName =
tone === 'sky'
@@ -353,6 +356,7 @@ function CatalogCard({
layout = 'stacked',
mediaClassName,
disabled = false,
actions,
}: {
title: string;
description: string;
@@ -364,6 +368,7 @@ function CatalogCard({
layout?: 'stacked' | 'compact';
mediaClassName?: string;
disabled?: boolean;
actions?: ReactNode;
}) {
const selectionBadge = isSelectionMode ? (
<div
@@ -408,6 +413,7 @@ function CatalogCard({
<div className="mt-1.5 text-sm leading-5 text-zinc-300">
{description || '暂无描述'}
</div>
{actions ? <div className="mt-2 flex flex-wrap gap-2">{actions}</div> : null}
</div>
</div>
</button>
@@ -443,6 +449,7 @@ function CatalogCard({
<div className="text-sm leading-6 text-zinc-300">
{description || '暂无描述'}
</div>
{actions ? <div className="flex flex-wrap gap-2">{actions}</div> : null}
</div>
</button>
);
@@ -882,6 +889,8 @@ export function CustomWorldEntityCatalog({
onProfileChange,
onDeleteStoryNpcs,
onDeleteLandmarks,
onGenerateRoleAssets,
onGenerateSceneAssets,
createActionLabel,
onCreateAction,
createActionDisabled = false,
@@ -1430,6 +1439,19 @@ export function CustomWorldEntityCatalog({
id: role.id,
})
}
actions={
!readOnly && onGenerateRoleAssets ? (
<SmallButton
onClick={(event) => {
event?.stopPropagation();
onGenerateRoleAssets(role.id);
}}
tone="sky"
>
</SmallButton>
) : null
}
media={
role.imageSrc?.trim() ? (
<ResolvedAssetImage
@@ -1539,6 +1561,19 @@ export function CustomWorldEntityCatalog({
id: npc.id,
})
}
actions={
!readOnly && !isBulkDeleteMode && onGenerateRoleAssets ? (
<SmallButton
onClick={(event) => {
event?.stopPropagation();
onGenerateRoleAssets(npc.id);
}}
tone="sky"
>
</SmallButton>
) : null
}
media={
<CustomWorldNpcPortrait
npc={npc}
@@ -1602,6 +1637,20 @@ export function CustomWorldEntityCatalog({
id: scene.id,
})
}
actions={
!readOnly && !isBulkDeleteMode && onGenerateSceneAssets ? (
<SmallButton
onClick={(event) => {
event?.stopPropagation();
onGenerateSceneAssets(scene.id, scene.kind);
}}
tone="sky"
disabled={scene.kind === 'camp' && isBulkDeleteMode}
>
</SmallButton>
) : null
}
media={
<ImageFrame
src={scene.imageSrc}
@@ -1619,3 +1668,4 @@ export function CustomWorldEntityCatalog({
</div>
);
}