Files
asset_helper/frontend/CLAUDE.md
2026-04-26 15:40:50 +08:00

173 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Frontend — Claude Code 项目指南
本文件为 Claude Code及其它 AI Agent提供前端项目的背景、结构说明和开发规范。
## 项目状态
**技术栈已确定,项目已初始化。**
| 维度 | 选型 |
|------|------|
| 框架 | React 18 + TypeScript 5 |
| 构建 | Vite 6 |
| UI 库 | Ant Design 5 + @ant-design/icons |
| 路由 | React Router 6 |
| 状态管理 | Zustand客户端状态 |
| HTTP 客户端 | AxiosAPI 封装在 `src/api/` |
## 定位
`frontend/` 是 asset_helper 的 **Web 管理后台**,调用后端 API通过 Nginx 网关暴露)。
-`backend/` 通过 HTTP/JSON 交互,遵循根目录 [CLAUDE.md](../CLAUDE.md) 中定义的跨端契约
-`app/`(移动/桌面端)共享后端,但 UI 实现独立
- 当前为后台管理系统,后续可扩展为面向用户的 Web 端
## Docker 部署
前端**不再单独编排**,统一由项目根目录的 docker compose 一并启动。详见 [根目录 CLAUDE.md](../CLAUDE.md#部署)。
| 环境 | 启动命令(在项目根目录执行) | 访问地址 |
|------|------|---------|
| 正式 | `docker compose up -d --build` | `http://localhost:20080` |
| 测试 | `docker compose -f docker-compose.dev.yml up -d --build` | `http://localhost:18888` |
两套环境前端均为多阶段构建Node 构建 → Nginx 静态托管),通过 Nginx 的 `location /api/` 反代到网关容器(服务名 `gateway`,同 Docker 网络内可达)。
## 与后端的协作约定
以下约定来自 [backend/CLAUDE.md](../backend/CLAUDE.md),前端调用时**必须遵守**
### 1. 请求包装(注册/业务类接口)
```ts
interface ApiRequest<T> {
device: number; // 前端固定使用 Device.Web = 3
language: number; // 默认 Language.SimplifiedChinese = 1
data: T; // 业务字段
}
```
**device 编码:**
- `1` = iOS、`2` = Android、`3` = Web ← **前端使用此值**
- `4` = iPad、`5` = macOS、`6` = Windows、`7` = Linux
**language 编码:**
- `1` = 简体中文(默认)、`2` = 繁体中文、`3` = 英文
### 2. 响应包装
```ts
interface ApiResponse<T> {
success: boolean;
message: string;
data: T | null; // 失败时为 null
}
```
### 3. 登录/认证类接口(扁平响应)
```ts
interface LoginResponse {
success: boolean;
token: string | null; // JWT
message: string;
}
```
**JWT 存储策略**:存于 Zustand 内存中(页面刷新丢失,需重新登录)。如需持久化,可改为 localStorage但需注意 XSS 风险。
### 4. 错误响应HTTP 非 200
```ts
interface ErrorResponse {
error: string;
message: string;
code: number;
}
```
## 目录结构
```
frontend/
├── docker/
│ ├── Dockerfile # 多阶段构建Node 构建 + Nginx 静态托管)
│ └── nginx.conf # 生产 Nginx SPA 配置 + /api 反代到网关
├── src/
│ ├── api/
│ │ ├── client.ts # Axios 封装device/language 注入、JWT、错误处理
│ │ └── auth.ts # 认证相关 API
│ ├── components/ # 可复用 UI 组件(待扩展)
│ ├── hooks/ # 自定义 Hooks待扩展
│ ├── layouts/
│ │ └── MainLayout.tsx # 后台主布局(侧边栏 + 头部 + 内容区)
│ ├── pages/
│ │ ├── LoginPage.tsx # 登录页(账号/邮箱切换)
│ │ ├── DashboardPage.tsx # 仪表盘首页
│ │ └── NotFoundPage.tsx # 404
│ ├── router/
│ │ └── index.tsx # 路由配置(登录守卫 + 受保护路由)
│ ├── stores/
│ │ └── auth.ts # Zustand 认证状态token + login/logout
│ ├── types/
│ │ ├── api.ts # 通用 API 类型device/language 枚举、包装类型)
│ │ └── auth.ts # 认证相关类型
│ ├── utils/
│ │ └── storage.ts # localStorage 封装(带前缀隔离)
│ ├── App.tsx # 根组件ConfigProvider + RouterProvider
│ └── main.tsx # 入口
├── index.html
├── package.json
├── tsconfig.json / tsconfig.app.json / tsconfig.node.json
└── vite.config.ts
```
> 编排文件已统一上移到项目根目录的 `docker-compose.yml` / `docker-compose.dev.yml`。
## API 调用规范
**必须使用封装函数,禁止直接 fetch/axios**
```ts
// ✅ 业务接口(自动注入 device/language
import { apiPost, apiGet } from '@/api/client'
const data = await apiPost<RequestType, ResponseType>('/api/v1/users/xxx', payload)
// ✅ 认证接口(扁平格式,不包装)
import { loginAccount } from '@/api/auth'
const result = await loginAccount({ account: 'xxx', password: 'xxx' })
```
## 代码风格
- 注释使用**中文**(与后端保持一致)
- TypeScript 类型与后端 Rust 结构体一一对齐,禁止 `any`
- API 调用集中在 `src/api/`,不在组件中直接写 axios
- 路由守卫在 `src/router/index.tsx` 中统一配置
## 常用命令
| 命令 | 说明 |
|------|------|
| `npm install` | 安装依赖(开发容器内自动执行) |
| `npm run dev` | 启动开发服务器(容器内) |
| `npm run build` | 生产构建 |
| `npm run preview` | 预览生产构建 |
## 开发环境
- 推荐:在项目根目录用 `docker compose -f docker-compose.dev.yml up -d --build` 启动整套测试环境,前端为 Nginx 静态托管,访问 `http://localhost:18888`
- 如需快速调试前端而不构建镜像,本目录下 `npm run dev` 可启动 Vite dev server监听 `0.0.0.0:5173`),需自行确保后端网关在宿主机可达;可通过 `VITE_API_BASE_URL` 覆盖 proxy 目标
## 扩展指南
新增页面/功能时:
1. 先在 `types/` 定义与后端对齐的类型
2.`api/` 添加调用封装(务必通过统一封装注入 `device`/`language`
3.`pages/` 创建页面组件
4.`router/index.tsx` 添加路由
5. 如需加入侧边栏菜单,在 `layouts/MainLayout.tsx``menuItems` 中配置
发现重复逻辑时优先抽到 `utils/` 或自定义 Hook。