Files
seclusion/plop/templates/api/controller.hbs
charilezhou 3119460f13 feat(plop): 优化生成器支持 Prisma 关联关系
- 支持一对多/多对一关系定义并生成到 Prisma schema
- 简化流程:查询关联配置根据关系自动预填
- 修复 Handlebars 模板 HTML 转义导致的乱码问题
- 修复 controller 模板缺少 Prisma 导入的问题
- 新增页面模板 (page.hbs) 生成前端页面
- 添加 FindAllParams/PaginationQueryDto 索引签名修复类型兼容

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 17:30:18 +08:00

178 lines
5.9 KiB
Handlebars

import {
Controller,
Get,
Post,
{{#if (eq serviceType 'CrudService')}}Patch{{else}}Put{{/if}},
Delete,
Param,
Body,
Query,
UseGuards,
} from '@nestjs/common';
import {
ApiTags,
ApiOperation,
ApiBearerAuth,
ApiOkResponse,
ApiCreatedResponse,
} from '@nestjs/swagger';
{{#if hasQueryDto}}
import { Prisma } from '@prisma/client';
{{/if}}
import {
Create{{pascalCase name}}Dto,
Update{{pascalCase name}}Dto,
{{pascalCase name}}ResponseDto,
{{#if needsDetailDto}}
{{pascalCase name}}DetailResponseDto,
{{/if}}
Paginated{{pascalCase name}}ResponseDto,
{{#if hasQueryDto}}
{{pascalCase name}}QueryDto,
{{/if}}
{{#each manyToMany}}
Assign{{pascalCase name}}Dto,
{{targetModel}}BriefDto,
{{/each}}
} from './dto/{{kebabCase name}}.dto';
import { {{pascalCase name}}Service } from './{{kebabCase name}}.service';
import { JwtAuthGuard } from '@/auth/guards/jwt-auth.guard';
{{#unless hasQueryDto}}
import { PaginationQueryDto } from '@/common/crud/dto/pagination.dto';
{{/unless}}
@ApiTags('{{chineseName}}')
@Controller('{{kebabCase pluralName}}')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
export class {{pascalCase name}}Controller {
constructor(private readonly {{camelCase name}}Service: {{pascalCase name}}Service) {}
@Post()
@ApiOperation({ summary: '创建{{chineseName}}' })
@ApiCreatedResponse({ type: {{pascalCase name}}ResponseDto, description: '创建成功' })
create(@Body() dto: Create{{pascalCase name}}Dto) {
return this.{{camelCase name}}Service.create(dto);
}
@Get()
@ApiOperation({ summary: '获取所有{{chineseName}}(分页)' })
@ApiOkResponse({ type: Paginated{{pascalCase name}}ResponseDto, description: '{{chineseName}}列表' })
{{#if hasQueryDto}}
findAll(@Query() query: {{pascalCase name}}QueryDto) {
{{#if (eq serviceType 'CrudService')}}
const { {{#each queryFields}}{{name}}, {{/each}}...pagination } = query;
const where: Prisma.{{pascalCase name}}WhereInput = {};
{{#each queryFields}}
if ({{name}}) {
{{#if (eq type 'string')}}
where.{{name}} = { contains: {{name}}, mode: 'insensitive' };
{{else}}
where.{{name}} = {{name}};
{{/if}}
}
{{/each}}
return this.{{camelCase name}}Service.findAll({ ...pagination, where });
{{else}}
return this.{{camelCase name}}Service.findAllWithRelations(query);
{{/if}}
}
{{else}}
findAll(@Query() query: PaginationQueryDto) {
{{#if (eq serviceType 'CrudService')}}
return this.{{camelCase name}}Service.findAll(query);
{{else}}
return this.{{camelCase name}}Service.findAllWithRelations(query);
{{/if}}
}
{{/if}}
{{#if softDelete}}
@Get('deleted')
@ApiOperation({ summary: '获取已删除的{{chineseName}}列表(分页)' })
@ApiOkResponse({ type: Paginated{{pascalCase name}}ResponseDto, description: '已删除{{chineseName}}列表' })
{{#if hasQueryDto}}
findDeleted(@Query() query: {{pascalCase name}}QueryDto) {
const { {{#each queryFields}}{{name}}, {{/each}}...pagination } = query;
const where: Prisma.{{pascalCase name}}WhereInput = {};
{{#each queryFields}}
if ({{name}}) {
{{#if (eq type 'string')}}
where.{{name}} = { contains: {{name}}, mode: 'insensitive' };
{{else}}
where.{{name}} = {{name}};
{{/if}}
}
{{/each}}
return this.{{camelCase name}}Service.findDeleted({ ...pagination, where });
}
{{else}}
findDeleted(@Query() query: PaginationQueryDto) {
return this.{{camelCase name}}Service.findDeleted(query);
}
{{/if}}
{{/if}}
@Get(':id')
@ApiOperation({ summary: '根据 ID 获取{{chineseName}}' })
{{#if needsDetailDto}}
@ApiOkResponse({ type: {{pascalCase name}}DetailResponseDto, description: '{{chineseName}}详情' })
findById(@Param('id') id: string) {
return this.{{camelCase name}}Service.findByIdWithRelations(id);
}
{{else if needsResponseDto}}
@ApiOkResponse({ type: {{pascalCase name}}ResponseDto, description: '{{chineseName}}详情' })
findById(@Param('id') id: string) {
return this.{{camelCase name}}Service.findByIdWithRelations(id);
}
{{else}}
@ApiOkResponse({ type: {{pascalCase name}}ResponseDto, description: '{{chineseName}}详情' })
findById(@Param('id') id: string) {
return this.{{camelCase name}}Service.findById(id);
}
{{/if}}
@{{#if (eq serviceType 'CrudService')}}Patch{{else}}Put{{/if}}(':id')
@ApiOperation({ summary: '更新{{chineseName}}信息' })
@ApiOkResponse({ type: {{pascalCase name}}ResponseDto, description: '更新后的{{chineseName}}信息' })
update(@Param('id') id: string, @Body() dto: Update{{pascalCase name}}Dto) {
return this.{{camelCase name}}Service.update(id, dto);
}
@Delete(':id')
@ApiOperation({ summary: '删除{{chineseName}}' })
@ApiOkResponse({ description: '删除成功' })
delete(@Param('id') id: string) {
return this.{{camelCase name}}Service.delete(id);
}
{{#if softDelete}}
@{{#if (eq serviceType 'CrudService')}}Patch{{else}}Put{{/if}}(':id/restore')
@ApiOperation({ summary: '恢复已删除的{{chineseName}}' })
@ApiOkResponse({ type: {{pascalCase name}}ResponseDto, description: '恢复后的{{chineseName}}信息' })
restore(@Param('id') id: string) {
return this.{{camelCase name}}Service.restore(id);
}
{{/if}}
{{#if hasManyToMany}}
{{#each manyToMany}}
@Get(':id/{{name}}')
@ApiOperation({ summary: '获取{{../chineseName}}{{name}}列表' })
@ApiOkResponse({ type: [{{targetModel}}BriefDto], description: '{{name}}列表' })
get{{pascalCase name}}(@Param('id') id: string) {
return this.{{camelCase ../name}}Service.getManyToManyTargets(id, '{{name}}');
}
@Put(':id/{{name}}')
@ApiOperation({ summary: '分配{{../chineseName}}{{name}}' })
@ApiOkResponse({ type: {{pascalCase ../name}}DetailResponseDto, description: '分配成功' })
assign{{pascalCase name}}(@Param('id') id: string, @Body() dto: Assign{{pascalCase name}}Dto) {
return this.{{camelCase ../name}}Service.assignManyToMany(id, '{{name}}', { targetIds: dto.{{target}}Ids });
}
{{/each}}
{{/if}}
}