import type { FormEvent, ReactNode } from 'react'; import { Boxes, Building2, Gauge, KeyRound, Route, ServerCog, ShieldCheck, UsersRound, Workflow } from 'lucide-react'; import type { BaseModelUpsertRequest, CatalogProviderUpsertRequest, PricingRuleSetUpsertRequest } from '@easyai-ai-gateway/contracts'; import type { ConsoleData, StatItem } from '../app-state'; import { EntityTable } from '../components/EntityTable'; import { PageHeader } from '../components/PageHeader'; import { StatGrid } from '../components/StatGrid'; import { Badge, Button, Card, CardContent, CardHeader, CardTitle, Input, Label, Select, Tabs } from '../components/ui'; import type { AdminSection, LoadState, PlatformForm, PlatformModelForm } from '../types'; import { BaseModelCatalogPanel } from './admin/BaseModelCatalogPanel'; import { PricingRulesPanel } from './admin/PricingRulesPanel'; import { ProviderManagementPanel } from './admin/ProviderManagementPanel'; const tabs = [ { value: 'overview', label: '总览', icon: }, { value: 'globalModels', label: 'Provider', icon: }, { value: 'baseModels', label: '基准模型库', icon: }, { value: 'pricing', label: '定价规则', icon: }, { value: 'platforms', label: '平台管理', icon: }, { value: 'tenants', label: '租户', icon: }, { value: 'users', label: '用户', icon: }, { value: 'userGroups', label: '用户组', icon: }, { value: 'runtime', label: '运行限流', icon: }, ] satisfies Array<{ value: AdminSection; label: string; icon: ReactNode }>; export function AdminPage(props: { data: ConsoleData; platformForm: PlatformForm; platformModelForm: PlatformModelForm; operationMessage: string; section: AdminSection; stats: StatItem[]; state: LoadState; onDeleteBaseModel: (baseModelId: string) => Promise; onDeleteProvider: (providerId: string) => Promise; onDeletePricingRuleSet: (ruleSetId: string) => Promise; onPlatformFormChange: (value: PlatformForm) => void; onPlatformModelFormChange: (value: PlatformModelForm) => void; onSaveBaseModel: (input: BaseModelUpsertRequest, baseModelId?: string) => Promise; onSaveProvider: (input: CatalogProviderUpsertRequest, providerId?: string) => Promise; onSavePricingRuleSet: (input: PricingRuleSetUpsertRequest, ruleSetId?: string) => Promise; onSectionChange: (value: AdminSection) => void; onSubmitPlatform: (event: FormEvent) => void; onSubmitPlatformModel: (event: FormEvent) => void; }) { return ( {props.section === 'overview' && } {props.section === 'globalModels' && ( )} {props.section === 'baseModels' && ( )} {props.section === 'pricing' && ( )} {props.section === 'platforms' && } {props.section === 'tenants' && } {props.section === 'users' && } {props.section === 'userGroups' && } {props.section === 'runtime' && } ); } function OverviewPanel(props: { data: ConsoleData; stats: StatItem[] }) { const enabledPlatforms = props.data.platforms.filter((item) => item.status === 'enabled'); const chatModels = props.data.models.filter((item) => item.modelType === 'chat' && item.enabled); const imageModels = props.data.models.filter((item) => item.modelType === 'image' && item.enabled); return ( } label="路由候选" value={enabledPlatforms.length} detail="平台优先级 / 失败切换" /> } label="策略对象" value={props.data.userGroups.length} detail="用户组 / 折扣 / 并发" /> } label="运行窗口" value={props.data.rateLimitWindows.length} detail="TPM / RPM / 并发" /> 可用平台 [item.provider, item.name, item.status, item.priority])} /> 近期任务 {props.data.taskResult ? ( {props.data.taskResult.status} {props.data.taskResult.model} {JSON.stringify(props.data.taskResult.result ?? {}, null, 2)} ) : ( 暂无任务记录 )} 模型能力 item.modelType === 'video').length, 'Next', '/v1/videos/*'], ]} /> 限流窗口 [item.scopeKey, item.metric, item.usedValue, item.limitValue])} /> ); } function ManagementCard(props: { detail: string; icon: ReactNode; label: string; value: number }) { return ( {props.icon} {props.label} {props.value} {props.detail} ); } function PlatformsPanel(props: { data: ConsoleData; platformForm: PlatformForm; platformModelForm: PlatformModelForm; state: LoadState; onPlatformFormChange: (value: PlatformForm) => void; onPlatformModelFormChange: (value: PlatformModelForm) => void; onSubmitPlatform: (event: FormEvent) => void; onSubmitPlatformModel: (event: FormEvent) => void; }) { return ( 创建平台 Provider props.onPlatformFormChange({ ...props.platformForm, provider: event.target.value })} /> 平台 Key props.onPlatformFormChange({ ...props.platformForm, platformKey: event.target.value })} /> 名称 props.onPlatformFormChange({ ...props.platformForm, name: event.target.value })} /> Base URL props.onPlatformFormChange({ ...props.platformForm, baseUrl: event.target.value })} /> 定价规则 props.onPlatformFormChange({ ...props.platformForm, pricingRuleSetId: event.target.value })}> 默认规则 {props.data.pricingRuleSets.map((item) => {item.name})} 平台折扣率 props.onPlatformFormChange({ ...props.platformForm, defaultDiscountFactor: event.target.value })} /> 创建平台 绑定平台模型 平台 props.onPlatformModelFormChange({ ...props.platformModelForm, platformId: event.target.value })}> 选择平台 {props.data.platforms.map((item) => {item.name})} 基准模型 updateBaseModel(event.target.value, props)}> 选择基准模型 {props.data.baseModels.map((item) => {item.canonicalModelKey})} 模型名 props.onPlatformModelFormChange({ ...props.platformModelForm, modelName: event.target.value })} /> 别名 props.onPlatformModelFormChange({ ...props.platformModelForm, modelAlias: event.target.value })} /> 定价规则 props.onPlatformModelFormChange({ ...props.platformModelForm, pricingRuleSetId: event.target.value })}> 继承平台规则 {props.data.pricingRuleSets.map((item) => {item.name})} 模型折扣率 props.onPlatformModelFormChange({ ...props.platformModelForm, discountFactor: event.target.value })} /> 绑定模型 平台模型 [item.modelName, item.modelType, item.platformName ?? item.provider ?? '-', item.enabled ? 'enabled' : 'disabled'])} /> ); } function TenantsPanel(props: { data: ConsoleData }) { return 租户管理 [item.tenantKey, item.name, item.source, item.status])} />; } function UsersPanel(props: { data: ConsoleData }) { return 用户管理 [item.username, item.tenantKey ?? '-', item.source, item.status])} />; } function UserGroupsPanel(props: { data: ConsoleData }) { return 用户组策略 [item.groupKey, item.name, item.priority, item.status])} />; } function RuntimePanel(props: { data: ConsoleData }) { return ( TPM / RPM / 并发窗口 {props.data.rateLimitWindows.length} [item.scopeKey, item.metric, item.usedValue, item.limitValue])} /> ); } function updateBaseModel(value: string, props: Parameters[0]) { const base = props.data.baseModels.find((item) => item.canonicalModelKey === value); props.onPlatformModelFormChange({ ...props.platformModelForm, canonicalModelKey: value, modelAlias: value, modelName: base?.providerModelName ?? '', modelType: base?.modelType ?? props.platformModelForm.modelType, }); }
{JSON.stringify(props.data.taskResult.result ?? {}, null, 2)}