⚠️ Alpha内测版本警告:此为早期内部构建版本,尚不完整且可能存在错误,欢迎大家提Issue反馈问题或建议
Skip to content

9.4.5 错误要记录在案——文档同步:错误码文档与处理指南

错误码文档是前后端协作的"合同"——改了代码必须更新文档。

错误码设计规范

错误码定义

typescript
// lib/error-codes.ts
export const ErrorCodes = {
  // 认证错误 (1xxx)
  AUTH_INVALID_CREDENTIALS: {
    code: 'AUTH_1001',
    message: '邮箱或密码错误',
    httpStatus: 401,
  },
  AUTH_TOKEN_EXPIRED: {
    code: 'AUTH_1002',
    message: '登录已过期,请重新登录',
    httpStatus: 401,
  },
  AUTH_INSUFFICIENT_PERMISSION: {
    code: 'AUTH_1003',
    message: '没有权限执行此操作',
    httpStatus: 403,
  },
  
  // 订单错误 (2xxx)
  ORDER_NOT_FOUND: {
    code: 'ORDER_2001',
    message: '订单不存在',
    httpStatus: 404,
  },
  ORDER_ALREADY_PAID: {
    code: 'ORDER_2002',
    message: '订单已支付',
    httpStatus: 409,
  },
  ORDER_STOCK_INSUFFICIENT: {
    code: 'ORDER_2003',
    message: '库存不足',
    httpStatus: 400,
  },
  
  // 支付错误 (3xxx)
  PAYMENT_FAILED: {
    code: 'PAYMENT_3001',
    message: '支付失败,请重试',
    httpStatus: 400,
  },
  PAYMENT_TIMEOUT: {
    code: 'PAYMENT_3002',
    message: '支付超时',
    httpStatus: 408,
  },
  
  // 系统错误 (9xxx)
  SYSTEM_ERROR: {
    code: 'SYSTEM_9001',
    message: '服务暂时不可用,请稍后重试',
    httpStatus: 500,
  },
  SYSTEM_MAINTENANCE: {
    code: 'SYSTEM_9002',
    message: '系统维护中,请稍后访问',
    httpStatus: 503,
  },
} as const;

export type ErrorCode = keyof typeof ErrorCodes;

使用错误码

typescript
// lib/errors.ts
import { ErrorCodes, ErrorCode } from './error-codes';

export class AppError extends Error {
  public code: string;
  public httpStatus: number;
  
  constructor(errorCode: ErrorCode, customMessage?: string) {
    const errorDef = ErrorCodes[errorCode];
    super(customMessage || errorDef.message);
    
    this.code = errorDef.code;
    this.httpStatus = errorDef.httpStatus;
  }
}

// 使用
throw new AppError('ORDER_STOCK_INSUFFICIENT');
throw new AppError('ORDER_NOT_FOUND', `订单 ${orderId} 不存在`);

自动生成文档

typescript
// scripts/generate-error-docs.ts
import { ErrorCodes } from '../lib/error-codes';
import * as fs from 'fs';

function generateErrorDocs() {
  const grouped = groupByModule(ErrorCodes);
  
  let markdown = '# API 错误码文档\n\n';
  markdown += `> 更新时间: ${new Date().toISOString()}\n\n`;
  
  for (const [module, errors] of Object.entries(grouped)) {
    markdown += `## ${module}\n\n`;
    markdown += '| 错误码 | HTTP 状态 | 描述 | 处理建议 |\n';
    markdown += '|--------|----------|------|----------|\n';
    
    for (const [key, error] of Object.entries(errors)) {
      markdown += `| ${error.code} | ${error.httpStatus} | ${error.message} | ${getHandlingTip(key)} |\n`;
    }
    
    markdown += '\n';
  }
  
  fs.writeFileSync('docs/api/error-codes.md', markdown);
  console.log('错误码文档已生成');
}

function groupByModule(codes: typeof ErrorCodes) {
  const groups: Record<string, typeof ErrorCodes> = {};
  
  for (const [key, value] of Object.entries(codes)) {
    const module = key.split('_')[0];
    if (!groups[module]) groups[module] = {};
    groups[module][key] = value;
  }
  
  return groups;
}

function getHandlingTip(key: string): string {
  const tips: Record<string, string> = {
    AUTH_INVALID_CREDENTIALS: '检查邮箱和密码是否正确',
    AUTH_TOKEN_EXPIRED: '重新登录获取新 Token',
    ORDER_STOCK_INSUFFICIENT: '减少购买数量或选择其他商品',
    PAYMENT_FAILED: '检查支付信息或更换支付方式',
    SYSTEM_ERROR: '稍后重试,如持续出现请联系客服',
  };
  
  return tips[key] || '请联系客服';
}

generateErrorDocs();

CI 检查文档同步

yaml
# .github/workflows/check-error-docs.yml
name: Check Error Docs

on:
  pull_request:
    paths:
      - 'lib/error-codes.ts'

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: '20'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Generate docs
        run: npx ts-node scripts/generate-error-docs.ts
      
      - name: Check for changes
        run: |
          if git diff --exit-code docs/api/error-codes.md; then
            echo "✅ 错误码文档已同步"
          else
            echo "❌ 错误码已更改,请更新文档"
            echo "运行: npm run generate:error-docs"
            exit 1
          fi

错误码文档模板

markdown
# API 错误码文档

## 认证模块 (AUTH)

| 错误码 | HTTP 状态 | 描述 | 处理建议 |
|--------|----------|------|----------|
| AUTH_1001 | 401 | 邮箱或密码错误 | 检查邮箱和密码 |
| AUTH_1002 | 401 | 登录已过期 | 重新登录 |
| AUTH_1003 | 403 | 没有权限 | 联系管理员 |

## 订单模块 (ORDER)

| 错误码 | HTTP 状态 | 描述 | 处理建议 |
|--------|----------|------|----------|
| ORDER_2001 | 404 | 订单不存在 | 检查订单号 |
| ORDER_2002 | 409 | 订单已支付 | 无需重复支付 |
| ORDER_2003 | 400 | 库存不足 | 减少数量 |

## 前端处理示例

\`\`\`typescript
try {
  await api.createOrder(data);
} catch (err) {
  if (err.code === 'ORDER_2003') {
    showStockWarning(err.message);
  } else {
    showError(err.message);
  }
}
\`\`\`

版本管理

typescript
// lib/error-codes.ts
export const ERROR_CODES_VERSION = '1.2.0';

// 更新日志
export const CHANGELOG = {
  '1.2.0': ['新增 PAYMENT_TIMEOUT 错误码'],
  '1.1.0': ['新增 ORDER_STOCK_INSUFFICIENT 错误码'],
  '1.0.0': ['初始版本'],
};

本节小结

错误码文档是前后端协作的基础。通过代码定义错误码(单一数据源),自动生成文档(保持同步),CI 检查(强制更新)。改错误码的同时必须更新文档,这是团队协作的基本纪律。