9.1 KiB
9.1 KiB
代码规范
分析日期: 2026-05-07
命名规范
文件命名:
- 组件文件:PascalCase +
.tsx扩展名(如DashboardShell.tsx、AddOutfitDialog.tsx) - 工具函数/库文件:kebab-case +
.ts扩展名(如error-handler.ts、client.ts) - 特殊情况:对话框类组件使用 kebab-case(如
add-outfit-dialog.tsx、delete-confirmation-dialog.tsx)
函数命名:
- 使用 camelCase(如
handleLogin、fetchOutfits、mapBackendOutfit) - API 函数:动词 + 名词,camelCase(如
getOutfits、createOutfit、updateOutfit、deleteOutfit) - 事件处理函数:
handle+ 事件名(如handleSubmit、handleChange、handleSendVerificationCode) - 工具函数:动词 + 目标(如
formatDate、toDisplayOutfit)
变量命名:
- 状态变量:camelCase(如
email、password、isLoading、selectedOutfit) - 布尔值:
is或has前缀(如isLoading、isSubmitting、hasPermission) - 常量:UPPER_SNAKE_CASE(如
TOAST_LIMIT、TOAST_REMOVE_DELAY、API_BASE_URL)
类型/接口命名:
- PascalCase(如
EmailLoginResponse、DashboardShellProps、ApiResponse<T>) - Props 接口:
组件名Props后缀(如ButtonProps、DashboardShellProps) - 联合类型:
RoleName、PermissionModule
代码样式
格式化:
- 使用 TypeScript strict 模式(
tsconfig.json中"strict": true) - 目标:ES6(
target: "ES6") - 模块化解析:
bundler模式(用于 Next.js) - 无 ESLint/Prettier 配置文件(
next.config.mjs中eslint.ignoreDuringBuilds: true) - 代码风格通过 TypeScript 编译器和 Next.js 内置检查
缩进和空格:
- 使用 2 空格缩进(根据代码库一致性)
- 函数声明和块语句间使用一致空格
类型注解:
- 所有函数参数必须有类型注解
- 所有变量应有类型注解(特别是导出的接口和公共函数返回值)
- 使用 TypeScript 严格模式防止隐式
any
导入组织
顺序:
- React 和 Next.js 核心库(
import React from "react"、import { useState } from "react") - Next.js 功能(
import { useRouter } from "next/navigation"、import Link from "next/link") - 第三方库(
import axios from "axios"、import Cookies from "js-cookie") - 本项目组件(
import { Button } from "@/components/ui/button") - 本项目库和工具(
import { cn } from "@/lib/utils") - 本项目 hooks(
import { useToast } from "@/components/ui/use-toast") - 类型导入(
import type { ApiResponse } from "./client")
路径别名:
- 项目配置
@/*指向项目根目录 - 组件:
@/components/... - 库函数:
@/lib/... - Hooks:
@/hooks/... - 类型和接口:通过
@/lib/api/types集中导入 - UI 组件:
@/components/ui/...
错误处理
模式:
- 使用
try-catch处理异步操作和 API 调用(见auth.ts、outfits.ts) - 创建自定义错误类
ApiError扩展Error,包含status属性(见error-handler.ts第 46-54 行) - 统一的错误处理函数
handleApiException()将不同类型的错误转换为用户友好的消息(见error-handler.ts第 79-90 行) - 错误信息映射表
errorMessages定义特定错误代码(USER_NOT_FOUND、ROLE_EXISTS等)的消息
API 错误处理:
- 在 Axios 响应拦截器中处理 401 未授权错误:清除 token 并重定向到登录页面(见
client.ts第 54-61 行) - 对 API 失败使用 Radix Toast 组件显示错误提示(见
error-handler.ts第 69-76 行、第 93-100 行) - 统一的
handleApiRequest()包装器函数处理成功/失败情况并自动显示 toast(见error-handler.ts第 102-144 行)
日志:
- 使用
console.log()、console.warn()、console.error()进行调试和错误追踪 - API 请求/响应在拦截器中记录详细日志,包括 token 检查、请求头、响应状态(见
client.ts第 20-66 行) - 使用 emoji 表情增强日志可读性(
🔍 Token检查、✅ Token已添加、❌ 响应错误)
日志记录
框架: console(浏览器原生)
使用规范:
- API 请求/响应日志在 Axios 拦截器中集中管理
- 所有认证流程加日志(token 检查、保存、清除)
- 错误信息带上上下文(URL、状态码、方法)
- 生产环境应考虑减少日志或使用第三方服务(未配置)
注释
何时写注释:
- JSDoc 风格注释用于公共 API 函数(见
auth.ts第 5-7 行、第 24-30 行) - 注释解释"为什么"而不是"是什么"
- 复杂业务逻辑或算法需要行内注释
JSDoc/TSDoc 风格:
/**
* 邮箱登录接口
* @param email 邮箱
* @param password 密码
* @returns 包含token的响应
*/
export const emailLogin = async (email: string, password: string): Promise<EmailLoginResponse> => {
// ...
}
中文注释: 所有注释使用中文(符合 CLAUDE.md 的语言偏好)
函数设计
大小:
- 函数长度通常 20-50 行(见
handleLogin在login/page.tsx第 28-63 行) - 超过 100 行的函数应考虑拆分(如
AddOutfitDialog组件中的多步表单分离为 Tabs)
参数:
- 单个参数优于多个参数
- 对象参数用于选项(如
handleApiRequest()的 options 对象,第 104-110 行) - 类型参数用于泛型函数(如
handleResponse<T>()、ApiResponse<T>)
返回值:
- 异步函数返回
Promise<T> - 布尔查询函数返回
boolean(如hasPermission()、isAuthenticated()) - 数据获取返回具体类型或
null(见getOutfit()返回Promise<Outfit>)
模块设计
导出:
- 公共 API 函数从
lib/api/模块导出(如emailLogin、getOutfits) - 类型从
lib/api/types.ts集中导出 - Utility 函数从
lib/utils.ts导出(如cn()用于样式合并)
Barrel 文件:
lib/api/index.ts作为 barrel 文件,导出所有 API 函数以便统一导入- 组件库采用 Radix UI + shadcn 风格,每个组件文件独立,无 barrel 文件
React 和组件规范
状态管理:
- 使用 React Hooks(
useState、useEffect、useCallback)进行本地状态管理 - 在客户端组件中集中管理表单状态(见
add-outfit-dialog.tsx第 24-36 行)
组件模式:
- 所有表单和交互组件用
"use client"指令标记 - Page 组件(
app/*/page.tsx)使用"use client"支持交互 - 使用 Radix UI 和 shadcn 风格组件库,组件文件在
components/ui/ - Props 接口扩展原生 HTML 属性(如
ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>)
样式:
- 使用 Tailwind CSS 类名
- 使用
cn()工具函数(基于clsx+tailwind-merge)合并条件样式(见button.tsx第 47 行) - 使用
class-variance-authority(CVA) 定义组件变体(见button.tsx第 7-34 行) - 颜色、间距、圆角通过 Tailwind 配置变量(CSS 变量)定义
表单与验证
表单状态:
- 使用
useState管理表单字段状态 - 表单提交通过
handleSubmit()函数处理(见add-outfit-dialog.tsx第 38-56 行)
验证:
- 基本的客户端验证(如检查空值:
if (!formData.name || !formData.description)) - React Hook Form + Zod 在 package.json 中定义但代码中未广泛使用
- 服务器端验证通过 API 响应处理(返回 400/422 等错误状态)
通知:
- 成功/错误提示使用 Sonner toast 或 Radix Toast(通过
useToast()hook) - toast 样式变体:
"default"、"destructive"(见error-handler.ts第 71-75 行)
权限控制
权限检查:
- 运行时权限检查通过
hasPermission(module)函数(见permissions.ts第 85-87 行) - 权限矩阵定义在
PERMISSION_MATRIX对象,映射角色到模块列表 - 路由保护:中间件
middleware.ts检查 cookie 中的 token,无 token 重定向到登录 - 组件级权限检查:
DashboardShell使用hasPathPermission()处理访问拒绝(见dashboard-shell.tsx第 23-24 行)
角色存储:
- 登录后在
localStorage中存储user_role字符串(见auth.ts第 58 行) - 超级管理员标识存储为
is_superuser(见auth.ts第 53 行) - token 同时存储在
localStorage和 Cookie 中(见auth.ts第 49、63 行)
异步操作
模式:
- 使用
async/await处理异步 API 调用 - 加载状态通过
isLoading布尔值跟踪(见login/page.tsx第 19、30 行) - 模拟延迟用于开发和测试(见
client.tssimulateDelay()和mockResponse()函数)
API 集成
Axios 配置:
- 在
lib/api/client.ts创建 Axios 实例,基础 URL 来自环境变量NEXT_PUBLIC_API_BASE_URL - 请求拦截器自动注入 Authorization 头(Bearer token)
- 响应拦截器处理 401 错误并触发重新登录
- API 端点前缀:
/api/v1/admin/
适配器模式:
- 后端返回数据结构与前端显示结构不同
- 使用
mapBackendOutfit()等适配器函数转换数据(见outfits.ts第 5-22 行) - 适配器在
lib/api/adapters.ts中集中管理
规范分析日期:2026-05-07