feat(*): 创作与运维 - 新增图片尺寸预设和系统性能面板并优化图片组动画
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import { ImageSizePresetsEditor } from "./image-size-presets-editor";
|
||||
import { imageSizeConfigWithPresets, imageSizePresets } from "@/lib/image-size-presets";
|
||||
import { Input, InputNumber, Segmented, Select, Switch } from "antd";
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
@@ -18,20 +20,8 @@ const operationOptions = [
|
||||
{ label: "音频生视频", value: "audio_to_video" },
|
||||
];
|
||||
|
||||
function formatImageSizeTagLabel(size: string): string {
|
||||
const raw = size.trim();
|
||||
if (raw === "1:1") return "1:1 (方图)";
|
||||
if (raw === "16:9") return "16:9 (横屏)";
|
||||
if (raw === "9:16") return "9:16 (竖屏)";
|
||||
if (raw === "1024x1024") return "1024x1024 (1:1)";
|
||||
if (raw === "2048x2048") return "2048x2048 (2K 方)";
|
||||
if (raw === "3840x2160") return "3840x2160 (4K 横屏)";
|
||||
if (raw === "2160x3840") return "2160x3840 (4K 竖屏)";
|
||||
return raw;
|
||||
}
|
||||
|
||||
function imageSizeOptions(values: string[]) {
|
||||
return values.map((v) => ({ label: formatImageSizeTagLabel(v), value: v }));
|
||||
function ImageSizeHelp() {
|
||||
return <p className="text-[var(--fs-label)] leading-relaxed text-foreground/60">按分辨率配置支持的比例,尺寸自动换算。size 发送像素,aspect_ratio 发送比例;独立分辨率由模型协议适配。实际输出尺寸以上游为准。</p>;
|
||||
}
|
||||
|
||||
type Props = {
|
||||
@@ -434,57 +424,40 @@ function ImageCapabilityEditor({ value, onChange, protocol, model, disabled, sec
|
||||
|
||||
if (section === "protocol") {
|
||||
return (
|
||||
<div className="admin-capability-protocol-editor">
|
||||
<div className="admin-capability-protocol-grid">
|
||||
<ProtocolParameterCard step="01" title="输出数量" description="设置单次生成图片数量">
|
||||
<NumberField label="单次生成张数" value={profile.maxOutputs} min={1} disabled={disabled} onChange={(maxOutputs) => update({ maxOutputs: maxOutputs || 1 })} />
|
||||
</ProtocolParameterCard>
|
||||
<ProtocolParameterCard step="02" title="尺寸参数" description="定义尺寸字段、支持值与默认值">
|
||||
<Segmented
|
||||
block
|
||||
disabled={disabled}
|
||||
value={profile.size.parameter}
|
||||
options={[
|
||||
{ label: "不发送", value: "none" },
|
||||
{ label: "size", value: "size" },
|
||||
{ label: "aspect_ratio", value: "aspect_ratio" },
|
||||
]}
|
||||
onChange={(value) => {
|
||||
const parameter = value as ImageCapabilityConfig["size"]["parameter"];
|
||||
updateSize(
|
||||
parameter === "none"
|
||||
? { parameter, values: [], default: "auto", allowCustom: false }
|
||||
: { parameter, values: profile.size.values.length ? profile.size.values : ["1:1"], default: profile.size.default === "auto" ? "1:1" : profile.size.default },
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<div className="admin-capability-protocol-editor admin-image-protocol-editor">
|
||||
<div className="admin-capability-protocol-grid admin-image-protocol-grid">
|
||||
<ProtocolParameterCard step="01" title="尺寸参数" description="按分辨率配置可用画幅,直接点选或输入比例" className="admin-image-size-card">
|
||||
<div className="admin-image-size-intro">
|
||||
<Segmented
|
||||
block
|
||||
disabled={disabled}
|
||||
value={profile.size.parameter}
|
||||
options={[
|
||||
{ label: "不发送", value: "none" },
|
||||
{ label: "size", value: "size" },
|
||||
{ label: "aspect_ratio", value: "aspect_ratio" },
|
||||
]}
|
||||
onChange={(value) => {
|
||||
const parameter = value as ImageCapabilityConfig["size"]["parameter"];
|
||||
updateSize(
|
||||
parameter === "none"
|
||||
? { parameter, values: [], presets: undefined, default: "auto", allowCustom: false }
|
||||
: imageSizeConfigWithPresets({ ...profile, size: { ...profile.size, parameter } }, imageSizePresets(profile)),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<ImageSizeHelp />
|
||||
</div>
|
||||
{profile.size.parameter !== "none" ? (
|
||||
<>
|
||||
<Field label="支持值">
|
||||
<Select
|
||||
mode="tags"
|
||||
className="admin-capability-tags w-full"
|
||||
disabled={disabled}
|
||||
value={profile.size.values}
|
||||
options={imageSizeOptions(profile.size.values)}
|
||||
tokenSeparators={[","]}
|
||||
placeholder="例如 1:1、1024x1024"
|
||||
onChange={(values) => updateSize({ values, default: values.includes(profile.size.default) || profile.size.allowCustom ? profile.size.default : values[0] || "auto" })}
|
||||
/>
|
||||
</Field>
|
||||
<Field label="默认值">
|
||||
<Select
|
||||
className="w-full"
|
||||
disabled={disabled}
|
||||
value={profile.size.default}
|
||||
options={profile.size.values.map((item) => ({ label: item, value: item }))}
|
||||
onChange={(defaultValue) => updateSize({ default: defaultValue })}
|
||||
/>
|
||||
</Field>
|
||||
<ImageSizePresetsEditor profile={profile} disabled={disabled} onChange={updateSize} />
|
||||
<ParameterField label="允许自定义" description="允许支持值之外的尺寸" supported={profile.size.allowCustom} disabled={disabled} onChange={(allowCustom) => updateSize({ allowCustom })} />
|
||||
</>
|
||||
) : null}
|
||||
</ProtocolParameterCard>
|
||||
<ProtocolParameterCard step="02" title="输出数量" description="设置单次生成图片数量">
|
||||
<NumberField label="单次生成张数" value={profile.maxOutputs} min={1} disabled={disabled} onChange={(maxOutputs) => update({ maxOutputs: maxOutputs || 1 })} />
|
||||
</ProtocolParameterCard>
|
||||
<ProtocolParameterCard step="03" title="可选参数" description="控制质量、背景与响应格式">
|
||||
<ParameterField label="图片质量" description="发送 quality 参数" supported={profile.quality.supported} disabled={disabled} onChange={(supported) => updateQuality({ supported })} />
|
||||
{profile.quality.supported ? (
|
||||
@@ -543,6 +516,7 @@ function ImageCapabilityEditor({ value, onChange, protocol, model, disabled, sec
|
||||
<NumberField label="单次生成张数" value={profile.maxOutputs} min={1} disabled={disabled} onChange={(maxOutputs) => update({ maxOutputs: maxOutputs || 1 })} />
|
||||
</CapabilityBlock>
|
||||
<CapabilityBlock title="尺寸参数">
|
||||
<ImageSizeHelp />
|
||||
<Segmented
|
||||
block
|
||||
disabled={disabled}
|
||||
@@ -555,38 +529,14 @@ function ImageCapabilityEditor({ value, onChange, protocol, model, disabled, sec
|
||||
onChange={(value) => {
|
||||
const parameter = value as ImageCapabilityConfig["size"]["parameter"];
|
||||
updateSize(
|
||||
parameter === "none"
|
||||
? { parameter, values: [], default: "auto", allowCustom: false }
|
||||
: { parameter, values: profile.size.values.length ? profile.size.values : ["1:1"], default: profile.size.default === "auto" ? "1:1" : profile.size.default },
|
||||
parameter === "none" ? { parameter, values: [], presets: undefined, default: "auto", allowCustom: false } : imageSizeConfigWithPresets({ ...profile, size: { ...profile.size, parameter } }, imageSizePresets(profile)),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
{profile.size.parameter !== "none" ? (
|
||||
<>
|
||||
<Field label="支持值">
|
||||
<Select
|
||||
mode="tags"
|
||||
className="admin-capability-tags w-full"
|
||||
disabled={disabled}
|
||||
value={profile.size.values}
|
||||
options={imageSizeOptions(profile.size.values)}
|
||||
tokenSeparators={[","]}
|
||||
placeholder="例如 1:1、1024x1024"
|
||||
onChange={(values) => updateSize({ values, default: values.includes(profile.size.default) || profile.size.allowCustom ? profile.size.default : values[0] || "auto" })}
|
||||
/>
|
||||
</Field>
|
||||
<div className="grid gap-3 sm:grid-cols-2">
|
||||
<Field label="默认值">
|
||||
<Select
|
||||
className="w-full"
|
||||
disabled={disabled}
|
||||
value={profile.size.default}
|
||||
options={profile.size.values.map((item) => ({ label: item, value: item }))}
|
||||
onChange={(defaultValue) => updateSize({ default: defaultValue })}
|
||||
/>
|
||||
</Field>
|
||||
<ParameterField label="允许自定义" description="允许用户输入支持值之外的尺寸" supported={profile.size.allowCustom} disabled={disabled} onChange={(allowCustom) => updateSize({ allowCustom })} />
|
||||
</div>
|
||||
<ImageSizePresetsEditor profile={profile} disabled={disabled} onChange={updateSize} />
|
||||
<ParameterField label="允许自定义" description="允许用户输入支持值之外的尺寸" supported={profile.size.allowCustom} disabled={disabled} onChange={(allowCustom) => updateSize({ allowCustom })} />
|
||||
</>
|
||||
) : null}
|
||||
</CapabilityBlock>
|
||||
@@ -665,9 +615,9 @@ function ReferenceCard({ title, description, children }: { title: string; descri
|
||||
);
|
||||
}
|
||||
|
||||
function ProtocolParameterCard({ step, title, description, children }: { step: string; title: string; description: string; children: ReactNode }) {
|
||||
function ProtocolParameterCard({ step, title, description, children, className = "" }: { step: string; title: string; description: string; children: ReactNode; className?: string }) {
|
||||
return (
|
||||
<section className="admin-capability-protocol-card">
|
||||
<section className={`admin-capability-protocol-card ${className}`}>
|
||||
<header className="admin-capability-protocol-card-heading">
|
||||
<span>{step}</span>
|
||||
<div>
|
||||
|
||||
Reference in New Issue
Block a user