Integrate role asset studio into custom world agent flow
This commit is contained in:
@@ -0,0 +1,204 @@
|
||||
import type { CustomWorldDraftCardDetail } from '../../../packages/shared/src/contracts/customWorldAgent';
|
||||
import { CustomWorldDraftEditPanel } from './CustomWorldDraftEditPanel';
|
||||
|
||||
type CustomWorldAgentDraftDetailPanelProps = {
|
||||
detail: CustomWorldDraftCardDetail | null;
|
||||
loading: boolean;
|
||||
busy?: boolean;
|
||||
editMode?: boolean;
|
||||
onClose: () => void;
|
||||
onStartEdit?: () => void;
|
||||
onCancelEdit?: () => void;
|
||||
onSave?: (
|
||||
sections: Array<{
|
||||
sectionId: string;
|
||||
value: string;
|
||||
}>,
|
||||
) => void;
|
||||
onGenerateCharacter?: () => void;
|
||||
onGenerateLandmark?: () => void;
|
||||
onOpenRoleAssetStudio?: () => void;
|
||||
};
|
||||
|
||||
function resolveKindLabel(kind: CustomWorldDraftCardDetail['kind']) {
|
||||
if (kind === 'world') return '世界总卡';
|
||||
if (kind === 'camp') return '营地';
|
||||
if (kind === 'faction') return '势力';
|
||||
if (kind === 'character') return '角色';
|
||||
if (kind === 'landmark') return '地点';
|
||||
if (kind === 'thread') return '线程';
|
||||
if (kind === 'chapter') return '第一幕';
|
||||
return '草稿卡';
|
||||
}
|
||||
|
||||
function ActionButton(props: {
|
||||
label: string;
|
||||
onClick?: () => void;
|
||||
disabled?: boolean;
|
||||
tone?: 'default' | 'sky';
|
||||
}) {
|
||||
const { label, onClick, disabled = false, tone = 'default' } = props;
|
||||
|
||||
if (!onClick) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
className={`rounded-full border px-3 py-1.5 text-[11px] transition ${
|
||||
tone === 'sky'
|
||||
? 'border-sky-300/20 bg-sky-500/10 text-sky-100 hover:text-white'
|
||||
: 'border-white/10 bg-black/20 text-zinc-300 hover:text-white'
|
||||
} disabled:cursor-not-allowed disabled:opacity-45`}
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
export function CustomWorldAgentDraftDetailPanel({
|
||||
detail,
|
||||
loading,
|
||||
busy = false,
|
||||
editMode = false,
|
||||
onClose,
|
||||
onStartEdit,
|
||||
onCancelEdit,
|
||||
onSave,
|
||||
onGenerateCharacter,
|
||||
onGenerateLandmark,
|
||||
onOpenRoleAssetStudio,
|
||||
}: CustomWorldAgentDraftDetailPanelProps) {
|
||||
return (
|
||||
<section className="rounded-[1.5rem] border border-white/10 bg-black/18 px-4 py-4">
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<div>
|
||||
<div className="text-[11px] font-bold tracking-[0.2em] text-zinc-400">
|
||||
卡片详情
|
||||
</div>
|
||||
<div className="mt-2 text-lg font-semibold text-white">
|
||||
{loading ? '正在读取' : detail?.title || '选择一张草稿卡'}
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
className="rounded-full border border-white/10 bg-black/20 px-3 py-1 text-[11px] text-zinc-300 transition hover:text-white"
|
||||
>
|
||||
关闭
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{loading ? (
|
||||
<div className="mt-4 rounded-[1.15rem] border border-white/8 bg-white/5 px-4 py-5 text-sm leading-7 text-zinc-300">
|
||||
正在整理这张卡的内容。
|
||||
</div>
|
||||
) : detail ? (
|
||||
<div className="mt-4 space-y-3">
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<span className="rounded-full border border-sky-300/20 bg-sky-500/10 px-3 py-1 text-[11px] text-sky-100">
|
||||
{resolveKindLabel(detail.kind)}
|
||||
</span>
|
||||
<span className="rounded-full border border-white/10 bg-black/24 px-3 py-1 text-[11px] text-zinc-300">
|
||||
关联 {detail.linkedIds.length}
|
||||
</span>
|
||||
{detail.editable ? (
|
||||
<span className="rounded-full border border-emerald-300/20 bg-emerald-500/10 px-3 py-1 text-[11px] text-emerald-100">
|
||||
可编辑
|
||||
</span>
|
||||
) : null}
|
||||
{detail.kind === 'character' && detail.assetStatusLabel ? (
|
||||
<span className="rounded-full border border-amber-300/20 bg-amber-500/10 px-3 py-1 text-[11px] text-amber-100">
|
||||
{detail.assetStatusLabel}
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{!editMode && detail.editable ? (
|
||||
<ActionButton
|
||||
label="编辑设定"
|
||||
onClick={onStartEdit}
|
||||
disabled={busy}
|
||||
/>
|
||||
) : null}
|
||||
{!editMode && detail.kind === 'character' ? (
|
||||
<ActionButton
|
||||
label="角色资产"
|
||||
onClick={onOpenRoleAssetStudio}
|
||||
disabled={busy}
|
||||
tone="sky"
|
||||
/>
|
||||
) : null}
|
||||
{!editMode ? (
|
||||
<>
|
||||
<ActionButton
|
||||
label="新增角色"
|
||||
onClick={onGenerateCharacter}
|
||||
disabled={busy}
|
||||
tone="sky"
|
||||
/>
|
||||
<ActionButton
|
||||
label="新增场景"
|
||||
onClick={onGenerateLandmark}
|
||||
disabled={busy}
|
||||
tone="sky"
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
{editMode && onSave && onCancelEdit ? (
|
||||
<CustomWorldDraftEditPanel
|
||||
detail={detail}
|
||||
disabled={busy}
|
||||
onSave={onSave}
|
||||
onCancel={onCancelEdit}
|
||||
/>
|
||||
) : (
|
||||
<div className="space-y-2">
|
||||
{detail.sections.map((section) => (
|
||||
<div
|
||||
key={section.id}
|
||||
className="rounded-[1.1rem] border border-white/8 bg-white/5 px-3 py-3"
|
||||
>
|
||||
<div className="text-[11px] tracking-[0.16em] text-zinc-400">
|
||||
{section.label}
|
||||
</div>
|
||||
<div className="mt-2 whitespace-pre-wrap text-sm leading-7 text-zinc-100">
|
||||
{section.value}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{detail.warningMessages.length > 0 ? (
|
||||
<div className="rounded-[1.15rem] border border-amber-300/20 bg-amber-500/10 px-4 py-4">
|
||||
<div className="text-[11px] font-bold tracking-[0.18em] text-amber-100">
|
||||
继续精修
|
||||
</div>
|
||||
<div className="mt-3 space-y-2">
|
||||
{detail.warningMessages.map((message, index) => (
|
||||
<div
|
||||
key={`${detail.id}-warning-${index}`}
|
||||
className="text-sm leading-7 text-amber-50"
|
||||
>
|
||||
{message}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : (
|
||||
<div className="mt-4 rounded-[1.15rem] border border-dashed border-white/10 bg-black/22 px-4 py-5 text-sm leading-7 text-zinc-400">
|
||||
从草稿抽屉里点开一张卡,就能在这里看世界底稿的具体内容。
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user