1
0
Files
nex/frontend/README.md
lanyuanxiaoyao 8eea30ea11 feat: 统一品牌标识、关于页面三卡片布局与版本诊断功能
- 统一品牌为 Nex:侧边栏、托盘 tooltip、HTML 标题、favicon (PNG 替代 SVG)
- 重构关于页面为三卡片布局(品牌/版本/链接),版本状态 Tag 绝对定位右上角
- 新增 GET /api/version 后端接口,返回 version/commit/build_time
- 新增前端版本一致性诊断:匹配/不匹配/不可判断三种状态
- 同步 delta specs 到主 specs 并归档变更
2026-05-05 03:28:22 +08:00

7.6 KiB
Raw Blame History

Nex Frontend

AI 网关管理前端,提供供应商配置和用量统计界面。

技术栈

  • 运行时: Bun
  • 构建工具: Vite
  • 语言: TypeScript (strict mode)
  • 框架: React
  • UI 组件库: TDesign
  • 路由: React Router v7
  • 数据获取: TanStack Query v5
  • 样式: TDesign 组件 props 优先TDesign tokens 次之SCSS 作为兜底补充
  • 测试: Vitest + React Testing Library + Playwright
  • 代码格式化: Prettier

API 层

字段转换机制

后端使用 snake_case,前端使用 camelCaseAPI 层自动转换:

// 发送请求时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 包含 statuscodemessage

错误处理

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 查询
│   │   └── version.ts          # 后端版本查询
│   ├── components/
│   │   └── AppLayout/          # 侧边栏导航布局
│   ├── hooks/                  # TanStack Query hooks
│   │   ├── useProviders.ts
│   │   ├── useModels.ts
│   │   ├── useStats.ts
│   │   └── useVersion.ts
│   ├── pages/
│   │   ├── Providers/          # 供应商管理(含内嵌模型管理)
│   │   ├── Stats/              # 用量统计
│   │   ├── Settings/           # 设置(开发中)
│   │   ├── About/              # 关于页面(品牌与版本信息)
│   │   └── NotFound.tsx
│   ├── routes/
│   │   └── index.tsx           # 路由配置
│   ├── types/
│   │   └── index.ts            # 类型定义
│   ├── __tests__/              # 测试
│   │   ├── setup.ts
│   │   ├── api/
│   │   ├── hooks/
│   │   └── components/
│   ├── App.tsx
│   ├── main.tsx
│   └── index.scss
├── e2e/                        # Playwright E2E 测试
├── public/                     # 静态资源icon.png 来源于 ../assets/icon.png
├── 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          # ESLint 检查
bun run format:check  # Prettier 格式检查
bun run check         # 同时检查 lint 和格式

代码格式化

bun run format        # 格式化所有文件
bun run fix           # 修复 lint 问题并格式化

VS Code 保存时自动格式化(需安装 Prettier 扩展)。

测试

单元测试 + 组件测试

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

关于页面

  • 展示应用名称、产品描述和项目链接
  • 展示前端版本、后端版本、后端 commit 和构建时间
  • 根据 VITE_APP_VERSIONGET /api/version 返回值提示前后端版本是否一致

测试策略

目录结构

__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
VITE_APP_VERSION 0.1.0 0.1.0 前端构建版本,由 make version-sync 同步

E2E 测试特有

  • NEX_BACKEND_PORT - E2E 后端端口(默认 19026
  • NEX_E2E_TEMP_DIR - E2E 临时目录

开发规范

  • 样式优先使用 TDesign 组件 propshoverShadowheaderBorderedvariantshapegutter
  • 组件 props 无法表达时使用 TDesign tokensvar(--td-*)
  • 仅当 props 和 tokens 无法满足布局、响应式或品牌视觉需求时使用 SCSS禁止使用纯 CSS 文件
  • 图标优先使用 TDesign 图标tdesign-icons-react
  • 应用 favicon 使用 frontend/public/icon.png,该文件来源于仓库根目录 assets/icon.png
  • TypeScript strict 模式,禁止 any 类型
  • API 层自动处理 snake_case ↔ camelCase 字段转换
  • 使用路径别名 @/ 引用 src 目录
  • 代码格式化使用 Prettier配置见 .prettierrc
  • 编辑器配置见 .editorconfig(统一缩进、换行符、编码)

环境要求

  • Bun 1.0 或更高版本
  • VS Code 推荐安装 Prettier 和 ESLint 扩展(见 .vscode/extensions.json

添加新页面

  1. src/pages/ 创建页面目录和组件
  2. src/hooks/ 创建对应的 TanStack Query hook
  3. src/routes/index.tsx 添加路由
  4. src/components/AppLayout/index.tsx 的 Menu 中添加 MenuItem