- ✅ 成功运行迁移工具,生成28个模块的完整NestJS代码 - ✅ 生成所有实体、服务、控制器、验证器等组件 - ✅ 修复npm依赖冲突,更新package-lock.json - ✅ 添加Docker测试脚本和配置文件 - ✅ 完善迁移工具的调试日志和错误处理 - 🔧 包含增量更新工具和质量检查工具 - 📊 迁移统计:28个模块,数千个文件,耗时26.47秒 主要变更: - wwjcloud-nest/src/core/* - 生成的业务模块代码 - tools/* - 迁移工具和辅助脚本 - wwjcloud-nest/package.json - 依赖更新 - docker/* - 容器化配置和测试脚本
341 lines
11 KiB
Markdown
341 lines
11 KiB
Markdown
# NestJS 文件生成标准(严格规范)
|
||
|
||
## 🚫 严格禁止条款
|
||
|
||
### 绝对禁止的行为
|
||
1. **禁止自创业务逻辑** - 所有业务逻辑必须严格按照PHP项目实现
|
||
2. **禁止假设数据结构** - 所有数据结构必须基于真实数据库表结构
|
||
3. **禁止使用默认值** - 所有字段、方法、配置必须基于真实PHP代码
|
||
4. **禁止编写骨架代码** - 不允许生成空方法或TODO注释
|
||
5. **禁止写死数据** - 不允许硬编码任何业务数据
|
||
6. **禁止猜测API接口** - 所有接口必须基于PHP控制器真实方法
|
||
|
||
## 📋 数据源依据(必须严格遵循)
|
||
|
||
### 1. 数据库结构依据
|
||
- **唯一数据源**: `./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. **可以直接投入生产使用** |