Add connection testing feature to ComponentsModelsPage

Implemented a new connection testing functionality in ComponentsModelsPage, allowing users to test API connectivity. Added state management for testing status and results, along with UI updates to display connection success or failure. Enhanced button interactions for improved user experience during testing.
This commit is contained in:
Xin Wang
2026-06-08 00:02:18 +08:00
parent 328e24e2e1
commit 82ca52d438

View File

@@ -2,15 +2,19 @@
import {
Brain,
CheckCircle2,
ChevronLeft,
ChevronRight,
Eye,
EyeOff,
Loader2,
MoreHorizontal,
Pencil,
Plug,
Plus,
Search,
Trash2,
XCircle,
} from "lucide-react";
import { Button } from "@/components/ui/button";
@@ -192,8 +196,28 @@ export function ComponentsModelsPage() {
const [form, setForm] = useState<ModelForm>(emptyForm);
const [showKey, setShowKey] = useState(false);
const [testing, setTesting] = useState(false);
const [testResult, setTestResult] = useState<"idle" | "ok" | "fail">("idle");
function updateForm<K extends keyof ModelForm>(key: K, value: ModelForm[K]) {
setForm((prev) => ({ ...prev, [key]: value }));
// 任何配置变更后,旧的测试结果不再可信,重置为待测状态
setTestResult("idle");
}
async function handleTestConnection() {
setTesting(true);
setTestResult("idle");
try {
// TODO: 接入真实疎通接口(按 form.interfaceType 区分调用方式)
await new Promise((resolve) => setTimeout(resolve, 900));
const reachable = Boolean(form.apiUrl.trim() && form.apiKey.trim());
setTestResult(reachable ? "ok" : "fail");
} catch {
setTestResult("fail");
} finally {
setTesting(false);
}
}
function handleTypeChange(type: ModelType) {
@@ -206,12 +230,14 @@ export function ComponentsModelsPage() {
? prev.interfaceType
: options[0],
}));
setTestResult("idle");
}
function openCreate() {
setEditingId(null);
setForm(emptyForm);
setShowKey(false);
setTestResult("idle");
setDialogOpen(true);
}
@@ -225,6 +251,7 @@ export function ComponentsModelsPage() {
apiKey: model.apiKey,
});
setShowKey(false);
setTestResult("idle");
setDialogOpen(true);
}
@@ -576,22 +603,53 @@ export function ComponentsModelsPage() {
</label>
</div>
<DialogFooter>
<Button
variant="outline"
className="border-hairline-strong text-muted-foreground hover:text-foreground"
onClick={() => setDialogOpen(false)}
>
</Button>
<Button
className="gap-2"
disabled={!canSave}
onClick={() => setDialogOpen(false)}
>
<Brain size={16} />
{editingId ? "保存" : "添加"}
</Button>
<DialogFooter className="sm:items-center sm:justify-between">
<div className="flex items-center gap-3">
<Button
variant="outline"
size="sm"
className="gap-2 border-hairline-strong text-muted-foreground hover:text-foreground"
disabled={!canSave || testing}
onClick={handleTestConnection}
>
{testing ? (
<Loader2 size={14} className="animate-spin" />
) : (
<Plug size={14} />
)}
</Button>
{testResult === "ok" && (
<span className="flex items-center gap-1.5 text-xs text-emerald-500">
<CheckCircle2 size={14} />
</span>
)}
{testResult === "fail" && (
<span className="flex items-center gap-1.5 text-xs text-destructive">
<XCircle size={14} />
</span>
)}
</div>
<div className="flex items-center gap-2">
<Button
variant="outline"
className="border-hairline-strong text-muted-foreground hover:text-foreground"
onClick={() => setDialogOpen(false)}
>
</Button>
<Button
className="gap-2"
disabled={!canSave}
onClick={() => setDialogOpen(false)}
>
<Brain size={16} />
{editingId ? "保存" : "添加"}
</Button>
</div>
</DialogFooter>
</DialogContent>
</Dialog>