refactor: convert provider preset selector to flat button layout
Replace dropdown select menu with flat button layout matching MCP design. Selecting a preset now fills the form without auto-submitting.
This commit is contained in:
@@ -3,15 +3,6 @@ import { useForm } from "react-hook-form";
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
|
||||||
Select,
|
|
||||||
SelectContent,
|
|
||||||
SelectGroup,
|
|
||||||
SelectItem,
|
|
||||||
SelectLabel,
|
|
||||||
SelectTrigger,
|
|
||||||
SelectValue,
|
|
||||||
} from "@/components/ui/select";
|
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
@@ -62,14 +53,16 @@ export function ProviderForm({
|
|||||||
}: ProviderFormProps) {
|
}: ProviderFormProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { theme } = useTheme();
|
const { theme } = useTheme();
|
||||||
const [selectedPresetId, setSelectedPresetId] = useState<string>("custom");
|
const [selectedPresetId, setSelectedPresetId] = useState<string | null>(
|
||||||
|
initialData ? null : "custom",
|
||||||
|
);
|
||||||
const [activePreset, setActivePreset] = useState<{
|
const [activePreset, setActivePreset] = useState<{
|
||||||
id: string;
|
id: string;
|
||||||
category?: ProviderCategory;
|
category?: ProviderCategory;
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSelectedPresetId("custom");
|
setSelectedPresetId(initialData ? null : "custom");
|
||||||
setActivePreset(null);
|
setActivePreset(null);
|
||||||
}, [appType, initialData]);
|
}, [appType, initialData]);
|
||||||
|
|
||||||
@@ -174,6 +167,7 @@ export function ProviderForm({
|
|||||||
setSelectedPresetId(value);
|
setSelectedPresetId(value);
|
||||||
if (value === "custom") {
|
if (value === "custom") {
|
||||||
setActivePreset(null);
|
setActivePreset(null);
|
||||||
|
form.reset(defaultValues);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,50 +212,59 @@ export function ProviderForm({
|
|||||||
return (
|
return (
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-6">
|
<form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-6">
|
||||||
<div className="space-y-2">
|
{/* 预设供应商选择(仅新增模式显示) */}
|
||||||
<FormLabel>
|
{!initialData && (
|
||||||
{t("providerPreset.label", { defaultValue: "预设供应商" })}
|
<div className="space-y-3">
|
||||||
</FormLabel>
|
<FormLabel>
|
||||||
<Select value={selectedPresetId} onValueChange={handlePresetChange}>
|
{t("providerPreset.label", { defaultValue: "预设供应商" })}
|
||||||
<SelectTrigger>
|
</FormLabel>
|
||||||
<SelectValue
|
<div className="flex flex-wrap gap-2">
|
||||||
placeholder={t("providerPreset.placeholder", {
|
{/* 自定义按钮 */}
|
||||||
defaultValue: "选择一个预设",
|
<button
|
||||||
})}
|
type="button"
|
||||||
/>
|
onClick={() => handlePresetChange("custom")}
|
||||||
</SelectTrigger>
|
className={`inline-flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
|
||||||
<SelectContent>
|
selectedPresetId === "custom"
|
||||||
<SelectItem value="custom">
|
? "bg-emerald-500 text-white dark:bg-emerald-600"
|
||||||
|
: "bg-gray-100 dark:bg-gray-800 text-gray-500 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-700"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
{t("providerPreset.custom", { defaultValue: "自定义配置" })}
|
{t("providerPreset.custom", { defaultValue: "自定义配置" })}
|
||||||
</SelectItem>
|
</button>
|
||||||
|
|
||||||
|
{/* 预设按钮 */}
|
||||||
{categoryKeys.map((category) => {
|
{categoryKeys.map((category) => {
|
||||||
const entries = groupedPresets[category];
|
const entries = groupedPresets[category];
|
||||||
if (!entries || entries.length === 0) return null;
|
if (!entries || entries.length === 0) return null;
|
||||||
return (
|
return entries.map((entry) => (
|
||||||
<SelectGroup key={category}>
|
<button
|
||||||
<SelectLabel>
|
key={entry.id}
|
||||||
{presetCategoryLabels[category] ??
|
type="button"
|
||||||
t("providerPreset.categoryOther", {
|
onClick={() => handlePresetChange(entry.id)}
|
||||||
defaultValue: "其他",
|
className={`inline-flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
|
||||||
})}
|
selectedPresetId === entry.id
|
||||||
</SelectLabel>
|
? "bg-emerald-500 text-white dark:bg-emerald-600"
|
||||||
{entries.map((entry) => (
|
: "bg-gray-100 dark:bg-gray-800 text-gray-500 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-700"
|
||||||
<SelectItem key={entry.id} value={entry.id}>
|
}`}
|
||||||
{entry.preset.name}
|
title={
|
||||||
</SelectItem>
|
presetCategoryLabels[category] ??
|
||||||
))}
|
t("providerPreset.categoryOther", {
|
||||||
</SelectGroup>
|
defaultValue: "其他",
|
||||||
);
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{entry.preset.name}
|
||||||
|
</button>
|
||||||
|
));
|
||||||
})}
|
})}
|
||||||
</SelectContent>
|
</div>
|
||||||
</Select>
|
<p className="text-xs text-muted-foreground">
|
||||||
<p className="text-xs text-muted-foreground">
|
{t("providerPreset.helper", {
|
||||||
{t("providerPreset.helper", {
|
defaultValue: "选择预设后可继续调整下方字段。",
|
||||||
defaultValue: "选择预设后可继续调整下方字段。",
|
})}
|
||||||
})}
|
</p>
|
||||||
</p>
|
</div>
|
||||||
</div>
|
)}
|
||||||
|
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
|
|||||||
Reference in New Issue
Block a user