6.0 KiB
6.0 KiB
AI Gateway Frontend
AI 网关管理前端,提供供应商配置和用量统计界面。
技术栈
- 运行时: Bun
- 构建工具: Vite
- 语言: TypeScript (strict mode)
- 框架: React
- UI 组件库: TDesign
- 路由: React Router v7
- 数据获取: TanStack Query v5
- 样式: SCSS Modules(禁止使用纯 CSS)
- 测试: Vitest + React Testing Library + Playwright
API 层
字段转换机制
后端使用 snake_case,前端使用 camelCase,API 层自动转换:
// 发送请求时:camelCase → snake_case
toApi({ providerId: "openai" }) // → { provider_id: "openai" }
// 接收响应时:snake_case → camelCase
fromApi({ provider_id: "openai" }) // → { providerId: "openai" }
统一请求函数
export async function request<T>(method: string, path: string, body?: unknown): Promise<T>
- 自动处理字段转换
- 自动处理 204 响应(无 body)
- 抛出
ApiError包含status、code、message
错误处理
class ApiError extends Error {
status: number; // HTTP 状态码
code?: string; // 业务错误码
message: string; // 错误消息
}
TanStack Query 模式
Query Keys 定义
// src/hooks/useProviders.ts
export const providerKeys = {
all: ['providers'] as const,
};
// src/hooks/useModels.ts
export const modelKeys = {
all: ['models'] as const,
byProvider: (providerId: string) => [...modelKeys.all, { providerId }] as const,
};
Mutation 使用
const mutation = useMutation({
mutationFn: createProvider,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: providerKeys.all });
},
});
项目结构
frontend/
├── src/
│ ├── api/ # API 层
│ │ ├── client.ts # 统一 request<T>() + 字段转换
│ │ ├── providers.ts # Provider CRUD
│ │ ├── models.ts # Model CRUD
│ │ └── stats.ts # Stats 查询
│ ├── components/
│ │ └── AppLayout/ # 侧边栏导航布局
│ ├── hooks/ # TanStack Query hooks
│ │ ├── useProviders.ts
│ │ ├── useModels.ts
│ │ └── useStats.ts
│ ├── pages/
│ │ ├── Providers/ # 供应商管理(含内嵌模型管理)
│ │ ├── Stats/ # 用量统计
│ │ ├── Settings/ # 设置(开发中)
│ │ └── NotFound.tsx
│ ├── routes/
│ │ └── index.tsx # 路由配置
│ ├── types/
│ │ └── index.ts # 类型定义
│ ├── __tests__/ # 测试
│ │ ├── setup.ts
│ │ ├── api/
│ │ ├── hooks/
│ │ └── components/
│ ├── App.tsx
│ ├── main.tsx
│ └── index.scss
├── e2e/ # Playwright E2E 测试
├── vitest.config.ts
├── playwright.config.ts
├── tsconfig.json
├── vite.config.ts
└── package.json
运行方式
安装依赖
bun install
开发模式
bun run dev
前端将在端口 5173 启动,API 请求通过 Vite proxy 转发到后端(localhost:9826)。
构建生产版本
bun run build
代码检查
bun run lint
测试
单元测试 + 组件测试
bun run test # 运行所有测试
bun run test:watch # 监听模式
bun run test:coverage # 生成覆盖率报告
E2E 测试
bun run test:e2e
功能
供应商管理
- 查看供应商列表(TDesign Table)
- 添加新供应商(Modal Form)
- 编辑供应商配置
- 删除供应商(Popconfirm 确认)
- API Key 脱敏显示
- 启用/禁用状态标签
- 协议字段:支持 OpenAI 和 Anthropic 协议选择
模型管理
- 展开供应商行查看关联模型
- 添加/编辑/删除模型
- 按供应商筛选模型
- 统一模型 ID:显示格式为
provider_id/model_name,用于跨协议模型识别 - UUID 自动生成:创建模型时后端自动生成 UUID,无需手动输入 ID
用量统计
- 查看统计数据
- 按供应商筛选
- 按模型筛选
- 按日期范围筛选(DatePicker.RangePicker)
测试策略
目录结构
__tests__/
├── setup.ts # 测试配置(happy-dom)
├── api/ # API 层测试
│ └── client.test.ts
├── hooks/ # TanStack Query Hook 测试
│ ├── useProviders.test.ts
│ └── useModels.test.ts
└── components/ # 组件测试
└── AppLayout.test.tsx
E2E 测试
- 位于
e2e/目录 - 使用 Playwright
- 自动启动后端服务(临时端口 19026)
- 配置文件:
playwright.config.ts
Mock 策略
- API 层测试使用 MSW(Mock Service Worker)
- Hook 测试使用
@testing-library/react-hooks - 组件测试使用
@testing-library/react
环境变量
| 变量 | 开发环境 | 生产环境 | 说明 |
|---|---|---|---|
VITE_API_BASE |
(空) | /api |
API 基础路径,空则走 Vite proxy |
E2E 测试特有:
NEX_BACKEND_PORT- E2E 后端端口(默认 19026)NEX_E2E_TEMP_DIR- E2E 临时目录
开发规范
- 所有样式使用 SCSS,禁止使用纯 CSS 文件
- 组件级样式使用 SCSS Modules(*.module.scss)
- 图标优先使用 TDesign 图标(tdesign-icons-react)
- TypeScript strict 模式,禁止 any 类型
- API 层自动处理 snake_case ↔ camelCase 字段转换
- 使用路径别名
@/引用 src 目录
环境要求
- Bun 1.0 或更高版本
添加新页面
- 在
src/pages/创建页面目录和组件 - 在
src/hooks/创建对应的 TanStack Query hook - 在
src/routes/index.tsx添加路由 - 在
src/components/AppLayout/index.tsx的 Menu 中添加 MenuItem