chore: audit log first

This commit is contained in:
xiaojunnuo
2026-07-10 19:24:42 +08:00
parent edda1b57f3
commit 4250d0e266
33 changed files with 1396 additions and 77 deletions
@@ -19,6 +19,7 @@ import sysauthority from "./certd/sys-authority";
import syscname from "./certd/sys-cname";
import tutorial from "./certd/tutorial";
import cron from "./certd/cron";
import audit from "./certd/audit";
// Note: @ is reserved in locale messages; use {'@'} when needed.
export default {
@@ -43,4 +44,5 @@ export default {
...syscname,
...tutorial,
...cron,
...audit,
};
@@ -0,0 +1,4 @@
export default {
"certd.auditLog": "Audit Log",
"certd.sysResources.auditLog": "Audit Log",
};
@@ -19,6 +19,7 @@ import sysauthority from "./certd/sys-authority";
import syscname from "./certd/sys-cname";
import tutorial from "./certd/tutorial";
import cron from "./certd/cron";
import audit from "./certd/audit";
// Note: @ is reserved in locale messages; use {'@'} when needed.
export default {
@@ -43,4 +44,5 @@ export default {
...syscname,
...tutorial,
...cron,
...audit,
};
@@ -0,0 +1,4 @@
export default {
"certd.auditLog": "操作日志",
"certd.sysResources.auditLog": "操作日志",
};
@@ -287,6 +287,17 @@ export const certdResources = [
isMenu: true,
},
},
{
title: "certd.auditLog",
name: "AuditLog",
path: "/certd/audit",
component: "/certd/audit/index.vue",
meta: {
icon: "ion:document-text-outline",
auth: true,
keepAlive: true,
},
},
{
title: "certd.userSecurity",
name: "UserSecurity",
@@ -410,6 +410,18 @@ export const sysResources = [
},
],
},
{
title: "certd.sysResources.auditLog",
name: "SysAuditLog",
path: "/sys/audit",
component: "/sys/audit/index.vue",
meta: {
icon: "ion:document-text-outline",
permission: "sys:settings:view",
keepAlive: true,
auth: true,
},
},
{
title: "certd.sysResources.netTest",
name: "NetTest",
@@ -0,0 +1,28 @@
import { request } from "/src/api/service";
const apiPrefix = "/pi/audit";
export function createAuditApi() {
return {
async GetList(query: any) {
return await request({
url: apiPrefix + "/page",
method: "post",
data: query,
});
},
async DelObj(id: number) {
return await request({
url: apiPrefix + "/delete",
method: "post",
params: { id },
});
},
async GetDict() {
return await request({
url: apiPrefix + "/dict",
method: "post",
});
},
};
}
@@ -0,0 +1,102 @@
import { CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, UserPageQuery, UserPageRes, dict } from "@fast-crud/fast-crud";
const typeDict = dict({
url: "/pi/audit/dict",
getData: async () => {
const { createAuditApi } = await import("./api");
const api = createAuditApi();
const res = await api.GetDict();
return res.types || [];
},
});
const actionDict = dict({
url: "/pi/audit/dict",
getData: async () => {
const { createAuditApi } = await import("./api");
const api = createAuditApi();
const res = await api.GetDict();
return res.actions || [];
},
});
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const api = context.api;
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
};
const delRequest = async (req: DelReq) => {
return await api.DelObj(req.row.id);
};
return {
crudOptions: {
request: { pageRequest, delRequest },
actionbar: {
buttons: {
add: { show: false },
},
},
rowHandle: {
width: 120,
fixed: "right",
buttons: {
view: { show: false },
edit: { show: false },
remove: { show: true },
},
},
columns: {
id: {
title: "ID",
type: "number",
column: { width: 80 },
form: { show: false },
},
createTime: {
title: "操作时间",
type: "datetime",
search: {
show: true,
component: {
name: "a-range-picker",
vModel: ["createTime_start", "createTime_end"],
},
},
column: { width: 170, sorter: true },
form: { show: false },
},
type: {
title: "操作类型",
type: "dict-select",
dict: typeDict,
search: { show: true },
column: { width: 120 },
form: { show: false },
},
action: {
title: "操作动作",
type: "dict-select",
dict: actionDict,
search: { show: true },
column: { width: 100 },
form: { show: false },
},
content: {
title: "内容",
type: "text",
search: { show: true },
column: { minWidth: 300 },
form: { show: false },
},
ipAddress: {
title: "IP地址",
type: "text",
column: { width: 140 },
form: { show: false },
},
},
},
};
}
@@ -0,0 +1,24 @@
<template>
<fs-page>
<template #header>
<div class="title">
操作日志
<span class="sub">查看您的操作记录</span>
</div>
</template>
<fs-crud ref="crudRef" v-bind="crudBinding" />
</fs-page>
</template>
<script lang="ts" setup>
import { useFs } from "@fast-crud/fast-crud";
import createCrudOptions from "./crud";
import { createAuditApi } from "./api";
import { useMounted } from "/@/use/use-mounted";
defineOptions({ name: "AuditLog" });
const api = createAuditApi();
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: { api } });
useMounted(() => crudExpose.doRefresh());
</script>
@@ -0,0 +1,35 @@
import { request } from "/src/api/service";
const apiPrefix = "/sys/audit";
export function createSysAuditApi() {
return {
async GetList(query: any) {
return await request({
url: apiPrefix + "/page",
method: "post",
data: query,
});
},
async DelObj(id: number) {
return await request({
url: apiPrefix + "/delete",
method: "post",
params: { id },
});
},
async Clean(retentionDays: number) {
return await request({
url: apiPrefix + "/clean",
method: "post",
data: { retentionDays },
});
},
async GetDict() {
return await request({
url: apiPrefix + "/dict",
method: "post",
});
},
};
}
@@ -0,0 +1,124 @@
import { CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, UserPageQuery, UserPageRes, dict } from "@fast-crud/fast-crud";
const typeDict = dict({
url: "/sys/audit/dict",
getData: async () => {
const { createSysAuditApi } = await import("./api");
const api = createSysAuditApi();
const res = await api.GetDict();
return res.types || [];
},
});
const actionDict = dict({
url: "/sys/audit/dict",
getData: async () => {
const { createSysAuditApi } = await import("./api");
const api = createSysAuditApi();
const res = await api.GetDict();
return res.actions || [];
},
});
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const api = context.api;
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
};
const delRequest = async (req: DelReq) => {
return await api.DelObj(req.row.id);
};
const cleanExpired = async () => {
await api.Clean(90);
crudExpose.doRefresh();
};
return {
crudOptions: {
request: { pageRequest, delRequest },
actionbar: {
buttons: {
add: { show: false },
clean: {
text: "清理过期日志(90天)",
type: "default",
click: cleanExpired,
},
},
},
rowHandle: {
width: 120,
fixed: "right",
buttons: {
view: { show: false },
edit: { show: false },
remove: { show: true },
},
},
search: {
initialForm: {
sort: { prop: "id", asc: false },
},
},
columns: {
id: {
title: "ID",
type: "number",
column: { width: 80 },
form: { show: false },
},
createTime: {
title: "操作时间",
type: "datetime",
search: {
show: true,
component: {
name: "a-range-picker",
vModel: ["createTime_start", "createTime_end"],
},
},
column: { width: 170, sorter: true },
form: { show: false },
},
userName: {
title: "操作人",
type: "text",
search: { show: true },
column: { width: 120 },
form: { show: false },
},
type: {
title: "操作类型",
type: "dict-select",
dict: typeDict,
search: { show: true },
column: { width: 120 },
form: { show: false },
},
action: {
title: "操作动作",
type: "dict-select",
dict: actionDict,
search: { show: true },
column: { width: 100 },
form: { show: false },
},
content: {
title: "内容",
type: "text",
search: { show: true },
column: { minWidth: 300 },
form: { show: false },
},
ipAddress: {
title: "IP地址",
type: "text",
column: { width: 140 },
form: { show: false },
},
},
},
};
}
@@ -0,0 +1,24 @@
<template>
<fs-page>
<template #header>
<div class="title">
操作日志
<span class="sub">查看所有用户的操作记录</span>
</div>
</template>
<fs-crud ref="crudRef" v-bind="crudBinding" />
</fs-page>
</template>
<script lang="ts" setup>
import { useFs } from "@fast-crud/fast-crud";
import createCrudOptions from "./crud";
import { createSysAuditApi } from "./api";
import { useMounted } from "/@/use/use-mounted";
defineOptions({ name: "SysAuditLog" });
const api = createSysAuditApi();
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: { api } });
useMounted(() => crudExpose.doRefresh());
</script>