origin/apps/server/src/models/sys-logs/systemLog.router.ts

302 lines
13 KiB
TypeScript
Raw Normal View History

2025-03-26 13:00:55 +08:00
import { Injectable } from "@nestjs/common";
import { TrpcService } from "@server/trpc/trpc.service";
import { SystemLogService } from "./systemLog.service";
import { z, ZodType } from "zod";
import { Prisma } from "@nice/common";
// 定义Zod类型Schema
const SystemLogCreateArgsSchema: ZodType<Prisma.SystemLogCreateArgs> = z.any();
const SystemLogFindManyArgsSchema: ZodType<Prisma.SystemLogFindManyArgs> = z.any();
const SystemLogFindUniqueArgsSchema: ZodType<Prisma.SystemLogFindUniqueArgs> = z.any();
const SystemLogWhereInputSchema: ZodType<Prisma.SystemLogWhereInput> = z.any();
const SystemLogSelectSchema: ZodType<Prisma.SystemLogSelect> = z.any();
@Injectable()
export class SystemLogRouter {
constructor(
private readonly trpc: TrpcService,
private readonly systemLogService: SystemLogService,
) { }
router = this.trpc.router({
// 创建日志
create: this.trpc.procedure
.input(z.object({
level: z.enum(['info', 'warning', 'error', 'debug']).default('info'),
module: z.string(),
action: z.string(),
operatorId: z.string().optional(),
ipAddress: z.string().optional(),
targetId: z.string().optional(),
targetType: z.string().optional(),
targetName: z.string().optional(),
2025-03-27 08:59:53 +08:00
message: z.string().optional(),
2025-03-26 13:00:55 +08:00
details: z.any().optional(),
beforeData: z.any().optional(),
afterData: z.any().optional(),
status: z.enum(['success', 'failure']).default('success'),
errorMessage: z.string().optional(),
departmentId: z.string().optional(),
}))
.mutation(async ({ input, ctx }) => {
const ctxIpAddress = ctx.ip;
const operatorId = ctx.staff?.id;
2025-03-27 08:59:53 +08:00
try {
return this.systemLogService.create({
data: {
level: input.level,
module: input.module,
action: input.action,
operatorId: input.operatorId || operatorId,
ipAddress: input.ipAddress || ctxIpAddress,
targetId: input.targetId,
targetType: input.targetType,
targetName: input.targetName,
message: input.message,
details: input.details,
beforeData: input.beforeData,
afterData: input.afterData,
status: input.status,
errorMessage: input.errorMessage,
departmentId: input.departmentId,
}
});
} catch (error) {
console.error('Error creating system log:', error);
throw new Error('Failed to create system log');
}
2025-03-26 13:00:55 +08:00
}),
// 查询日志列表
findMany: this.trpc.procedure
.input(SystemLogFindManyArgsSchema)
.query(async ({ input }) => {
return this.systemLogService.findMany(input);
}),
// 查询日志列表(带分页) - 保留原名
getLogs: this.trpc.procedure
.input(z.object({
page: z.number().default(1),
pageSize: z.number().default(20),
where: SystemLogWhereInputSchema.optional(),
select: SystemLogSelectSchema.optional(),
}))
.query(async ({ input }) => {
try {
const { page, pageSize, where = {}, select } = input;
return await this.systemLogService.findManyWithPagination({
page,
pageSize,
where,
...(select ? { select } : {})
});
} catch (error) {
console.error('Error in getLogs:', error);
// 返回空结果,避免崩溃
return {
items: [],
total: 0,
page: input.page,
pageSize: input.pageSize,
totalPages: 0
};
}
}),
// 查询日志列表(带分页) - 新名称
findManyWithPagination: this.trpc.procedure
.input(z.object({
page: z.number().default(1),
pageSize: z.number().default(20),
where: SystemLogWhereInputSchema.optional(),
select: SystemLogSelectSchema.optional(),
}))
.query(async ({ input }) => {
try {
const { page, pageSize, where = {}, select } = input;
return await this.systemLogService.findManyWithPagination({
page,
pageSize,
where,
...(select ? { select } : {})
});
} catch (error) {
console.error('Error in findManyWithPagination:', error);
// 返回空结果,避免崩溃
return {
items: [],
total: 0,
page: input.page,
pageSize: input.pageSize,
totalPages: 0
};
}
}),
// 获取单个日志详情
findUnique: this.trpc.procedure
.input(SystemLogFindUniqueArgsSchema)
.query(async ({ input }) => {
return this.systemLogService.findUnique(input);
}),
// 通过ID获取日志详情(简化版)
findById: this.trpc.procedure
.input(z.string())
.query(async ({ input }) => {
return this.systemLogService.findUnique({
where: { id: input },
include: {
operator: {
select: {
id: true,
username: true,
showname: true,
}
},
department: {
select: {
id: true,
name: true,
}
}
}
});
}),
// 记录人员操作日志的便捷方法
logStaffAction: this.trpc.protectProcedure
.input(z.object({
action: z.string(),
targetId: z.string(),
targetName: z.string(),
2025-03-27 08:59:53 +08:00
message: z.string().optional(),
2025-03-26 13:00:55 +08:00
beforeData: z.any().optional(),
afterData: z.any().optional(),
status: z.enum(['success', 'failure']).default('success'),
errorMessage: z.string().optional(),
}))
.mutation(async ({ input, ctx }) => {
const ipAddress = ctx.ip;
const operatorId = ctx.staff?.id;
2025-03-27 08:59:53 +08:00
try {
return this.systemLogService.create({
data: {
level: input.status === 'success' ? 'info' : 'error',
module: 'staff',
action: input.action,
operatorId: operatorId,
ipAddress: ipAddress,
targetId: input.targetId,
targetType: 'staff',
targetName: input.targetName,
message: input.message,
beforeData: input.beforeData,
afterData: input.afterData,
status: input.status,
errorMessage: input.errorMessage,
}
});
} catch (error) {
console.error('Error logging staff action:', error);
throw new Error('Failed to log staff action');
}
}),
// 高级搜索日志
searchLogs: this.trpc.procedure
.input(z.object({
page: z.number().default(1),
pageSize: z.number().default(20),
level: z.enum(['info', 'warning', 'error', 'debug']).optional(),
module: z.string().optional(),
action: z.string().optional(),
operatorId: z.string().optional(),
targetId: z.string().optional(),
targetType: z.string().optional(),
status: z.enum(['success', 'failure']).optional(),
startTime: z.string().optional(),
endTime: z.string().optional(),
keyword: z.string().optional(),
departmentId: z.string().optional(),
}))
.query(async ({ input }) => {
console.log('Received input for searchLogs:', input);
const where: Prisma.SystemLogWhereInput = {};
if (input.level) where.level = input.level;
if (input.module) where.module = input.module;
if (input.action) where.action = input.action;
if (input.operatorId) where.operatorId = input.operatorId;
if (input.targetId) where.targetId = input.targetId;
if (input.targetType) where.targetType = input.targetType;
if (input.status) where.status = input.status;
if (input.departmentId) where.departmentId = input.departmentId;
// 时间范围查询
if (input.startTime || input.endTime) {
where.timestamp = {};
if (input.startTime) where.timestamp.gte = new Date(input.startTime);
if (input.endTime) where.timestamp.lte = new Date(input.endTime);
}
// 关键词搜索
if (input.keyword) {
where.OR = [
{ targetName: { contains: input.keyword } },
{ action: { contains: input.keyword } },
{ module: { contains: input.keyword } },
{ errorMessage: { contains: input.keyword } },
];
}
try {
const result = await this.systemLogService.findManyWithPagination({
page: input.page,
pageSize: input.pageSize,
where,
select: {
id: true,
level: true,
module: true,
action: true,
timestamp: true,
operatorId: true,
ipAddress: true,
targetId: true,
targetType: true,
targetName: true,
details: true,
beforeData: true,
afterData: true,
status: true,
errorMessage: true,
departmentId: true,
operator: {
select: {
id: true,
username: true,
showname: true,
}
},
department: {
select: {
id: true,
name: true,
}
}
}
});
console.log('Search logs result:', result);
return result;
} catch (error) {
console.error('Error in searchLogs:', error);
throw new Error('Failed to search logs');
}
2025-03-26 13:00:55 +08:00
}),
})
}