Add platform status switch

This commit is contained in:
2026-05-12 21:49:08 +08:00
parent 682a491d27
commit a76ab941bc
10 changed files with 195 additions and 5 deletions
@@ -1,7 +1,7 @@
import { useEffect, useMemo, useState, type FormEvent, type ReactNode } from 'react';
import { Boxes, CheckCircle2, Globe2, KeyRound, Pencil, Plus, RotateCcw, Search, ServerCog, ShieldCheck, SlidersHorizontal, Trash2, X } from 'lucide-react';
import type { BaseModelCatalogItem, CatalogProvider, IntegrationPlatform, PlatformModel, PricingRuleSet } from '@easyai-ai-gateway/contracts';
import { Badge, Button, Card, CardContent, CardHeader, CardTitle, ConfirmDialog, EmptyState, FormDialog, Input, Label, ScreenMessage, Select, Table, TableCell, TableHead, TableRow } from '../../components/ui';
import { Badge, Button, Card, CardContent, CardHeader, CardTitle, ConfirmDialog, EmptyState, FormDialog, Input, Label, ScreenMessage, Select, Switch, Table, TableCell, TableHead, TableRow } from '../../components/ui';
import type { LoadState, PlatformWithModelsInput } from '../../types';
import {
authTypes,
@@ -31,6 +31,7 @@ export function PlatformManagementPanel(props: {
state: LoadState;
onDeletePlatform: (platformId: string) => Promise<void>;
onSavePlatform: (input: PlatformWithModelsInput) => Promise<void>;
onTogglePlatformStatus: (platform: IntegrationPlatform, status: 'enabled' | 'disabled') => Promise<void>;
}) {
const defaultProvider = props.providers[0]?.providerKey ?? props.baseModels[0]?.providerKey ?? '';
const [now, setNow] = useState(() => Date.now());
@@ -42,6 +43,7 @@ export function PlatformManagementPanel(props: {
const [globalProxyNoticeOpen, setGlobalProxyNoticeOpen] = useState(false);
const [editingPlatform, setEditingPlatform] = useState<IntegrationPlatform | null>(null);
const [pendingDeletePlatform, setPendingDeletePlatform] = useState<IntegrationPlatform | null>(null);
const [togglingPlatformId, setTogglingPlatformId] = useState('');
const providerMap = useMemo(() => new Map(props.providers.map((item) => [item.providerKey, item])), [props.providers]);
const platformMap = useMemo(() => new Map(props.platforms.map((item) => [item.id, item])), [props.platforms]);
const [form, setForm] = useState<PlatformWizardForm>(() => createEmptyPlatformForm(defaultProvider, providerDefaults(providerMap.get(defaultProvider))));
@@ -157,6 +159,18 @@ export function PlatformManagementPanel(props: {
}
}
async function togglePlatformStatus(platform: IntegrationPlatform, status: 'enabled' | 'disabled') {
setTogglingPlatformId(platform.id);
setValidationMessage('');
try {
await props.onTogglePlatformStatus(platform, status);
} catch (err) {
setValidationMessage(err instanceof Error ? err.message : '切换平台状态失败');
} finally {
setTogglingPlatformId('');
}
}
return (
<section className="pageStack">
<ScreenMessage message={validationMessage} variant="error" onClose={() => setValidationMessage('')} />
@@ -183,9 +197,11 @@ export function PlatformManagementPanel(props: {
platforms={props.platforms}
providerMap={providerMap}
pricingRuleSets={props.pricingRuleSets}
togglingPlatformId={togglingPlatformId}
onDelete={setPendingDeletePlatform}
onCreate={openCreateDialog}
onEdit={openEditDialog}
onToggleStatus={togglePlatformStatus}
/>
) : (
<PlatformModelTable
@@ -404,9 +420,11 @@ function PlatformTable(props: {
platforms: IntegrationPlatform[];
providerMap: Map<string, CatalogProvider>;
pricingRuleSets: PricingRuleSet[];
togglingPlatformId: string;
onCreate: () => void;
onDelete: (platform: IntegrationPlatform) => void;
onEdit: (platform: IntegrationPlatform) => void;
onToggleStatus: (platform: IntegrationPlatform, status: 'enabled' | 'disabled') => void;
}) {
if (!props.platforms.length) {
return (
@@ -438,6 +456,8 @@ function PlatformTable(props: {
const rateLimit = platformRateLimitSummary(platform.rateLimitPolicy);
const runtime = platformRuntimeSummary(platform);
const platformCooldownMs = cooldownRemainingMs(platform.cooldownUntil, props.now);
const isEnabled = platform.status === 'enabled';
const isToggling = props.togglingPlatformId === platform.id;
return (
<TableRow key={platform.id}>
<TableCell>
@@ -467,12 +487,21 @@ function PlatformTable(props: {
</TableCell>
<TableCell>{props.platformModelCount.get(platform.id) ?? 0}</TableCell>
<TableCell>
<span className="platformTableName">
<span className="platformStatusCell">
<span className="platformStatusToggle">
<Switch
aria-label={`${platformDisplayName(platform)} ${isEnabled ? '禁用' : '启用'}平台`}
checked={isEnabled}
disabled={isToggling}
onCheckedChange={(checked) => props.onToggleStatus(platform, checked ? 'enabled' : 'disabled')}
/>
<span>{isEnabled ? '启用' : '禁用'}</span>
</span>
<strong>
{platformCooldownMs > 0 ? (
<Badge variant="warning"></Badge>
) : (
<Badge variant={platform.status === 'enabled' ? 'success' : 'secondary'}>{platform.status}</Badge>
<Badge variant={isEnabled ? 'success' : 'destructive'}>{isEnabled ? '已启用' : '已禁用'}</Badge>
)}
</strong>
<small>{platformCooldownMs > 0 ? `剩余 ${formatCooldownRemaining(platformCooldownMs)}` : runtime}</small>