112 lines
3.6 KiB
TypeScript
112 lines
3.6 KiB
TypeScript
type EightAnchorProgressBarProps = {
|
|
currentTurn: number;
|
|
progressPercent: number;
|
|
disabled: boolean;
|
|
onSummaryClick: () => void;
|
|
onQuickFill: () => void;
|
|
onGenerateDraft: () => void;
|
|
};
|
|
|
|
function clampProgress(progressPercent: number) {
|
|
if (!Number.isFinite(progressPercent)) {
|
|
return 0;
|
|
}
|
|
|
|
return Math.max(0, Math.min(100, Math.round(progressPercent)));
|
|
}
|
|
|
|
function resolveProgressHint(progressPercent: number) {
|
|
if (progressPercent >= 100) {
|
|
return '当前设定已经收束完成,可以进入草稿生成';
|
|
}
|
|
|
|
if (progressPercent >= 75) {
|
|
return '正在收束成一版可进入草稿的世界底子';
|
|
}
|
|
|
|
if (progressPercent >= 45) {
|
|
return '世界方向已经成形,继续补关键骨架';
|
|
}
|
|
|
|
if (progressPercent >= 15) {
|
|
return '先把玩家视角、开局和冲突线钉稳';
|
|
}
|
|
|
|
return '先抓住这个世界最关键的方向';
|
|
}
|
|
|
|
export function EightAnchorProgressBar({
|
|
currentTurn,
|
|
progressPercent,
|
|
disabled,
|
|
onSummaryClick,
|
|
onQuickFill,
|
|
onGenerateDraft,
|
|
}: EightAnchorProgressBarProps) {
|
|
const normalizedProgress = clampProgress(progressPercent);
|
|
const isCompleted = normalizedProgress >= 100;
|
|
const canQuickFill = currentTurn >= 2;
|
|
const progressFillStyle = isCompleted
|
|
? { background: 'linear-gradient(90deg, #86efac 0%, #34d399 100%)' }
|
|
: { background: 'var(--platform-button-primary-fill)' };
|
|
|
|
return (
|
|
<div className="platform-remap-surface platform-subpanel rounded-[1.75rem] p-4">
|
|
<div className="flex flex-col gap-3">
|
|
<div className="flex items-start justify-between gap-3">
|
|
<div>
|
|
<div className="text-xs font-semibold tracking-[0.14em] text-[var(--platform-text-base)]">
|
|
创作进度
|
|
</div>
|
|
<div className="mt-1 text-sm text-[var(--platform-text-soft)]">
|
|
{resolveProgressHint(normalizedProgress)}
|
|
</div>
|
|
</div>
|
|
<div className="text-lg font-semibold text-[var(--platform-text-strong)]">
|
|
{normalizedProgress}%
|
|
</div>
|
|
</div>
|
|
|
|
<div className="platform-progress-track h-3 overflow-hidden rounded-full">
|
|
<div
|
|
className="h-full rounded-full transition-[width] duration-500"
|
|
style={{
|
|
width: `${Math.max(6, normalizedProgress)}%`,
|
|
...progressFillStyle,
|
|
}}
|
|
/>
|
|
</div>
|
|
<div className="flex flex-wrap items-center justify-between gap-3">
|
|
<button
|
|
type="button"
|
|
onClick={onSummaryClick}
|
|
disabled={disabled}
|
|
className="platform-button platform-button--ghost min-h-0 rounded-full px-3 py-1.5 text-xs disabled:cursor-not-allowed disabled:opacity-45"
|
|
>
|
|
总结当前设定
|
|
</button>
|
|
{isCompleted ? (
|
|
<button
|
|
type="button"
|
|
onClick={onGenerateDraft}
|
|
disabled={disabled}
|
|
className="platform-button platform-button--primary min-h-[3rem] rounded-[1.1rem] px-4 py-3 text-sm disabled:cursor-not-allowed disabled:opacity-45"
|
|
>
|
|
生成游戏设定草稿
|
|
</button>
|
|
) : canQuickFill ? (
|
|
<button
|
|
type="button"
|
|
onClick={onQuickFill}
|
|
disabled={disabled}
|
|
className="platform-button platform-button--ghost min-h-0 rounded-full px-3 py-1.5 text-xs disabled:cursor-not-allowed disabled:opacity-45"
|
|
>
|
|
补全剩余设定
|
|
</button>
|
|
) : null}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|