Nuxt3 全栈作品【通用信息管理系统】操作日志

发布于:2025-08-04 ⋅ 阅读:(9) ⋅ 点赞:(0)

最终效果

在这里插入图片描述

前端代码

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);

网站公告

今日签到

点亮在社区的每一天
去签到