341 lines
11 KiB
Markdown
341 lines
11 KiB
Markdown
|
|
# NestJS 文件生成标准(严格规范)
|
|||
|
|
|
|||
|
|
## 🚫 严格禁止条款
|
|||
|
|
|
|||
|
|
### 绝对禁止的行为
|
|||
|
|
1. **禁止自创业务逻辑** - 所有业务逻辑必须严格按照PHP项目实现
|
|||
|
|
2. **禁止假设数据结构** - 所有数据结构必须基于真实数据库表结构
|
|||
|
|
3. **禁止使用默认值** - 所有字段、方法、配置必须基于真实PHP代码
|
|||
|
|
4. **禁止编写骨架代码** - 不允许生成空方法或TODO注释
|
|||
|
|
5. **禁止写死数据** - 不允许硬编码任何业务数据
|
|||
|
|
6. **禁止猜测API接口** - 所有接口必须基于PHP控制器真实方法
|
|||
|
|
|
|||
|
|
## 📋 数据源依据(必须严格遵循)
|
|||
|
|
|
|||
|
|
### 1. 数据库结构依据
|
|||
|
|
- **唯一数据源**: `g:\wwjcloud-nestjs\sql\wwjcloud.sql`
|
|||
|
|
- **字段定义**: 严格按照SQL表结构定义实体字段
|
|||
|
|
- **字段类型**: 完全对应数据库字段类型
|
|||
|
|
- **字段约束**: 包括NOT NULL、DEFAULT、COMMENT等
|
|||
|
|
|
|||
|
|
### 2. PHP业务逻辑依据
|
|||
|
|
- **控制器方法**: `niucloud-php\niucloud\app\adminapi\controller\`
|
|||
|
|
- **服务层逻辑**: `niucloud-php\niucloud\app\service\`
|
|||
|
|
- **模型定义**: `niucloud-php\niucloud\app\model\`
|
|||
|
|
- **验证规则**: `niucloud-php\niucloud\app\validate\`
|
|||
|
|
|
|||
|
|
### 3. Java框架参考标准
|
|||
|
|
- **Spring Boot命名规范**: 文件后缀、类命名、方法命名
|
|||
|
|
- **分层架构**: Controller → Service → Repository → Entity
|
|||
|
|
- **注解使用**: 参考Spring Boot注解模式设计NestJS装饰器
|
|||
|
|
|
|||
|
|
## 🏗️ 文件生成规范
|
|||
|
|
|
|||
|
|
### 实体文件生成 (*.entity.ts)
|
|||
|
|
```typescript
|
|||
|
|
// 基于数据库表: sys_user
|
|||
|
|
// 严格对应字段,不允许增减
|
|||
|
|
|
|||
|
|
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
|
|||
|
|
|
|||
|
|
@Entity('sys_user')
|
|||
|
|
export class SysUser {
|
|||
|
|
@PrimaryGeneratedColumn({ name: 'uid', comment: '系统用户ID' })
|
|||
|
|
uid: number;
|
|||
|
|
|
|||
|
|
@Column({ name: 'username', type: 'varchar', length: 255, default: '', comment: '用户账号' })
|
|||
|
|
username: string;
|
|||
|
|
|
|||
|
|
@Column({ name: 'head_img', type: 'varchar', length: 255, default: '' })
|
|||
|
|
headImg: string;
|
|||
|
|
|
|||
|
|
@Column({ name: 'password', type: 'varchar', length: 100, default: '', comment: '用户密码' })
|
|||
|
|
password: string;
|
|||
|
|
|
|||
|
|
@Column({ name: 'real_name', type: 'varchar', length: 16, default: '', comment: '实际姓名' })
|
|||
|
|
realName: string;
|
|||
|
|
|
|||
|
|
@Column({ name: 'last_ip', type: 'varchar', length: 50, default: '', comment: '最后一次登录ip' })
|
|||
|
|
lastIp: string;
|
|||
|
|
|
|||
|
|
@Column({ name: 'last_time', type: 'int', unsigned: true, default: 0, comment: '最后一次登录时间' })
|
|||
|
|
lastTime: number;
|
|||
|
|
|
|||
|
|
@Column({ name: 'create_time', type: 'int', unsigned: true, default: 0, comment: '添加时间' })
|
|||
|
|
createTime: number;
|
|||
|
|
|
|||
|
|
@Column({ name: 'login_count', type: 'int', unsigned: true, default: 0, comment: '登录次数' })
|
|||
|
|
loginCount: number;
|
|||
|
|
|
|||
|
|
@Column({ name: 'status', type: 'tinyint', unsigned: true, default: 1, comment: '后台管理员状态 1有效0无效' })
|
|||
|
|
status: number;
|
|||
|
|
|
|||
|
|
@Column({ name: 'is_del', type: 'tinyint', unsigned: true, default: 0 })
|
|||
|
|
isDel: number;
|
|||
|
|
|
|||
|
|
@Column({ name: 'delete_time', type: 'int', default: 0, comment: '删除时间' })
|
|||
|
|
deleteTime: number;
|
|||
|
|
|
|||
|
|
@Column({ name: 'update_time', type: 'int', default: 0, comment: '更新时间' })
|
|||
|
|
updateTime: number;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 控制器文件生成 (*.controller.ts)
|
|||
|
|
```typescript
|
|||
|
|
// 基于PHP控制器: app\adminapi\controller\user\User.php
|
|||
|
|
// 严格对应所有public方法
|
|||
|
|
|
|||
|
|
import { Controller, Get, Post, Put, Delete, Param, Body, Query } from '@nestjs/common';
|
|||
|
|
import { UserService } from './user.service';
|
|||
|
|
|
|||
|
|
@Controller('adminapi/user')
|
|||
|
|
export class UserController {
|
|||
|
|
constructor(private readonly userService: UserService) {}
|
|||
|
|
|
|||
|
|
// 对应PHP方法: public function lists()
|
|||
|
|
@Get('lists')
|
|||
|
|
async lists(@Query() query: any) {
|
|||
|
|
const data = {
|
|||
|
|
username: query.username || '',
|
|||
|
|
real_name: query.real_name || '',
|
|||
|
|
last_time: query.last_time || []
|
|||
|
|
};
|
|||
|
|
return await this.userService.getPage(data);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 对应PHP方法: public function info($uid)
|
|||
|
|
@Get('info/:uid')
|
|||
|
|
async info(@Param('uid') uid: number) {
|
|||
|
|
return await this.userService.getInfo(uid);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 对应PHP方法: public function getUserAll()
|
|||
|
|
@Get('getUserAll')
|
|||
|
|
async getUserAll(@Query() query: any) {
|
|||
|
|
const data = {
|
|||
|
|
username: query.username || '',
|
|||
|
|
realname: query.realname || '',
|
|||
|
|
create_time: query.create_time || []
|
|||
|
|
};
|
|||
|
|
return await this.userService.getUserAll(data);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 对应PHP方法: public function getUserSelect()
|
|||
|
|
@Get('getUserSelect')
|
|||
|
|
async getUserSelect(@Query() query: any) {
|
|||
|
|
const data = {
|
|||
|
|
username: query.username || ''
|
|||
|
|
};
|
|||
|
|
return await this.userService.getUserSelect(data);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 对应PHP方法: public function checkUserIsExist()
|
|||
|
|
@Get('checkUserIsExist')
|
|||
|
|
async checkUserIsExist(@Query() query: any) {
|
|||
|
|
const data = {
|
|||
|
|
username: query.username || ''
|
|||
|
|
};
|
|||
|
|
return await this.userService.checkUsername(data.username);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 对应PHP方法: public function add()
|
|||
|
|
@Post('add')
|
|||
|
|
async add(@Body() body: any) {
|
|||
|
|
const data = {
|
|||
|
|
username: body.username || '',
|
|||
|
|
password: body.password || '',
|
|||
|
|
real_name: body.real_name || '',
|
|||
|
|
status: body.status || 1, // UserDict::ON
|
|||
|
|
head_img: body.head_img || '',
|
|||
|
|
create_site_limit: body.create_site_limit || []
|
|||
|
|
};
|
|||
|
|
return await this.userService.add(data);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 对应PHP方法: public function edit($uid)
|
|||
|
|
@Put('edit/:uid')
|
|||
|
|
async edit(@Param('uid') uid: number, @Body() body: any) {
|
|||
|
|
const data = {
|
|||
|
|
password: body.password || '',
|
|||
|
|
real_name: body.real_name || '',
|
|||
|
|
head_img: body.head_img || ''
|
|||
|
|
};
|
|||
|
|
return await this.userService.edit(uid, data);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 对应PHP方法: public function del($uid)
|
|||
|
|
@Delete('del/:uid')
|
|||
|
|
async del(@Param('uid') uid: number) {
|
|||
|
|
return await this.userService.del(uid);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 对应PHP方法: public function getUserCreateSiteLimit($uid)
|
|||
|
|
@Get('getUserCreateSiteLimit/:uid')
|
|||
|
|
async getUserCreateSiteLimit(@Param('uid') uid: number) {
|
|||
|
|
return await this.userService.getUserCreateSiteLimit(uid);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 对应PHP方法: public function getUserCreateSiteLimitInfo($id)
|
|||
|
|
@Get('getUserCreateSiteLimitInfo/:id')
|
|||
|
|
async getUserCreateSiteLimitInfo(@Param('id') id: number) {
|
|||
|
|
return await this.userService.getUserCreateSiteLimitInfo(id);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 对应PHP方法: public function addUserCreateSiteLimit($uid)
|
|||
|
|
@Post('addUserCreateSiteLimit/:uid')
|
|||
|
|
async addUserCreateSiteLimit(@Param('uid') uid: number, @Body() body: any) {
|
|||
|
|
const data = {
|
|||
|
|
uid: body.uid || 0,
|
|||
|
|
group_id: body.group_id || 0,
|
|||
|
|
num: body.num || 1,
|
|||
|
|
month: body.month || 1
|
|||
|
|
};
|
|||
|
|
return await this.userService.addUserCreateSiteLimit(data);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 对应PHP方法: public function editUserCreateSiteLimit($id)
|
|||
|
|
@Put('editUserCreateSiteLimit/:id')
|
|||
|
|
async editUserCreateSiteLimit(@Param('id') id: number, @Body() body: any) {
|
|||
|
|
const data = {
|
|||
|
|
num: body.num || 1,
|
|||
|
|
month: body.month || 1
|
|||
|
|
};
|
|||
|
|
return await this.userService.editUserCreateSiteLimit(id, data);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 对应PHP方法: public function delUserCreateSiteLimit($id)
|
|||
|
|
@Delete('delUserCreateSiteLimit/:id')
|
|||
|
|
async delUserCreateSiteLimit(@Param('id') id: number) {
|
|||
|
|
return await this.userService.delUserCreateSiteLimit(id);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 服务文件生成 (*.service.ts)
|
|||
|
|
```typescript
|
|||
|
|
// 基于PHP服务: app\service\admin\user\UserService.php
|
|||
|
|
// 严格对应所有public方法签名和业务逻辑
|
|||
|
|
|
|||
|
|
import { Injectable } from '@nestjs/common';
|
|||
|
|
import { InjectRepository } from '@nestjs/typeorm';
|
|||
|
|
import { Repository } from 'typeorm';
|
|||
|
|
import { SysUser } from './sysUser.entity';
|
|||
|
|
|
|||
|
|
@Injectable()
|
|||
|
|
export class UserService {
|
|||
|
|
constructor(
|
|||
|
|
@InjectRepository(SysUser)
|
|||
|
|
private readonly sysUserRepository: Repository<SysUser>,
|
|||
|
|
) {}
|
|||
|
|
|
|||
|
|
// 对应PHP方法: public function getPage(array $where)
|
|||
|
|
async getPage(where: any): Promise<any> {
|
|||
|
|
// 严格按照PHP逻辑实现
|
|||
|
|
// AuthService::isSuperAdmin(); 对应的权限检查
|
|||
|
|
// 字段选择: 'uid,username,head_img,real_name,last_ip,last_time,login_count,status'
|
|||
|
|
// 搜索条件: username, real_name, last_time
|
|||
|
|
// 排序: uid desc
|
|||
|
|
// 分页查询逻辑
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 对应PHP方法: public function getInfo(int $uid)
|
|||
|
|
async getInfo(uid: number): Promise<any> {
|
|||
|
|
// 严格按照PHP逻辑实现
|
|||
|
|
// 权限检查、字段选择、关联查询等
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 对应PHP方法: public function add(array $data)
|
|||
|
|
async add(data: any): Promise<any> {
|
|||
|
|
// 严格按照PHP逻辑实现
|
|||
|
|
// 用户名重复检查、事务处理等
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ... 其他方法严格对应PHP服务类
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 🔍 生成检查清单
|
|||
|
|
|
|||
|
|
### 必须检查项
|
|||
|
|
- [ ] 实体字段与数据库表100%对应
|
|||
|
|
- [ ] 控制器方法与PHP控制器100%对应
|
|||
|
|
- [ ] 服务方法与PHP服务100%对应
|
|||
|
|
- [ ] 方法参数与PHP方法参数100%对应
|
|||
|
|
- [ ] 业务逻辑与PHP业务逻辑100%对应
|
|||
|
|
- [ ] 路由定义与PHP路由100%对应
|
|||
|
|
|
|||
|
|
### 禁止检查项
|
|||
|
|
- [ ] 没有自创的业务逻辑
|
|||
|
|
- [ ] 没有假设的数据结构
|
|||
|
|
- [ ] 没有默认的配置值
|
|||
|
|
- [ ] 没有空的方法体
|
|||
|
|
- [ ] 没有TODO注释
|
|||
|
|
- [ ] 没有硬编码数据
|
|||
|
|
|
|||
|
|
## 🎯 质量标准
|
|||
|
|
|
|||
|
|
### A级标准(必须达到)
|
|||
|
|
- 数据库字段映射准确率: 100%
|
|||
|
|
- PHP方法对应准确率: 100%
|
|||
|
|
- 业务逻辑一致性: 100%
|
|||
|
|
- 代码可直接运行: 100%
|
|||
|
|
|
|||
|
|
### 验证方式
|
|||
|
|
1. 使用 `auto-mapping-checker.js` 检查文件对应关系
|
|||
|
|
2. 对比数据库表结构与实体定义
|
|||
|
|
3. 对比PHP控制器与NestJS控制器方法
|
|||
|
|
4. 对比PHP服务与NestJS服务业务逻辑
|
|||
|
|
|
|||
|
|
## 📝 开发流程
|
|||
|
|
|
|||
|
|
### 标准流程(严格执行)
|
|||
|
|
1. **分析阶段**: 详细分析PHP源码和数据库结构
|
|||
|
|
2. **设计阶段**: 基于真实数据设计NestJS文件结构
|
|||
|
|
3. **实现阶段**: 严格按照PHP逻辑实现NestJS代码
|
|||
|
|
4. **验证阶段**: 使用自动化工具验证对应关系
|
|||
|
|
5. **测试阶段**: 确保生成的代码可以正常运行
|
|||
|
|
|
|||
|
|
### 每个文件生成前必须
|
|||
|
|
1. 查看对应的PHP文件源码
|
|||
|
|
2. 查看相关的数据库表结构
|
|||
|
|
3. 理解真实的业务逻辑
|
|||
|
|
4. 确认所有依赖关系
|
|||
|
|
5. 验证生成的代码正确性
|
|||
|
|
|
|||
|
|
## ⚠️ 违规处理
|
|||
|
|
|
|||
|
|
### 发现违规行为时
|
|||
|
|
1. 立即停止代码生成
|
|||
|
|
2. 重新分析PHP源码
|
|||
|
|
3. 修正错误的假设
|
|||
|
|
4. 重新生成正确代码
|
|||
|
|
5. 验证修正结果
|
|||
|
|
|
|||
|
|
### 常见违规示例
|
|||
|
|
```typescript
|
|||
|
|
// ❌ 错误示例 - 自创字段
|
|||
|
|
@Column()
|
|||
|
|
createdBy: string; // 数据库表中不存在此字段
|
|||
|
|
|
|||
|
|
// ❌ 错误示例 - 假设方法
|
|||
|
|
async someMethod() {
|
|||
|
|
// TODO: 实现业务逻辑
|
|||
|
|
} // PHP中不存在此方法
|
|||
|
|
|
|||
|
|
// ❌ 错误示例 - 默认值
|
|||
|
|
const DEFAULT_PAGE_SIZE = 10; // 应该从PHP代码中获取真实值
|
|||
|
|
|
|||
|
|
// ✅ 正确示例 - 基于真实数据
|
|||
|
|
@Column({ name: 'username', type: 'varchar', length: 255, default: '', comment: '用户账号' })
|
|||
|
|
username: string; // 严格对应数据库字段定义
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 🎯 最终目标
|
|||
|
|
|
|||
|
|
确保生成的NestJS项目:
|
|||
|
|
1. **业务逻辑100%与PHP一致**
|
|||
|
|
2. **数据结构100%与数据库一致**
|
|||
|
|
3. **API接口100%与PHP接口一致**
|
|||
|
|
4. **代码质量符合NestJS最佳实践**
|
|||
|
|
5. **可以直接投入生产使用**
|