import { useEffect, useMemo, useState, type FormEvent } from 'react'; import type { BaseModelCatalogItem, CatalogProvider, GatewayTenant, GatewayUser, IntegrationPlatform, PlatformModel, PricingRule, RateLimitWindow, UserGroup, } from '@easyai-ai-gateway/contracts'; import { getHealth, listBaseModels, listCatalogProviders, listModels, listPlatforms, listPricingRules, listRateLimitWindows, listTenants, listUserGroups, listUsers, loginLocalAccount, registerLocalAccount, type HealthResponse, } from './api'; type LoadState = 'idle' | 'loading' | 'ready' | 'error'; type AuthMode = 'login' | 'register' | 'external'; const primaryModules = [ { title: '首页', path: '/', description: '服务状态、推荐模型、最近任务、用量摘要和快捷入口。', items: ['能力概览', '最近任务', '用量摘要'], }, { title: '模型', path: '/models', description: '按能力、价格、限流和 provider 浏览模型,并进入在线试用。', items: ['模型广场', '模型详情', '调用测试'], }, { title: '用户工作台', path: '/workspace', description: '个人中心、身份来源、余额充值、API Key 管理和任务记录。', items: ['个人总览', '身份来源', '余额充值', 'API Key', '任务记录'], }, { title: '管理工作台', path: '/admin', description: '租户、用户、用户组、全局模型、平台、限流、重试、队列和回调 outbox。', items: ['租户管理', '用户管理', '用户组策略', '全局模型', '队列限流'], }, { title: 'API 文档', path: '/docs', description: '开放接口、鉴权、错误码、示例代码和在线调用测试。', items: ['快速开始', '接口文档', '在线调试'], }, ]; const workspacePages = [ { title: '个人中心总览', path: '/workspace/overview', description: '账号、身份来源、租户、角色、用户组、余额、API Key 数、最近任务和用量摘要。' }, { title: '余额与充值', path: '/workspace/billing', description: '余额、资源包、充值入口、用户组折扣、消费记录和订单状态。' }, { title: 'API Key 管理', path: '/workspace/api-keys', description: '创建、禁用、重置、权限范围和最近调用记录。' }, { title: '任务记录', path: '/workspace/tasks', description: 'Chat、生图、生视频任务列表、进度、结果和计费明细。' }, ]; const adminPages = [ { title: '租户管理', path: '/admin/tenants', description: '本地租户、同步租户、租户策略、状态和用量隔离。' }, { title: '用户管理', path: '/admin/users', description: '本地用户、同步用户、角色、状态、同步差异和用户组命中。' }, { title: '用户组策略', path: '/admin/user-groups', description: '用户组成员、充值折扣、调用折扣、TPM/RPM/并发和队列优先级。' }, { title: '全局模型配置', path: '/admin/models/global', description: '基准模型库、能力 schema、基准定价和默认限流模板。' }, { title: '平台管理', path: '/admin/platforms', description: '平台 CRUD、凭证、默认折扣、平台模型、限流和重试策略。' }, { title: '运行与队列', path: '/admin/runtime/queues', description: 'TPM/RPM 窗口、并发 lease、cooldown、任务恢复和队列积压。' }, { title: '回调与结算', path: '/admin/callbacks', description: '任务进度 callback outbox、结算 outbox、失败重试和手动 replay。' }, ]; const apiDocPages = [ { title: '鉴权与限流', path: '/docs/auth', description: '本地账号、JWT、OpenAPI Key、TPM/RPM/并发限制和错误码。' }, { title: 'Chat / Responses', path: '/docs/api/chat', description: '对话、stream、结构化输出、取消请求和示例代码。' }, { title: '图片 / 视频', path: '/docs/api/media', description: '生图、图像编辑、生视频、任务进度和结果取回。' }, { title: '在线调用测试', path: '/docs/playground', description: '选择模型和 API Key,编辑参数,查看实时响应和 billings。' }, ]; export function App() { const [token, setToken] = useState(''); const [externalToken, setExternalToken] = useState(''); const [authMode, setAuthMode] = useState('login'); const [loginForm, setLoginForm] = useState({ account: '', password: '' }); const [registerForm, setRegisterForm] = useState({ username: '', email: '', password: '', displayName: '', tenantKey: '', tenantName: '', invitationCode: '', }); const [health, setHealth] = useState(null); const [platforms, setPlatforms] = useState([]); const [models, setModels] = useState([]); const [providers, setProviders] = useState([]); const [baseModels, setBaseModels] = useState([]); const [pricingRules, setPricingRules] = useState([]); const [rateLimitWindows, setRateLimitWindows] = useState([]); const [tenants, setTenants] = useState([]); const [users, setUsers] = useState([]); const [userGroups, setUserGroups] = useState([]); const [state, setState] = useState('idle'); const [error, setError] = useState(''); useEffect(() => { getHealth() .then(setHealth) .catch((err: Error) => setError(err.message)); }, []); const stats = useMemo(() => { const enabledPlatforms = platforms.filter((item) => item.status === 'enabled').length; const enabledModels = models.filter((item) => item.enabled).length; const activeProviders = providers.filter((item) => item.status === 'active').length; const activeRateWindows = rateLimitWindows.filter((item) => item.resetAt >= new Date().toISOString()).length; return [ { label: '租户', value: tenants.length, tone: 'cyan' }, { label: '用户', value: users.length, tone: 'green' }, { label: '用户组', value: userGroups.length, tone: 'blue' }, { label: '平台', value: platforms.length, tone: 'blue' }, { label: '启用平台', value: enabledPlatforms, tone: 'green' }, { label: '基准模型', value: baseModels.length, tone: 'violet' }, { label: 'Provider', value: activeProviders || providers.length || enabledModels, tone: 'amber' }, { label: '定价规则', value: pricingRules.length, tone: 'cyan' }, { label: '限流窗口', value: activeRateWindows, tone: 'rose' }, ]; }, [baseModels.length, models, platforms, pricingRules.length, providers, rateLimitWindows, tenants.length, userGroups.length, users.length]); async function refresh(nextToken = token) { setState('loading'); setError(''); try { const [ platformResponse, modelResponse, providerResponse, baseModelResponse, pricingRuleResponse, rateLimitWindowResponse, tenantResponse, userResponse, userGroupResponse, ] = await Promise.all([ listPlatforms(nextToken), listModels(nextToken), listCatalogProviders(nextToken), listBaseModels(nextToken), listPricingRules(nextToken), listRateLimitWindows(nextToken), listTenants(nextToken), listUsers(nextToken), listUserGroups(nextToken), ]); setPlatforms(platformResponse.items); setModels(modelResponse.items); setProviders(providerResponse.items); setBaseModels(baseModelResponse.items); setPricingRules(pricingRuleResponse.items); setRateLimitWindows(rateLimitWindowResponse.items); setTenants(tenantResponse.items); setUsers(userResponse.items); setUserGroups(userGroupResponse.items); setState('ready'); } catch (err) { setState('error'); setError(err instanceof Error ? err.message : '加载失败'); } } async function submitLogin(event: FormEvent) { event.preventDefault(); setState('loading'); setError(''); try { const response = await loginLocalAccount(loginForm); setToken(response.accessToken); await refresh(response.accessToken); } catch (err) { setState('error'); setError(err instanceof Error ? err.message : '登录失败'); } } async function submitRegister(event: FormEvent) { event.preventDefault(); setState('loading'); setError(''); try { const response = await registerLocalAccount(registerForm); setToken(response.accessToken); await refresh(response.accessToken); } catch (err) { setState('error'); setError(err instanceof Error ? err.message : '注册失败'); } } async function submitExternalToken(event: FormEvent) { event.preventDefault(); const nextToken = externalToken.trim(); if (!nextToken) { setError('请填写 access token'); return; } setToken(nextToken); await refresh(nextToken); } function signOut() { setToken(''); setState('idle'); setPlatforms([]); setModels([]); setProviders([]); setBaseModels([]); setPricingRules([]); setRateLimitWindows([]); setTenants([]); setUsers([]); setUserGroups([]); } return (

EasyAI

AI Gateway Console

{health?.identityMode ? `${health.service} · ${health.identityMode}` : health?.service ?? 'API 未连接'}
{token && ( )}
{!token ? ( ) : ( <>
)} {error &&
{error}
}
); } function AuthPanel(props: { authMode: AuthMode; externalToken: string; loginForm: { account: string; password: string }; registerForm: { username: string; email: string; password: string; displayName: string; tenantKey: string; tenantName: string; invitationCode: string; }; state: LoadState; onAuthModeChange: (value: AuthMode) => void; onExternalTokenChange: (value: string) => void; onLoginChange: (value: { account: string; password: string }) => void; onRegisterChange: (value: { username: string; email: string; password: string; displayName: string; tenantKey: string; tenantName: string; invitationCode: string; }) => void; onSubmitExternalToken: (event: FormEvent) => void; onSubmitLogin: (event: FormEvent) => void; onSubmitRegister: (event: FormEvent) => void; }) { return (

Gateway Identity

登录 AI Gateway

{[ ['login', '账号登录'], ['register', '注册账号'], ['external', '外部 Token'], ].map(([value, label]) => ( ))}
{props.authMode === 'login' && (
)} {props.authMode === 'register' && (
)} {props.authMode === 'external' && (
)}
); } function Dashboard(props: { baseModels: BaseModelCatalogItem[]; models: PlatformModel[]; platforms: IntegrationPlatform[]; rateLimitWindows: RateLimitWindow[]; stats: Array<{ label: string; value: number; tone: string }>; }) { return ( <>

Navigation

前端页面结构

5 个一级模块
{primaryModules.map((item) => (

{item.title}

{item.path}

{item.description}

{item.items.map((tag) => ( {tag} ))}
))}

Workspace

用户、管理与 API 文档

设计分区
{props.stats.map((item) => (
{item.label} {item.value}
))}
[item.provider, item.name, item.status, String(item.priority)])} title="平台" /> [item.modelName, item.modelType, item.provider ?? item.platformName ?? '-', item.enabled ? '是' : '否'])} title="模型" />
[item.providerKey, item.canonicalModelKey, item.modelType, String(item.pricingVersion)])} title="基准模型库" /> [item.scopeKey, item.metric, `${item.usedValue}/${item.limitValue}`, String(item.reservedValue)])} title="TPM/RPM 窗口" />
); } function DataPanel(props: { columns: string[]; empty: string; rows: string[][]; title: string }) { return (

{props.title}

{props.rows.length}
{props.columns.map((column) => ( {column} ))}
{props.rows.map((row, index) => (
{row.map((cell, cellIndex) => ( {cell} ))}
))} {!props.rows.length &&

{props.empty}

}
); } function ModuleList(props: { title: string; items: Array<{ title: string; path: string; description: string }>; }) { return (

{props.title}

{props.items.map((item) => (
{item.title}

{item.description}

{item.path}
))}
); }