阅读时间 8 分钟最后更新: 2025-12-31 12:12

工程化编码规范与协作指南

本文档旨在统一项目的代码风格、架构设计与协作流程,确保代码库的可维护性、扩展性与一致性。所有贡献者在提交代码前,请务必仔细阅读并遵守本指南。

核心架构设计原则

分层架构

本项目采用清晰的分层架构,严格分离关注点:

  • API Layer (src/app/api): 处理 HTTP 请求,进行参数校验和权限检查,然后调用 Service Layer。不应包含核心业务逻辑。
  • Service Layer (src/lib/services): 核心业务逻辑的栖息地。负责处理具体的业务规则、数据组装、调用 ORM 和其他服务。
    • client/: 面向终端用户的服务(如 subscription-service.ts, credits-service.ts
    • admin/: 面向管理员的服务(如 admin-service.ts
    • settings/: 系统配置相关服务
  • Data Access Layer (src/lib/database.ts, Drizzle ORM): 负责与数据库交互
  • Lib/Utils (src/lib): 通用工具函数、常量定义、第三方库封装(如 src/lib/payment, src/lib/email

依赖注入与单例模式

  • 对于复杂的外部依赖(如支付网关、存储服务),应使用工厂模式策略模式进行封装,对外提供统一接口
    • 例如:src/lib/payment/gateway-factory.ts 根据配置动态返回 StripeGatewayCreemGateway 实例
  • Service 类通常导出单例实例,方便直接调用,同时保持状态(如果需要)的一致性
    • 例如:export const subscriptionService = new SubscriptionService();

数据库适配

  • 多数据库支持: 项目同时支持 SQL (PostgreSQL) 和 SQLite
  • Schema 定义: 必须同时维护 src/drizzle-postgres-schema.tssrc/drizzle-sqlite-schema.ts,确保两者字段结构一致(类型定义可能略有差异)
  • ORM 使用: 使用 Drizzle ORM 进行数据库操作,尽量使用类型安全的构建器语法,避免手写 SQL 字符串,以确保跨数据库兼容性

编码规范

TypeScript 规范

  • 严格类型: 启用 strict: true。禁止使用 any,必须定义明确的接口(Interface)或类型(Type)
  • 类型定义位置:
    • 组件 props 定义在组件文件内部
    • 公共数据模型定义在 types.ts 或相关模块的 types 文件中(如 src/lib/payment/types.ts
  • 非空断言: 尽量避免使用 ! 非空断言,优先使用可选链 ?. 和空值合并 ??,或进行显式的空值检查

组件开发规范 (React/Next.js)

  • 组件结构:
    • 优先使用函数式组件 + Hooks
    • Server Components vs Client Components: 默认使用 Server Components。只有在需要交互(onClick, useState, useEffect)时才添加 'use client' 指令
    • 文件命名: 组件文件使用 PascalCase.tsx(如 Button.tsx),页面文件使用 page.tsx
  • Props 命名:
    • 使用 interface 定义 Props,命名遵循 PascalCase + Props 后缀(如 SubscriptionManagerProps
    • 事件处理函数 Props 命名以 on 开头(如 onSave, onClick
  • Hooks: 自定义 Hooks 应放在 src/lib/hooks 目录下,命名以 use 开头
  • 国际化: 所有 UI 文本必须使用 i18next 进行国际化
    • Server Component: 使用 src/i18n 中的 useTranslation (async)
    • Client Component: 使用 src/i18n/client 中的 useTranslation
    • 文本 Key 命名: namespace:category.key (如 home:hero.title)

前端开发规范

样式与 UI 规范

本项目采用 Tailwind CSS 4 + Shadcn/ui 作为核心 UI 方案。

颜色语义化(强制)

严禁使用固定颜色值。必须使用设计系统中定义的语义化 CSS 变量,以确保主题切换功能正常。

  • 背景: bg-[var(--color-bg-main)], bg-[var(--color-bg-surface)], bg-[var(--color-bg-subtle)]
  • 文本: text-[var(--color-text-primary)], text-[var(--color-text-secondary)], text-[var(--color-text-tertiary)]
  • 边框: border-[var(--color-border-subtle)], border-[var(--color-border-strong)]
  • 品牌: bg-brand-500, text-brand-500
  • 功能: text-[var(--color-text-error)], bg-[var(--color-bg-success)]

样式编写原则

  • 原子化优先: 禁止编写传统的 CSS/SCSS 文件。所有样式应尽可能通过 Tailwind utility classes 实现
  • 响应式设计: 遵循 Mobile First 原则。默认编写移动端样式,使用 sm:, md:, lg: 前缀覆盖大屏样式
  • 类名合并: 使用 src/lib/utils.ts 中的 cn 函数处理条件类名
    • className={cn("p-4 rounded", isActive && "bg-brand-500", className)}

常用前端工具类 (Utils)

本项目在 src/lib/utils.tssrc/lib/hooks 中封装了大量实用工具,开发时请优先使用,避免重复造轮子。

  • 样式合并: cn(...inputs: ClassValue[]) - 合并 Tailwind 类名,解决冲突
  • 日期格式化: useDateFormat Hook - 处理时区和本地化日期显示
    • formatDate(date, formatStr?): 格式化日期
    • formatTime(date): 格式化时间
    • formatDateTime(date): 格式化日期时间
  • 价格格式化: formatPrice(amount, currency) - 根据币种格式化价格显示
  • 网络请求: src/lib/fetch.ts - 封装了带有语言参数和错误处理的 fetch 方法
    • fetchGet(url, options)
    • fetchPost(url, body, options)
  • 认证状态: useAuthContext - 获取当前用户信息 (user) 和加载状态 (isPending)

新页面开发清单

创建一个新页面时,必须包含以下要素:

  1. 文件位置:
    • 路由页面放在 src/app/[lang]/.../page.tsx
    • 需要权限控制的页面(如后台)应放在 (auth)admin 路由组下
  2. 国际化 (i18n):
    • 页面组件必须接收 params: { lang: string }
    • 服务端获取翻译:const { t } = await useTranslation(lang, 'namespace')
    • 客户端组件通过 props 接收 lang 或使用 useTranslation hook
  3. 布局与容器:
    • 使用语义化标签 (main, section, article)
    • 页面内容通常包裹在 Layoutdiv 容器中,使用标准内边距
  4. 错误边界:
    • 复杂页面建议添加 error.tsx 处理运行时错误
    • 未找到资源时使用 notFound() 函数
  5. 加载状态:
    • 对于异步数据加载,应显示 loading.tsx 或骨架屏 (Skeleton)

示例页面结构:

import { useTranslation } from '@/i18n'

export default async function Page({ params: { lang } }) {
  const { t } = await useTranslation(lang, 'home')
  
  return (
    <main className="bg-[var(--color-bg-main)] min-h-screen">
      <div className="container mx-auto px-4 py-8">
        <h1 className="text-[var(--color-text-primary)] text-2xl font-bold">
          {t('title')}
        </h1>
        {/* Page Content */}
      </div>
    </main>
  )
}

核心业务模块开发指南

认证 (Authentication)

  • Better Auth: 所有的认证逻辑基于 src/lib/auth.ts
  • Hooks:
    • before: 用于登录前检查(如验证码、登录锁定、注册限制)
    • after: 用于登录后处理(如记录日志、发送欢迎邮件)
  • Session: 前端使用 useAuthContext 获取当前用户信息

支付与订阅 (Payment & Subscription)

  • 流程: 创建 Checkout Session -> 用户支付 -> Webhook 回调 -> 更新数据库状态
  • Webhook: 所有状态变更必须依赖 Webhook 通知的处理结果,而不是前端回调
  • 积分逻辑:
    • creditsService.addCredits: 增加积分,需区分 Free (赠送) 和 Paid (购买)
    • creditsService.consumeCredits: 消费积分,优先扣除 Free Credits
  • 幂等性: Webhook 处理逻辑必须是幂等的,即多次接收同一事件不应导致数据错误(如重复发分)

管理后台 (Admin)

  • 接口权限控制: 管理端 API 接口必须严格检查管理员权限。在 API Route 中应使用 checkPermissionWithResponse(request, Permission) 进行校验;在 Server Action 中应验证 session 及其权限
  • 页面访问控制: 管理后台的所有页面组件必须进行权限校验。使用 PermissionGuard 组件包裹受限内容,确保无权用户无法看到特定功能或页面
  • 日志记录: 所有敏感操作(如数据的增、删、改)必须记录日志。调用 adminOperationLogs 服务或 logSimpleOperation,记录操作人、模块、行为及目标 ID

性能、安全与部署

性能优化

  • 图片优化: 必须使用 next/image 组件,并正确配置 sizes 属性以实现响应式加载
  • 组件懒加载: 对于非首屏关键组件(如模态框、大型图表),使用 next/dynamic 进行懒加载
  • 服务端组件: 默认使用 Server Components 减少客户端 Bundle 体积
  • 字体优化: 使用 next/font 加载字体,避免布局偏移 (CLS)

安全规范

  • 输入验证: 所有 API 接口必须使用 Zod 进行参数校验,确保输入数据的合法性与安全性
  • 身份验证 (Authentication): 客户端 API 接口在处理涉及用户隐私或个性化数据的请求时,必须首先调用 verifyUserInApiRoute(request) 验证用户的 Session 状态
  • CSRF 防护: 所有的 POST/PUT/DELETE 请求必须通过 Next.js 的 Server Actions 或 API Routes 自动处理 CSRF
  • 敏感数据: 禁止在客户端代码中暴露 API Keys、Secrets 或数据库连接字符串。环境变量需区分 NEXT_PUBLIC_ 前缀
  • 权限校验 (Authorization): 任何涉及数据修改的接口,必须在服务端再次校验当前用户是否具有执行该操作的具体权限

部署流程

  • Vercel 部署: 推荐使用 Vercel 进行部署,利用其 Edge Network 和 Serverless Functions
  • 环境变量: 生产环境部署前,务必在 Vercel Dashboard 配置好所有必要的环境变量
  • 数据库迁移: 部署流程中应包含 drizzle-kit migrate 步骤,确保数据库结构是最新的

提交与协作规范

Git 提交信息

遵循 Conventional Commits 规范:

  • feat: 新功能
  • fix: 修复 bug
  • docs: 文档变更
  • style: 代码格式调整(不影响逻辑)
  • refactor: 代码重构(无新功能或 bug 修复)
  • chore: 构建过程或辅助工具的变动

示例: feat(auth): add google login support

分支管理

  • main: 主分支,保持稳定,随时可部署
  • develop: 开发分支,日常开发合并至此
  • feature/*: 功能分支,从 develop 检出,完成后提 PR 合并回 develop
  • fix/*: 修复分支

代码审查 (Code Review)

  • 提交 PR 前请先自测,并确保通过 lint 检查
  • PR 描述应清晰说明变更内容、目的及测试方法
  • 核心逻辑变更(特别是涉及支付、权限部分)必须经过严格审查

常用命令速查

命令说明
pnpm dev启动开发服务器
pnpm build构建项目
pnpm drizzle-kit generate数据库迁移生成
pnpm drizzle-kit push数据库迁移推送
pnpm prettier --write .代码格式化