1
0

docs: 更新三份 README 文档以反映实际项目情况

This commit is contained in:
2026-04-22 16:05:23 +08:00
parent f5e45d032e
commit 72aebef625
3 changed files with 274 additions and 20 deletions

View File

@@ -14,6 +14,68 @@ AI 网关管理前端,提供供应商配置和用量统计界面。
- **样式**: SCSS Modules禁止使用纯 CSS
- **测试**: Vitest + React Testing Library + Playwright
## API 层
### 字段转换机制
后端使用 `snake_case`,前端使用 `camelCase`API 层自动转换:
```typescript
// 发送请求时camelCase → snake_case
toApi({ providerId: "openai" }) // → { provider_id: "openai" }
// 接收响应时snake_case → camelCase
fromApi({ provider_id: "openai" }) // → { providerId: "openai" }
```
### 统一请求函数
```typescript
export async function request<T>(method: string, path: string, body?: unknown): Promise<T>
```
- 自动处理字段转换
- 自动处理 204 响应(无 body
- 抛出 `ApiError` 包含 `status``code``message`
### 错误处理
```typescript
class ApiError extends Error {
status: number; // HTTP 状态码
code?: string; // 业务错误码
message: string; // 错误消息
}
```
## TanStack Query 模式
### Query Keys 定义
```typescript
// 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 使用
```typescript
const mutation = useMutation({
mutationFn: createProvider,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: providerKeys.all });
},
});
```
## 项目结构
```
@@ -25,7 +87,7 @@ frontend/
│ │ ├── models.ts # Model CRUD
│ │ └── stats.ts # Stats 查询
│ ├── components/
│ │ └── AppLayout/ # 顶部导航布局
│ │ └── AppLayout/ # 侧边栏导航布局
│ ├── hooks/ # TanStack Query hooks
│ │ ├── useProviders.ts
│ │ ├── useModels.ts
@@ -33,6 +95,7 @@ frontend/
│ ├── pages/
│ │ ├── Providers/ # 供应商管理(含内嵌模型管理)
│ │ ├── Stats/ # 用量统计
│ │ ├── Settings/ # 设置(开发中)
│ │ └── NotFound.tsx
│ ├── routes/
│ │ └── index.tsx # 路由配置
@@ -125,11 +188,50 @@ bun run test:e2e
- 按模型筛选
- 按日期范围筛选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 层测试使用 MSWMock 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
- 图标优先使用 @ant-design/icons
- 图标优先使用 TDesign 图标tdesign-icons-react
- TypeScript strict 模式,禁止 any 类型
- API 层自动处理 snake_case ↔ camelCase 字段转换
- 使用路径别名 `@/` 引用 src 目录
@@ -143,4 +245,4 @@ bun run test:e2e
1.`src/pages/` 创建页面目录和组件
2.`src/hooks/` 创建对应的 TanStack Query hook
3.`src/routes/index.tsx` 添加路由
4.`src/components/AppLayout/index.tsx`menuItems 添加导航项
4.`src/components/AppLayout/index.tsx`Menu 中添加 MenuItem