编码规范
本文档定义 AI 编程时必须遵守的编码规范。
TypeScript / NestJS 规范
类型严格要求
tsconfig.json必须开启strict: true- 禁止使用
any类型(ESLint:@typescript-eslint/no-explicit-any: error) - 所有函数必须声明参数类型和返回值类型
- DTO 必须使用
class-validator装饰器校验 - Service 方法返回值必须明确类型,禁止返回
any或隐式类型
typescript
// ✅ 正确
async createUser(dto: CreateUserDto): Promise<User> {
return this.prisma.user.create({ data: dto });
}
// ❌ 错误
async createUser(dto: any): Promise<any> {
return this.prisma.user.create({ data: dto });
}测试要求
- 每个 Service 方法 必须 编写对应的单元测试(
.spec.ts) - Controller 必须 有 E2E 测试覆盖核心 CRUD 路径
- 新建模块时,
<module>.service.spec.ts必须与 Service 同步提交 - 测试覆盖率目标:Service ≥ 80%,Controller ≥ 60%
typescript
// 每个 PR 必须包含对应的测试文件:
// src/modules/device/device.service.ts ← 实现
// src/modules/device/device.service.spec.ts ← 必须存在命名约定
| 类型 | 规范 | 示例 |
|---|---|---|
| 文件名 | kebab-case | user.service.ts, auth.controller.ts |
| 类名 | PascalCase | UserService, AuthController |
| 方法/变量 | camelCase | getUserInfo(), accessToken |
| 常量 | UPPER_SNAKE_CASE | JWT_SECRET, REDIS_KEY_PREFIX |
| 接口 | PascalCase, I 前缀可选 | UserInfo, LoginRequest |
| 类型 | PascalCase | PageResult<T>, ApiResponse |
模块结构
src/modules/<module-name>/
├── <module>.module.ts # 模块定义
├── <module>.controller.ts # 控制器(路由)
├── <module>.service.ts # 业务逻辑
├── <module>.service.spec.ts # 单元测试
└── dto/ # 请求/响应 DTO
├── create-<entity>.dto.ts
└── update-<entity>.dto.ts装饰器使用
typescript
// Controller 示例
@Controller('users')
@ApiTags('用户管理')
@UseGuards(AuthGuard('jwt'), RolesGuard)
@ApiBearerAuth()
export class UserController {
@Get()
@ApiOperation({ summary: '获取用户列表' })
@Roles('admin')
async findAll(@Query() query: PageQueryDto) {}
}错误处理
typescript
// 使用 NestJS 内置异常
throw new BadRequestException('参数错误');
throw new UnauthorizedException('未登录');
throw new ForbiddenException('无权限');
throw new NotFoundException('资源不存在');Vue 3 规范
组件命名
| 类型 | 规范 | 示例 |
|---|---|---|
| 页面组件 | kebab-case 目录 | views/system/user/index.vue |
| 通用组件 | PascalCase | UserTable.vue, SearchForm.vue |
| 布局组件 | PascalCase | DefaultLayout.vue |
Composition API 风格
vue
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
const loading = ref(false)
const dataList = ref([])
const filteredList = computed(() => {
return dataList.value.filter(item => item.status === 1)
})
onMounted(async () => {
await fetchData()
})
</script>Pinia Store 规范
typescript
// Setup Store 风格(推荐)
export const useUserStore = defineStore('user', () => {
const userInfo = ref<UserInfo>({} as UserInfo)
const isLoggedIn = computed(() => !!userInfo.value.id)
async function login(data: LoginRequest) {
const res = await AuthAPI.login(data)
setAccessToken(res.data.accessToken)
}
return { userInfo, isLoggedIn, login }
})数据库规范
表命名
- 表名:snake_case,单数形式
- Prisma model 名:PascalCase,单数形式
- 字段名:camelCase,数据库映射为 snake_case
prisma
model User {
id String @id @map("user_id")
createdTime DateTime @default(now()) @map("created_time")
@@map("user")
}C / ESP-IDF 编码规范
命名约定
| 类型 | 规范 | 示例 |
|---|---|---|
| 组件名 | snake_case | sc8co2, ws2812_led |
| 源文件 | snake_case | sc8co2.c, ws2812_led.h |
| 函数名 | snake_case,组件前缀 | sc8co2_init(), ws2812_led_set_color() |
| 宏/常量 | UPPER_SNAKE_CASE,组件前缀 | SC8CO2_UART_PORT, LED_GPIO |
| 结构体 | snake_case,_t 后缀 | sc8co2_handle_t |
| 全局变量 | snake_case | i2c_bus, led_strip |
| FreeRTOS 任务 | snake_case,_task 后缀 | sensor_task |
组件结构
components/<component-name>/
├── CMakeLists.txt # idf_component_register
├── <component>.c # 实现
├── include/
│ └── <component>.h # 公开 API
└── idf_component.yml # 组件注册表依赖(可选)日志规范
c
#include "esp_log.h"
static const char *TAG = "COMPONENT";
ESP_LOGI(TAG, "初始化完成"); // 信息
ESP_LOGW(TAG, "响应超时 %dms", timeout); // 警告
ESP_LOGE(TAG, "I2C 读取失败: %s", esp_err_to_name(ret)); // 错误错误处理
c
// 函数返回 esp_err_t,调用方检查返回值
esp_err_t ret = aht20_read_data(handle, &temp, &humi);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "AHT20 读取失败");
return ret;
}
// 指针参数有效性检查
if (!handle || !co2_value) {
return ESP_ERR_INVALID_ARG;
}传感器故障约定
所有传感器数据获取失败时,对应值设为 -999(float)或 -999.0,便于上层统一判断数据有效性。
Git 提交规范
bash
<type>: <简短描述>
# type 可选:
# feat 新功能
# fix 修复
# docs 文档
# refactor 重构
# test 测试
# chore 构建/工具示例:
feat: 添加设备注册接口
fix: 修复 MQTT 重连问题
docs: 更新 API 接口规范API 响应格式
typescript
// 成功响应
{ code: '00000', msg: 'Success', data: {...} }
// 分页响应
{ code: '00000', msg: 'Success', data: { list: [...], total: 100 } }
// 错误响应
{ code: 'A0001', msg: '参数错误' }日志规范
typescript
// 使用 NestJS Logger
private readonly logger = new Logger(UserService.name);
this.logger.log(`用户 ${userId} 登录成功`);
this.logger.warn(`设备 ${deviceId} 离线`);
this.logger.error(`MQTT 连接失败: ${err.message}`, err.stack);
this.logger.debug(`查询参数: ${JSON.stringify(query)}`);