Files
juip-web/.github/copilot-instructions.md
2026-08-13 18:28:20 +08:00

5.8 KiB
Raw Blame History

juip-web - AI 开发助手指南

项目概述

Vite + React 19 纯 SPA 代理服务站点,包含公开营销页与用户管理后台。使用 Bun 运行时、react-router-dom 7 路由、Tailwind CSS 4、shadcn/ui (radix-nova 风格)、sonner 提示、biome 代码规范。

核心业务: IP 代理产品展示与购买、订单支付、短信验证码注册登录、后台资源/通道/白名单管理

架构模式

三层数据流架构

  1. API 层 (src/api/*.ts) - 所有后端调用统一入口

    • 每个文件对应一个业务域 (auth, order, product, verify, captcha)
    • 通过 base.ts 的三种调用模式访问后端:
      • callPublic() - 无需认证的公开接口
      • callByDevice() - 使用 CLIENT_ID/CLIENT_SECRET 的设备级认证
      • callByUser() - 使用用户会话 token 的用户级认证
    • 所有调用返回统一的 ApiResponse<T> 类型
    • 后端存在两套响应约定,base.ts 自动识别:
      • 裸 JSON (OAuth2 接口、/script/linedata/*.php 等) - 原样返回
      • 会员接口信封 {Code, Message, Data} - 顶层有 Code 字段时自动解包: Code === 10000 成功返回 Data/data,否则转 success: false + Message
  2. 会话状态 (src/api/token.ts) - 令牌存取唯一入口

    • 登录后 token/userInfo 由后端 Set-Cookie 下发,经 apiLogin 镜像到 localStorage
    • setSession() / clearSession() 统一派发 auth-change 事件驱动 UI 重渲染
    • UI 组件 (header/authGuard) 通过 isAuthed() 读取登录态,禁止直接读 localStorage
    • 401 时 user 模式自动 clearSession()device 模式自动清缓存重取设备令牌
  3. UI 层 - 业务域 API 函数供组件直接调用

    • 公开页组件位于 src/home/*,后台位于 src/admin/*
    • /admin 路由由 AuthGuard 保护,未登录重定向 /login?redirect=

API 层使用示例

// 业务域文件: src/api/xxx.ts
import type { ApiResponse } from "@/lib/api"
import { callByUser, callPublic } from "./base"

// 1. 公开接口 (GET 自动并发去重)
const resp = await callPublic<{ token: string; base64: string }>(
  "/api/captcha/get",
  undefined,
  "GET",
)

// 2. 设备级认证 (client_credentials 令牌模块内单飞缓存,提前 60s 过期)
const resp2 = await callByDevice<{ access_token: string }>(
  "/api/auth/token",
  { grant_type: "client_credentials" },
)

// 3. 用户级认证 (读取会话 token401 自动清会话)
const resp3 = await callByUser<CreateOrderData>("/product/CreateOrder", data)
const resp4 = await callByUser<number>(
  `/product/IsPay?orderNo=${orderNo}`,
  undefined,
  "GET",
)

// 4. Code 信封接口 (顶层有 Code 字段自动解包Code === 10000 成功)
const resp5 = await callPublic("/user/ApiLogin", {
  Logincode: "xxx",
  Password: "xxx",
})
const resp6 = await callPublic<ProductItem[]>(
  "/product/ApiProductActive",
  undefined,
  "GET",
)

// 5. 统一响应处理
if (resp.success) {
  console.log(resp.data) // 强类型 T
} else {
  console.error(resp.status, resp.message)
}

组件调用示例

import { fetchProducts } from "@/api/product"
import { toast } from "sonner"

const result = await fetchProducts()
if (result.success) {
  setProducts(result.data)
} else {
  toast.error(result.message)
}

路由组织

  • / - 公开站点 (LayoutPage 统一头部/底部): 首页、/product(+/buy//http//routeros)、/ipline/softdownload/help/client
  • /login - 登录/注册 (tab 状态经 location.state.tab 切换)
  • /admin - 用户后台 (AuthGuard 保护): dashboard、channels、whitelist、funds、product/long、product/short

路由定义集中在 src/routers/index.tsx

开发工作流

命令速查

bun install               # 安装依赖
bun dev                   # 开发服务器 (vite --host)
bun run build             # 生产构建 (tsc -b && vite build)
bun run lint              # biome 检查并自动修复

代码规范 (biome)

  • 无分号、双引号、2 空格缩进、单参数箭头函数省略括号
  • import 自动排序 (organizeImports)
  • noNonNullAssertion 为 error禁用 ! 断言
  • 提交前运行 bun run lint

组件开发模式

shadcn/ui 组件 (src/components/ui/*.tsx)

  • 通过 CLI 添加: bunx shadcn@latest add <component>
  • 类名合并使用 cn() (来自 @/lib/utils)

业务组件

  • src/components/composites/* - 复杂对话框等
  • src/components/* - 通用组件 (wrap 布局容器、authGuard 路由守卫、data-table、page)

表单: react-hook-form + zod 校验

提示: 统一使用 sonner (toast.success / toast.error)

项目特定约定

类型定义

  • 后端响应统一为 ApiResponse<T> (定义于 src/lib/api.ts):
    • 成功: {success: true, data: T}
    • 失败: {success: false, status?: number, message: string}
  • 请求/响应业务类型定义在对应业务域 API 文件中 (如 src/api/order.tsCreateOrderRequest)
  • UI 展示模型位于 src/lib/models/*

环境变量 (见 .env)

  • VITE_API_BASE_URL - 后端地址 (留空表示同源,登录 Cookie 自动携带)
  • VITE_CLIENT_ID / VITE_CLIENT_SECRET - OAuth2 设备认证凭据 (当前均为 web)

关键文件参考