开发规范
接口与路由
- API 前缀:
/api/v1 - Swagger:
/api-docs
项目结构
youlai-nest/
├── src/
│ ├── main.ts # 应用入口
│ ├── app.module.ts # 根模块
│ ├── auth/ # 认证与会话
│ ├── system/ # 系统管理
│ ├── platform/ # 平台能力
│ ├── common/ # 通用能力
│ ├── shared/ # 共享基础设施
│ └── config/ # 配置模块
├── sql/ # 数据库脚本
├── .env # 基础配置
├── .env.dev # 开发环境配置
├── .env.prod # 生产环境配置
└── package.json # 项目配置目录约定
| 目录 | 说明 |
|---|---|
src/auth | 认证与会话(登录/Token/验证码) |
src/system | 系统管理(用户/角色/菜单/部门/字典) |
src/platform | 平台能力(文件/代码生成/WebSocket) |
src/common | 通用能力(异常/拦截器/守卫/上下文) |
src/shared | 共享基础设施(Redis/Logger) |
src/config | 配置模块(TypeORM/Redis/OSS/JWT) |
开发规范
架构分层
- Controller:接收请求,调用 Service,返回响应
- Service:业务逻辑处理
- Repository:数据库操作(TypeORM)
重要:Controller 禁止直接注入 Repository,必须通过 Service 操作数据库。
路由顺序
静态路由在前,动态路由在后,避免 :id 抢占:
typescript
@Controller('users')
export class UserController {
@Put('read-all') // 静态路由在前
readAll() {}
@Put(':id') // 动态路由在后
update() {}
}新模块创建
建议沿用项目结构:
- 系统模块:
src/system/<module> - 平台模块:
src/platform/<module>
命名规范
文件命名
- 小驼峰:
user.controller.ts,user.service.ts - 类名大驼峰:
UserController,UserService
接口命名
typescript
// RESTful 风格
@Controller('users')
export class UserController {
@Get() // GET /api/v1/users
findAll() {}
@Get(':id') // GET /api/v1/users/:id
findOne() {}
@Post() // POST /api/v1/users
create() {}
@Put(':id') // PUT /api/v1/users/:id
update() {}
@Delete(':id') // DELETE /api/v1/users/:id
remove() {}
}参数校验
使用 DTO + class-validator:
typescript
import { IsString, IsInt, Min, Max, IsOptional } from 'class-validator';
export class CreateUserDto {
@IsString()
@MaxLength(50)
username: string;
@IsString()
@MinLength(6)
@MaxLength(20)
password: string;
@IsInt()
@IsOptional()
@Min(1)
deptId?: number;
}配合全局 ValidationPipe:
typescript
// main.ts
app.useGlobalPipes(new ValidationPipe({
transform: true,
whitelist: true,
}));统一响应
所有接口返回统一格式:
typescript
interface Result<T> {
code: string;
msg: string;
data: T;
}成功响应:
typescript
return { code: '00000', msg: '操作成功', data: user };错误响应:
typescript
throw new BusinessException('A0001', '认证失败');错误处理
自定义异常
typescript
export class BusinessException extends HttpException {
constructor(code: string, msg: string) {
super({ code, msg, data: null }, HttpStatus.OK);
}
}全局异常过滤器
typescript
@Catch()
export class GlobalExceptionFilter implements ExceptionFilter {
catch(exception: unknown, host: ArgumentsHost) {
// 统一异常处理
}
}接口幂等
- 优先使用数据库唯一约束兜底
- 对高风险写操作使用 Redis 分布式锁
typescript
// 分布式锁示例
const lockKey = `lock:order:${orderId}`;
const locked = await this.redisService.lock(lockKey, 30);
if (!locked) {
throw new BusinessException('A0004', '操作进行中,请勿重复提交');
}
try {
// 业务处理
} finally {
await this.redisService.unlock(lockKey);
}代码风格
- ESLint + Prettier
- 使用项目脚本:
pnpm lint/pnpm lint:fix
相关文件
| 文件 | 说明 |
|---|---|
src/common/exception/ | 异常处理 |
src/common/interceptor/ | 响应拦截器 |
src/common/guard/ | 认证守卫 |
src/common/decorator/ | 自定义装饰器 |
eslint.config.mjs | ESLint 配置 |
