最终效果
前端代码
pages/system/log/list.vue
<script lang="ts" setup>
import { Model } from "./model";
const PageConfig = {
//被操作实体的名称
entity: "log",
entityName: "日志",
disAdd: true,
hideHandle: true,
};
</script>
<template>
<S-comMangeInfo :Model="Model" :PageConfig="PageConfig" />
</template>
pages/system/log/model.ts
export const Model: {
[key: string]: any;
} = {
createdAt: {
width: 150,
formHide: "all",
label: "操作时间",
search: true,
type: "dateTimeRange",
},
account: {
label: "操作员账号",
search: true,
},
operator: {
label: "操作员姓名",
search: true,
},
action: {
label: "操作内容",
search: true,
},
};
依赖组件 S-comMangeInfo
https://blog.csdn.net/weixin_41192489/article/details/149768541
接口开发
server/models/log.ts
import { defineMongooseModel } from "#nuxt/mongoose";
export interface LogDataProps {
action: string;
createdAt: string;
operator: string;
account: string;
}
export const LogSchema = defineMongooseModel<LogDataProps>(
"Log",
{
action: { type: String },
operator: { type: String },
account: { type: String },
},
{
timestamps: true,
toJSON: {
// 过滤掉敏感字段
transform(doc: any, ret: Record<string, any>, options: any) {
delete ret.__v;
},
},
}
);
validators/log.ts
import { z } from "zod";
export const logCreateSchema = z.object({
_id: z.string().optional(),
action: z.string(),
operator: z.string().optional(),
account: z.string(),
});
export type LogCreateType = z.infer<typeof logCreateSchema>;
server/api/log/list.ts
import type { SortOrder } from "mongoose";
export default defineEventHandler(async (event) => {
const queryObj = getQuery(event);
const { orderBy = "createdAt", order = "desc" } = queryObj;
const customSort = {
[orderBy as string]: order as SortOrder,
};
const currentPage = Number(queryObj.currentPage) || 1;
const pageSize = Number(queryObj.pageSize) || 10;
const skip = (currentPage - 1) * pageSize;
const findCondition: {
[key: string]: any;
} = {};
if (queryObj.account) {
findCondition.account = {
// 模糊匹配
$regex: queryObj.account,
};
}
if (queryObj.operator) {
findCondition.operator = {
// 模糊匹配
$regex: queryObj.operator,
};
}
if (queryObj.action) {
findCondition.action = {
// 模糊匹配
$regex: queryObj.action,
};
}
if (queryObj.createdAt_start && queryObj.createdAt_end) {
findCondition.createdAt = {
$gte: new Date(queryObj.createdAt_start as string),
$lte: new Date(queryObj.createdAt_end as string),
};
}
const res_list = await LogSchema.find(findCondition)
.select(["action", "operator", "account", "createdAt"])
.skip(skip)
.limit(pageSize)
.sort(customSort)
.lean();
const total = await LogSchema.find(findCondition).countDocuments();
return {
data: res_list,
total,
pageSize,
currentPage,
};
});
server/api/log/add.post.ts
新增日志
import { logCreateSchema } from "~/validators/log";
export default defineEventHandler(async (event) => {
const result = await runValidate(logCreateSchema, event);
const newLog = await LogSchema.create(result.data);
return newLog;
});
记录日志
composables/useLog.ts
export const useLog = (action: string, account?: string, operator?: string) => {
const currentUser = useCurrentUserStore().currentUser;
$fetch("/api/log/add", {
body: {
account: account || currentUser?.account,
operator: operator || currentUser?.name,
action: action,
},
method: "POST",
});
};
如登录成功后,记录日志
// 记录登录日志
useLog("登录", result.account, result.name);