From f516e98f7feba3f9d287dbba6eca5408d8f5d2c5 Mon Sep 17 00:00:00 2001 From: liuyun Date: Sun, 11 Oct 2026 12:46:10 +0800 Subject: [PATCH] feat: list search filters for user/config/role/audit-log/login-log MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - user/config/role/audit-log/login-log 列表增加搜索过滤(ListXxxQuery) - audit-logs/login-logs 新增 dto + listXxx 方法 Co-Authored-By: Claude Opus 4.8 --- src/audit-logs/audit-logs.controller.ts | 6 +++--- src/audit-logs/audit-logs.service.ts | 9 +++++++++ src/audit-logs/dto.ts | 20 ++++++++++++++++++++ src/configs/configs.controller.ts | 7 +++---- src/configs/configs.service.ts | 9 ++++++++- src/configs/dto.ts | 13 +++++++++++++ src/login-logs/dto.ts | 15 +++++++++++++++ src/login-logs/login-logs.controller.ts | 6 +++--- src/login-logs/login-logs.service.ts | 8 ++++++++ src/roles/dto.ts | 18 ++++++++++++++++++ src/roles/roles.controller.ts | 7 +++---- src/roles/roles.service.ts | 10 +++++++++- 12 files changed, 112 insertions(+), 16 deletions(-) create mode 100644 src/audit-logs/dto.ts create mode 100644 src/login-logs/dto.ts diff --git a/src/audit-logs/audit-logs.controller.ts b/src/audit-logs/audit-logs.controller.ts index 4408443..0906341 100644 --- a/src/audit-logs/audit-logs.controller.ts +++ b/src/audit-logs/audit-logs.controller.ts @@ -1,7 +1,7 @@ import { Controller, Get, Query } from '@nestjs/common'; -import { PageQuery } from '../common/page.dto.js'; import { Permissions } from '../common/permissions.js'; import { RequirePermissions } from '../auth/decorators.js'; +import { ListAuditLogQuery } from './dto.js'; import { AuditLogsService } from './audit-logs.service.js'; @Controller('audit-logs') @@ -10,7 +10,7 @@ export class AuditLogsController { @Get() @RequirePermissions(Permissions.audit.list) - list(@Query() q: PageQuery) { - return this.service.paginate(q.page, q.pageSize); + list(@Query() q: ListAuditLogQuery) { + return this.service.listAuditLogs(q); } } diff --git a/src/audit-logs/audit-logs.service.ts b/src/audit-logs/audit-logs.service.ts index 6e43d86..5c17cf8 100644 --- a/src/audit-logs/audit-logs.service.ts +++ b/src/audit-logs/audit-logs.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common'; import { InjectPinoLogger, PinoLogger } from 'nestjs-pino'; import { BaseCrudService } from '../common/base-crud.service.js'; import { PrismaService } from '../prisma/prisma.service.js'; +import { ListAuditLogQuery } from './dto.js'; export interface AuditLogEntry { tenantCode: string; @@ -37,4 +38,12 @@ export class AuditLogsService extends BaseCrudService { this.logger.warn({ err }, '审计日志写入失败'); } } + + listAuditLogs(q: ListAuditLogQuery) { + const where: Record = {}; + if (q.username) where.username = { contains: q.username }; + if (q.module) where.module = { contains: q.module }; + if (q.status) where.status = q.status; + return this.paginate(q.page, q.pageSize, where); + } } diff --git a/src/audit-logs/dto.ts b/src/audit-logs/dto.ts new file mode 100644 index 0000000..0489300 --- /dev/null +++ b/src/audit-logs/dto.ts @@ -0,0 +1,20 @@ +import { ApiPropertyOptional } from '@nestjs/swagger'; +import { IsOptional, IsString } from 'class-validator'; +import { PageQuery } from '../common/page.dto.js'; + +export class ListAuditLogQuery extends PageQuery { + @ApiPropertyOptional({ description: '操作人(模糊)' }) + @IsOptional() + @IsString() + username?: string; + + @ApiPropertyOptional({ description: '模块(模糊)' }) + @IsOptional() + @IsString() + module?: string; + + @ApiPropertyOptional({ description: '状态:success/fail' }) + @IsOptional() + @IsString() + status?: string; +} diff --git a/src/configs/configs.controller.ts b/src/configs/configs.controller.ts index 50cdb04..c3c6d61 100644 --- a/src/configs/configs.controller.ts +++ b/src/configs/configs.controller.ts @@ -1,8 +1,7 @@ import { Body, Controller, Delete, Get, Param, Patch, Post, Query } from '@nestjs/common'; -import { PageQuery } from '../common/page.dto.js'; import { Permissions } from '../common/permissions.js'; import { AuditLog, RequirePermissions } from '../auth/decorators.js'; -import { CreateConfigDto, UpdateConfigDto } from './dto.js'; +import { CreateConfigDto, ListConfigQuery, UpdateConfigDto } from './dto.js'; import { ConfigsService } from './configs.service.js'; @Controller('configs') @@ -11,8 +10,8 @@ export class ConfigsController { @Get() @RequirePermissions(Permissions.config.list) - list(@Query() q: PageQuery) { - return this.service.paginate(q.page, q.pageSize); + list(@Query() q: ListConfigQuery) { + return this.service.listConfigs(q); } @Get(':id') diff --git a/src/configs/configs.service.ts b/src/configs/configs.service.ts index b9dc0c6..7f3f79d 100644 --- a/src/configs/configs.service.ts +++ b/src/configs/configs.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { BaseCrudService } from '../common/base-crud.service.js'; import { PrismaService } from '../prisma/prisma.service.js'; -import { CreateConfigDto, UpdateConfigDto } from './dto.js'; +import { CreateConfigDto, ListConfigQuery, UpdateConfigDto } from './dto.js'; @Injectable() export class ConfigsService extends BaseCrudService { @@ -16,4 +16,11 @@ export class ConfigsService extends BaseCrudService { updateConfig(id: string, dto: UpdateConfigDto) { return this.update(id, { ...dto }); } + + listConfigs(q: ListConfigQuery) { + const where: Record = {}; + if (q.key) where.key = { contains: q.key }; + if (q.value) where.value = { contains: q.value }; + return this.paginate(q.page, q.pageSize, where); + } } diff --git a/src/configs/dto.ts b/src/configs/dto.ts index af8a027..f9e5131 100644 --- a/src/configs/dto.ts +++ b/src/configs/dto.ts @@ -1,5 +1,6 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { IsNotEmpty, IsOptional, IsString } from 'class-validator'; +import { PageQuery } from '../common/page.dto.js'; export class CreateConfigDto { @ApiProperty({ description: '配置 key(租户内唯一)' }) @@ -29,3 +30,15 @@ export class UpdateConfigDto { @IsString() remark?: string; } + +export class ListConfigQuery extends PageQuery { + @ApiPropertyOptional({ description: '键名(模糊)' }) + @IsOptional() + @IsString() + key?: string; + + @ApiPropertyOptional({ description: '值(模糊)' }) + @IsOptional() + @IsString() + value?: string; +} diff --git a/src/login-logs/dto.ts b/src/login-logs/dto.ts new file mode 100644 index 0000000..d07c400 --- /dev/null +++ b/src/login-logs/dto.ts @@ -0,0 +1,15 @@ +import { ApiPropertyOptional } from '@nestjs/swagger'; +import { IsOptional, IsString } from 'class-validator'; +import { PageQuery } from '../common/page.dto.js'; + +export class ListLoginLogQuery extends PageQuery { + @ApiPropertyOptional({ description: '用户名(模糊)' }) + @IsOptional() + @IsString() + username?: string; + + @ApiPropertyOptional({ description: '状态:success/fail' }) + @IsOptional() + @IsString() + status?: string; +} diff --git a/src/login-logs/login-logs.controller.ts b/src/login-logs/login-logs.controller.ts index 3be6459..5fd46ab 100644 --- a/src/login-logs/login-logs.controller.ts +++ b/src/login-logs/login-logs.controller.ts @@ -1,7 +1,7 @@ import { Controller, Get, Query } from '@nestjs/common'; -import { PageQuery } from '../common/page.dto.js'; import { Permissions } from '../common/permissions.js'; import { RequirePermissions } from '../auth/decorators.js'; +import { ListLoginLogQuery } from './dto.js'; import { LoginLogsService } from './login-logs.service.js'; @Controller('login-logs') @@ -10,7 +10,7 @@ export class LoginLogsController { @Get() @RequirePermissions(Permissions.loginLog.list) - list(@Query() q: PageQuery) { - return this.service.paginate(q.page, q.pageSize); + list(@Query() q: ListLoginLogQuery) { + return this.service.listLoginLogs(q); } } diff --git a/src/login-logs/login-logs.service.ts b/src/login-logs/login-logs.service.ts index 21388ec..dd8f67d 100644 --- a/src/login-logs/login-logs.service.ts +++ b/src/login-logs/login-logs.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common'; import { InjectPinoLogger, PinoLogger } from 'nestjs-pino'; import { BaseCrudService } from '../common/base-crud.service.js'; import { PrismaService } from '../prisma/prisma.service.js'; +import { ListLoginLogQuery } from './dto.js'; export interface LoginLogEntry { tenantCode: string; @@ -29,4 +30,11 @@ export class LoginLogsService extends BaseCrudService { this.logger.warn({ err }, '登录日志写入失败'); } } + + listLoginLogs(q: ListLoginLogQuery) { + const where: Record = {}; + if (q.username) where.username = { contains: q.username }; + if (q.status) where.status = q.status; + return this.paginate(q.page, q.pageSize, where); + } } diff --git a/src/roles/dto.ts b/src/roles/dto.ts index f9fee1a..e9470c6 100644 --- a/src/roles/dto.ts +++ b/src/roles/dto.ts @@ -1,5 +1,6 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { IsArray, IsNotEmpty, IsOptional, IsString } from 'class-validator'; +import { PageQuery } from '../common/page.dto.js'; export class CreateRoleDto { @ApiProperty({ description: '角色编码' }) @@ -51,3 +52,20 @@ export class AssignResourcesDto { @IsString({ each: true }) resourceCodes!: string[]; } + +export class ListRoleQuery extends PageQuery { + @ApiPropertyOptional({ description: '角色名称(模糊)' }) + @IsOptional() + @IsString() + name?: string; + + @ApiPropertyOptional({ description: '角色编码(模糊)' }) + @IsOptional() + @IsString() + code?: string; + + @ApiPropertyOptional({ description: '状态:enabled/disabled' }) + @IsOptional() + @IsString() + status?: string; +} diff --git a/src/roles/roles.controller.ts b/src/roles/roles.controller.ts index db7c6af..bc7eadb 100644 --- a/src/roles/roles.controller.ts +++ b/src/roles/roles.controller.ts @@ -1,8 +1,7 @@ import { Body, Controller, Delete, Get, Param, Patch, Post, Put, Query } from '@nestjs/common'; -import { PageQuery } from '../common/page.dto.js'; import { Permissions } from '../common/permissions.js'; import { AuditLog, RequirePermissions } from '../auth/decorators.js'; -import { AssignResourcesDto, CreateRoleDto, UpdateRoleDto } from './dto.js'; +import { AssignResourcesDto, CreateRoleDto, ListRoleQuery, UpdateRoleDto } from './dto.js'; import { RolesService } from './roles.service.js'; @Controller('roles') @@ -11,8 +10,8 @@ export class RolesController { @Get() @RequirePermissions(Permissions.role.list) - list(@Query() q: PageQuery) { - return this.service.paginate(q.page, q.pageSize); + list(@Query() q: ListRoleQuery) { + return this.service.listRoles(q); } @Get(':id') diff --git a/src/roles/roles.service.ts b/src/roles/roles.service.ts index e289bfb..fdbcde1 100644 --- a/src/roles/roles.service.ts +++ b/src/roles/roles.service.ts @@ -3,7 +3,7 @@ import { BaseCrudService } from '../common/base-crud.service.js'; import { PrismaService } from '../prisma/prisma.service.js'; import { RedisService } from '../common/redis/redis.service.js'; import { getRequestContext } from '../common/context/request-context.js'; -import { AssignResourcesDto, CreateRoleDto, UpdateRoleDto } from './dto.js'; +import { AssignResourcesDto, CreateRoleDto, ListRoleQuery, UpdateRoleDto } from './dto.js'; @Injectable() export class RolesService extends BaseCrudService { @@ -22,6 +22,14 @@ export class RolesService extends BaseCrudService { return this.update(id, { ...dto }); } + listRoles(q: ListRoleQuery) { + const where: Record = {}; + if (q.name) where.name = { contains: q.name }; + if (q.code) where.code = { contains: q.code }; + if (q.status) where.status = q.status; + return this.paginate(q.page, q.pageSize, where); + } + async assignedResources(roleCode: string) { const ctx = getRequestContext()!; const rows = await this.prisma.client.roleResource.findMany({