diff --git a/scripts/template/module/{{fileName name}}.controller.ts.hbs b/scripts/template/module/{{fileName name}}.controller.ts.hbs index 66cd3d3..605f3a6 100644 --- a/scripts/template/module/{{fileName name}}.controller.ts.hbs +++ b/scripts/template/module/{{fileName name}}.controller.ts.hbs @@ -1,7 +1,7 @@ import { BaseController } from '@/common/base'; import { Respond, RespondType } from '@/common/response'; -import { Body, Controller, Delete, Get, Param, Patch, Post, Query, Version } from '@nestjs/common'; -import { ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger'; +import { Body, Controller, Delete, Get, Param, Patch, Post, Query, ParseIntPipe } from '@nestjs/common'; +import { ApiOkResponse, ApiTags } from '@nestjs/swagger'; import { Create{{upcaseName name}}Dto } from './dto/create-{{fileName name}}.dto'; import { Find{{upcaseName name}}Dto } from './dto/find-{{fileName name}}.dto'; import { Update{{upcaseName name}}Dto } from './dto/update-{{fileName name}}.dto'; @@ -15,29 +15,45 @@ export class {{upcaseName name}}Controller extends BaseController { super(); } + /** + * 新增{{cnName}} + */ @Post() - @ApiOperation({ description: '创建{{cnName}}', operationId: 'add{{upcaseName name}}' }) - create(@Body() create{{upcaseName name}}Dto: Create{{upcaseName name}}Dto) { + add{{upcaseName name}}(@Body() create{{upcaseName name}}Dto: Create{{upcaseName name}}Dto) { return this.{{lowcaseName name}}Service.create(create{{upcaseName name}}Dto); } + /** + * 根据分页/过滤参数查询{{cnName}} + */ @Get() @Respond(RespondType.PAGINATION) @ApiOkResponse({ isArray: true, type: {{upcaseName name}} }) - @ApiOperation({ description: '批量查询{{cnName}}', operationId: 'get{{upcaseName name}}s' }) - async findMany(@Query() query: Find{{upcaseName name}}Dto) { + get{{upcaseName name}}s(@Query() query: Find{{upcaseName name}}Dto) { return this.{{lowcaseName name}}Service.findMany(query); } + /** + * 根据ID查询{{cnName}} + */ + @Get(':id') + get{{upcaseName name}}(@Param('id', ParseIntPipe) id: number): Promise<{{upcaseName name}}> { + return this.{{lowcaseName name}}Service.findOne(id); + } + + /** + * 根据ID更新{{cnName}} + */ @Patch(':id') - @ApiOperation({ description: '更新{{cnName}}', operationId: 'update{{upcaseName name}}' }) - update(@Param('id') id: number, @Body() update{{upcaseName name}}Dto: Update{{upcaseName name}}Dto) { + update{{upcaseName name}}(@Param('id', ParseIntPipe) id: number, @Body() update{{upcaseName name}}Dto: Update{{upcaseName name}}Dto) { return this.{{lowcaseName name}}Service.update(+id, update{{upcaseName name}}Dto); } + /** + * 根据ID删除{{cnName}} + */ @Delete(':id') - @ApiOperation({ description: '删除{{cnName}}', operationId: 'delete{{upcaseName name}}' }) - remove(@Param('id') id: number) { + del{{upcaseName name}}(@Param('id', ParseIntPipe) id: number) { return this.{{lowcaseName name}}Service.remove(+id); } } diff --git a/src/common/response/notcaptured.filter.ts b/src/common/response/notcaptured.filter.ts index 297c2fc..90d9041 100644 --- a/src/common/response/notcaptured.filter.ts +++ b/src/common/response/notcaptured.filter.ts @@ -8,7 +8,7 @@ import { LoggerService } from '../logger'; export class AllExecptionFilter implements ExceptionFilter { constructor(private logger: LoggerService) {} - catch(exception: Error, host: ArgumentsHost) { + catch(exception: any, host: ArgumentsHost) { const ctx = host.switchToHttp(); const request = ctx.getRequest(); const response = ctx.getResponse<_Response>(); @@ -16,6 +16,23 @@ export class AllExecptionFilter implements ExceptionFilter { const code = ResponseCode.UNKNOWN_ERROR; console.trace(exception); this.logger.error(exception, `${request.method} ${request.url}`); - response.status(HttpStatus.INTERNAL_SERVER_ERROR).json(Response.create({ code, message, data: null })); + + // 静态文件路径不存在的异常 + if (exception.code === 'ENOENT') { + return response.status(exception.status).json( + Response.create({ + code: ResponseCode.ERROR, + message: '访问的路径不存在', + }), + ); + } + + // 其他异常 + response.status(HttpStatus.INTERNAL_SERVER_ERROR).json( + Response.create({ + code, + message, + }), + ); } } diff --git a/src/common/response/response.ts b/src/common/response/response.ts index cf64072..8e233e9 100644 --- a/src/common/response/response.ts +++ b/src/common/response/response.ts @@ -24,7 +24,7 @@ export class Response { * @example 1 */ @ApiProperty({}) - data: T; + data?: T; /** * 响应元数据 diff --git a/src/common/static/static.module.ts b/src/common/static/static.module.ts index 5db8123..d42d099 100644 --- a/src/common/static/static.module.ts +++ b/src/common/static/static.module.ts @@ -11,9 +11,16 @@ export const ServeStaticModule = _ServeStaticModule.forRootAsync({ { rootPath: config.uploadDir, serveRoot: config.uploadPrefix, + serveStaticOptions: { + fallthrough: false, + }, }, { rootPath: config.staticDir, + serveRoot: config.staticPrefix, + serveStaticOptions: { + fallthrough: false, + }, }, ]; }, diff --git a/src/common/swagger/index.ts b/src/common/swagger/index.ts index 934eb49..07f6cda 100644 --- a/src/common/swagger/index.ts +++ b/src/common/swagger/index.ts @@ -24,7 +24,7 @@ export const initSwagger = (app: INestApplication) => { .build(); const options: SwaggerDocumentOptions = { operationIdFactory(controllerKey, methodKey) { - return `${controllerKey}_${methodKey}`; + return `${methodKey}`; }, }; const document = addResponseWrapper(SwaggerModule.createDocument(app, docConfig, options)); diff --git a/src/common/swagger/util.ts b/src/common/swagger/util.ts index 6643162..953cc98 100644 --- a/src/common/swagger/util.ts +++ b/src/common/swagger/util.ts @@ -27,6 +27,13 @@ export function addResponseWrapper(doc: OpenAPIObject) { for (const status of Object.keys(responses)) { const json = responses[status].content?.['application/json']; if (!json) { + responses[status].content = { + 'application/json': { + schema: { + $ref: '#/components/schemas/Response', + }, + }, + }; continue; } const schema = json.schema; diff --git a/src/config/config.service.ts b/src/config/config.service.ts index 0c40322..13191cf 100644 --- a/src/config/config.service.ts +++ b/src/config/config.service.ts @@ -122,6 +122,14 @@ export class ConfigService { return this.config.get('STATIC_DIR', './content/static'); } + /** + * 静态文件URL前缀 + * @default '/'' + */ + get staticPrefix(): string { + return this.config.get('STATIC_PREFIX', '/'); + } + /** * 默认页码 * @default 1 diff --git a/src/modules/user/user.controller.ts b/src/modules/user/user.controller.ts index 040423c..6016359 100644 --- a/src/modules/user/user.controller.ts +++ b/src/modules/user/user.controller.ts @@ -1,12 +1,12 @@ import { BaseController } from '@/common/base'; import { Respond, RespondType } from '@/common/response'; -import { Body, Controller, Delete, Get, Param, Patch, Post, Query, Version } from '@nestjs/common'; -import { ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger'; +import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post, Query } from '@nestjs/common'; +import { ApiOkResponse, ApiTags } from '@nestjs/swagger'; import { CreateUserDto } from './dto/create-user.dto'; import { FindUserDto } from './dto/find-user.dto'; import { UpdateUserDto } from './dto/update-user.dto'; -import { User } from './entities/user.entity'; import { UserService } from './user.service'; +import { User } from './entities/user.entity'; @ApiTags('user') @Controller('users') @@ -15,36 +15,45 @@ export class UserController extends BaseController { super(); } + /** + * 新增用户 + */ @Post() - @ApiOperation({ description: '创建用户', operationId: 'addUser' }) - create(@Body() createUserDto: CreateUserDto) { + addUser(@Body() createUserDto: CreateUserDto) { return this.userService.create(createUserDto); } + /** + * 分页/条件查询用户 + */ @Get() @Respond(RespondType.PAGINATION) - @ApiOkResponse({ isArray: true, type: User }) - @ApiOperation({ description: '批量查询用户', operationId: 'getUsers' }) - async findMany(@Query() query: FindUserDto) { + @ApiOkResponse({ type: User, isArray: true }) + async getUsers(@Query() query: FindUserDto) { return this.userService.findMany(query); } + /** + * 根据ID查询用户 + */ @Get(':id') - @Version('2') - @ApiOperation({ deprecated: true, description: '查询用户', operationId: 'getUserv2' }) - findOne(@Param('id') id: number) { - return this.userService.findOne(+id); + getUser(@Param('id', ParseIntPipe) id: number): Promise { + return this.userService.findOne(id); } + /** + * 根据ID更新用户 + */ @Patch(':id') - @ApiOperation({ description: '更新用户', operationId: 'updateUser' }) - update(@Param('id') id: number, @Body() updateUserDto: UpdateUserDto) { + updateUser(@Param('id') id: number, @Body() updateUserDto: UpdateUserDto) { return this.userService.update(+id, updateUserDto); } + /** + * 根据ID删除用户 + */ @Delete(':id') - @ApiOperation({ description: '删除用户', operationId: 'deleteUser' }) - remove(@Param('id') id: number) { + delUser(@Param('id', ParseIntPipe) id: number) { return this.userService.remove(+id); } }