import { Provide } from '@midwayjs/core'; import { BaseService } from '@cool-midway/core'; import { InjectEntityModel } from '@midwayjs/typeorm'; import { Repository } from 'typeorm'; import { BaseAuditLogEntity } from '../entity/audit'; export interface AuditRecordDTO { module: string; action: string; operatorId?: number | null; operatorName?: string | null; ip?: string | null; detail?: string | null; status?: number; } export interface AuditQueryDTO { module?: string; action?: string; status?: number; keyWord?: string; startDate?: string; endDate?: string; page?: number; size?: number; } export interface AuditPaginationResult { list: BaseAuditLogEntity[]; total: number; page: number; size: number; } /** * 安全审计日志服务 */ @Provide() export class BaseAuditLogService extends BaseService { @InjectEntityModel(BaseAuditLogEntity) baseAuditLogEntity: Repository; /** * 自动落库记录一条安全审计日志 */ async record(dto: AuditRecordDTO): Promise { const log = new BaseAuditLogEntity(); log.module = dto.module; log.action = dto.action; log.operatorId = dto.operatorId ?? null; log.operatorName = dto.operatorName ?? null; log.ip = dto.ip ?? null; log.detail = dto.detail ?? null; log.status = dto.status !== undefined ? Number(dto.status) : 1; return await this.baseAuditLogEntity.save(log); } /** * 多条件组合过滤与分页检索 */ async filterLogs(query: AuditQueryDTO): Promise { const page = Math.max(1, Number(query.page) || 1); const size = Math.max(1, Number(query.size) || 20); const skip = (page - 1) * size; // 构建过滤条件 const where: Record = {}; if (query.module) { where.module = query.module; } if (query.action) { where.action = query.action; } if (query.status !== undefined && query.status !== null) { where.status = Number(query.status); } const [allList, total] = await this.baseAuditLogEntity.findAndCount({ where: Object.keys(where).length > 0 ? where : undefined, order: { createTime: 'DESC' }, }); let resultList = allList; // 关键字模糊匹配 (operatorName, action, ip, module) if (query.keyWord) { const kw = query.keyWord.toLowerCase(); resultList = resultList.filter((item) => { return ( (item.operatorName && item.operatorName.toLowerCase().includes(kw)) || (item.action && item.action.toLowerCase().includes(kw)) || (item.module && item.module.toLowerCase().includes(kw)) || (item.ip && item.ip.toLowerCase().includes(kw)) ); }); } const finalTotal = query.keyWord ? resultList.length : total; const paginatedList = resultList.slice(skip, skip + size); return { list: paginatedList, total: finalTotal, page, size, }; } }