134 lines
4.4 KiB
TypeScript
134 lines
4.4 KiB
TypeScript
import { Injectable } from "@nestjs/common";
|
|
import { BaseService } from "../base/base.service";
|
|
import { db, ObjectType, Prisma } from "@nice/common";
|
|
import EventBus, { CrudOperation } from "@server/utils/event-bus";
|
|
|
|
@Injectable()
|
|
export class SystemLogService extends BaseService<Prisma.SystemLogDelegate> {
|
|
protected readonly prismaClient: any;
|
|
|
|
constructor() {
|
|
super(db, ObjectType.SYSTEM_LOG, false);
|
|
this.prismaClient = db;
|
|
}
|
|
|
|
async create(args: Prisma.SystemLogCreateArgs) {
|
|
// 确保消息字段有值
|
|
if (args.data && typeof args.data === 'object') {
|
|
const { level, module, action, targetName } = args.data as any;
|
|
const timestamp = new Date().toLocaleString();
|
|
const messagePrefix = level === 'error' ? '错误' : '';
|
|
|
|
// 添加默认消息格式 - 确保 message 字段存在
|
|
if (!args.data.message) {
|
|
args.data.message = `[${timestamp}] ${messagePrefix}${module || ''} ${action || ''}: ${targetName || ''}`;
|
|
}
|
|
}
|
|
|
|
const result = await super.create(args);
|
|
this.emitDataChanged(CrudOperation.CREATED, result);
|
|
return result;
|
|
}
|
|
|
|
async findMany(args: Prisma.SystemLogFindManyArgs): Promise<Prisma.SystemLogGetPayload<{}>[]> {
|
|
return super.findMany(args); // 放弃分页结构
|
|
}
|
|
|
|
async findManyWithPagination({ page = 1, pageSize = 20, where = {}, ...rest }: any) {
|
|
const skip = (page - 1) * pageSize;
|
|
|
|
try {
|
|
const [items, total] = await Promise.all([
|
|
this.prismaClient.systemLog.findMany({
|
|
where,
|
|
skip,
|
|
take: pageSize,
|
|
orderBy: { timestamp: 'desc' },
|
|
...rest
|
|
}),
|
|
this.prismaClient.systemLog.count({ where })
|
|
]);
|
|
|
|
return {
|
|
items,
|
|
total,
|
|
page,
|
|
pageSize,
|
|
totalPages: Math.ceil(total / pageSize)
|
|
};
|
|
} catch (error) {
|
|
console.error('Error in findManyWithPagination:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async logStaffAction(
|
|
action: string,
|
|
operatorId: string | null,
|
|
ipAddress: string | null,
|
|
targetId: string,
|
|
targetName: string,
|
|
beforeData: any = null,
|
|
afterData: any = null,
|
|
status: 'success' | 'failure' = 'success',
|
|
errorMessage?: string
|
|
) {
|
|
// 生成变更详情
|
|
const details = beforeData && afterData
|
|
? this.generateChangeDetails(beforeData, afterData)
|
|
: {};
|
|
|
|
const timestamp = new Date().toLocaleString();
|
|
const messagePrefix = status === 'success' ? '' : '错误: ';
|
|
const message = `[${timestamp}] ${messagePrefix}用户 ${targetName} 的${action}`;
|
|
|
|
return this.create({
|
|
data: {
|
|
level: status === 'success' ? 'info' : 'error',
|
|
module: '人员管理',
|
|
action,
|
|
operatorId,
|
|
ipAddress,
|
|
targetId,
|
|
targetType: 'staff',
|
|
targetName,
|
|
message,
|
|
details,
|
|
beforeData,
|
|
afterData,
|
|
status,
|
|
errorMessage,
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 生成变更详情
|
|
*/
|
|
private generateChangeDetails(before: any, after: any) {
|
|
if (!before || !after) return {};
|
|
|
|
const changes: Record<string, { oldValue: any; newValue: any }> = {};
|
|
|
|
Object.keys(after).forEach(key => {
|
|
// 忽略一些不需要记录的字段
|
|
if (['password', 'createdAt', 'updatedAt', 'deletedAt'].includes(key)) return;
|
|
|
|
if (JSON.stringify(before[key]) !== JSON.stringify(after[key])) {
|
|
changes[key] = {
|
|
oldValue: before[key],
|
|
newValue: after[key]
|
|
};
|
|
}
|
|
});
|
|
return { changes };
|
|
}
|
|
|
|
private emitDataChanged(operation: CrudOperation, data: any) {
|
|
EventBus.emit('dataChanged', {
|
|
type: ObjectType.SYSTEM_LOG,
|
|
operation,
|
|
data,
|
|
});
|
|
}
|
|
} |