Files
web/.github/copilot-instructions.md
2026-04-14 11:34:28 +08:00

140 lines
5.3 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.
# 蓝狐代理 (Lanhu Proxy) - AI 开发助手指南
## 项目概述
Next.js 15+ 代理服务平台,包含公开营销站点与用户管理后台。使用 Bun 运行时React 19 Server Componentsshadcn/ui 组件库。
**核心业务**: IP 代理购买、提取、白名单管理、实名认证、充值计费
## 架构模式
### 三层数据流架构
1. **Server Actions** (`src/actions/*.ts`) - 所有 API 调用统一入口
- 每个文件对应一个业务域 (auth, bill, ip, resource 等)
- 通过 `base.ts` 的三种调用模式访问后端:
- `callPublic()` - 无需认证的公开接口
- `callByDevice()` - 使用 CLIENT_ID/CLIENT_SECRET 的设备级认证
- `callByUser()` - 使用用户会话 token 的用户级认证
- 所有调用都用 `cache()` 包装以支持 React 缓存
- 返回统一的 `ApiResponse<T>` 类型
2. **Zustand Store** (`src/components/stores/*.tsx`) - 客户端状态管理
- 异步初始化模式: 通过 Promise 传递服务端数据到客户端
- `ProfileStoreProvider` 在根布局初始化用户资料
- 每个 store 导出: `createXxxStore()`, `XxxStoreProvider`, `useXxxStore()`
- 示例: `profile.tsx` 使用 `profile: Promise<User | null>` 实现服务端到客户端水合
3. **认证流程** - Token 刷新在 middleware 自动处理
- `src/proxy.ts` (middleware) 检测 `auth_token` 过期时自动调用 `refreshAuth()`
- 访问 `/admin` 路径无 token 时重定向到 `/login?redirect=`
- Cookies: `auth_token` (访问令牌), `auth_refresh` (刷新令牌)
### 路由组织
- **(home)** - 公开营销站点,包含产品介绍、文档中心、定制服务
- **(auth)** - 登录、实名认证、隐私协议、兑换码
- **admin** - 用户后台,包含仪表盘、账单、资源管理、白名单、提取功能
- **(api)/proxies** - API 端点路由
括号路由 `(group)` 不影响 URL 路径,仅用于组织布局层级。
### 验证码集成 (Cap.js)
- `src/lib/cap/index.ts` 自定义存储实现,使用 HMAC 签名的 Cookie 而非文件系统
- `getCap()` 返回配置好的 Cap 实例
- Challenge 和 token 都存储在 httpOnly cookies 中
- `sign()` / `verify()` 基于 CLIENT_SECRET 的签名验证
## 开发工作流
### 命令速查
```bash
bun install # 安装依赖
bun dev # 开发服务器 (0.0.0.0:3000 + Turbopack)
bun run build # 生产构建 (Turbopack)
bun start # 启动生产服务器
bun run lint # ESLint 自动修复
bun run check # TypeScript 类型检查
```
### 组件开发模式
**shadcn/ui 组件** (`src/components/ui/*.tsx`)
- 使用 `components.json` 配置New York 风格
- 通过 CLI 添加: `bunx shadcn@latest add <component>`
- 所有组件使用 `merge()` (twMerge 别名) 合并类名
**业务组件** (`src/components/composites/*`)
- 复杂表单、对话框、支付组件等放在此目录
- 标记 `'use client'` 的客户端组件
- 示例: `purchase/index.tsx` 使用 URL 查询参数控制 Tab 状态
**工具函数**
- `merge(...inputs)` - 合并 Tailwind 类名 (来自 `@/lib/utils`)
- `Children` 类型 - 标准 `{children: ReactNode}` 类型别名
### MDX 文档系统
- 文档源文件: `src/docs/*.mdx`
- 配置: `next.config.ts` 集成 `@next/mdx`, `remark-gfm`, `rehype-highlight`
- 页面扩展名: `.md`, `.mdx`, `.js`, `.jsx`, `.ts`, `.tsx`
- 布局: `src/app/(home)/docs/layout.tsx` 提供面包屑和侧边栏
## 项目特定约定
### 类型定义模式
```typescript
// 从 server action 推断请求/响应类型
type ExtraReq<T> = T extends (...args: infer P) => unknown ? P[0] : never
type ExtraResp<T> = Awaited<ReturnType<T>> extends ApiResponse<infer D> ? D : never
// 使用示例
type LoginRequest = ExtraReq<typeof login>
type UserProfile = ExtraResp<typeof getProfile>
```
### 错误处理
- Server actions 返回 `ApiResponse<T>`:
- 成功: `{success: true, data: T}`
- 失败: `{success: false, status: number, message: string}`
- 使用 `sonner` (Toaster) 显示用户提示
- 预定义错误: `UnauthorizedError` (401 场景)
### 样式规范
- 主色系: `primary-*`, `card`, `primary-muted`
- 响应式断点: 使用 Tailwind 默认 (`sm:`, `md:`, `lg:`)
- 布局: 首页使用 `bg-blue-50` 背景,后台使用 `bg-card` 和圆角遮罩 (见 `admin/layout.tsx`)
## 关键文件参考
- [src/actions/base.ts](src/actions/base.ts) - API 调用核心抽象
- [src/proxy.ts](src/proxy.ts) - 认证 middleware 和 token 刷新逻辑
- [src/components/stores/profile.tsx](src/components/stores/profile.tsx) - 异步 store 初始化模式
- [src/lib/cap/index.ts](src/lib/cap/index.ts) - Cap.js 自定义存储实现
- [src/app/layout.tsx](src/app/layout.tsx) - Store providers 和异步初始化
- [next.config.ts](next.config.ts) - MDX、React Compiler、Turbopack 配置
## 环境变量
需要配置:
- `API_BASE_URL` - 后端 API 地址
- `CLIENT_ID`, `CLIENT_SECRET` - OAuth2 设备认证凭据
## 部署
- 使用 `output: 'standalone'` 模式
- Dockerfile 多阶段构建 (Bun 1.2.19 Alpine)
- 生产端口: 3000
## 待改进事项 (来自 README)
- 考虑使用 SWR/React Query 替代当前的 server cache + zustand 混合方案
- 手机端优化: 购买和提取页面需一页展示全部内容
- IP 管理按长短效分页
- 后台导航结构重组 (当前过于分散)