feat: 操作日志
This commit is contained in:
134
src/pages/system/log/operate/config.tsx
Normal file
134
src/pages/system/log/operate/config.tsx
Normal file
@@ -0,0 +1,134 @@
|
||||
import {
|
||||
type ProColumns,
|
||||
type ProDescriptionsItemProps,
|
||||
ProFormColumnsType,
|
||||
} from '@ant-design/pro-components';
|
||||
import { DescriptionsProps } from 'antd';
|
||||
import dayjs from 'dayjs';
|
||||
import type { OperateLogVO } from '@/services/system/log/operate';
|
||||
export const baseTenantColumns: ProColumns<OperateLogVO>[] = [
|
||||
{
|
||||
title: '日志编号',
|
||||
dataIndex: 'id',
|
||||
tip: '日志编号',
|
||||
width: 100,
|
||||
hideInSearch: true, // 在搜索表单中隐藏
|
||||
},
|
||||
{
|
||||
title: '操作人',
|
||||
dataIndex: 'userName',
|
||||
tip: '操作人', // 提示信息
|
||||
},
|
||||
{
|
||||
title: '操作模块',
|
||||
dataIndex: 'type',
|
||||
},
|
||||
{
|
||||
title: '操作名',
|
||||
dataIndex: 'subType',
|
||||
},
|
||||
{
|
||||
title: '操作内容',
|
||||
dataIndex: 'action',
|
||||
},
|
||||
|
||||
{
|
||||
title: '操作时间',
|
||||
dataIndex: 'createTime',
|
||||
valueType: 'dateRange',
|
||||
search: {
|
||||
transform: (value) => {
|
||||
return {
|
||||
[`createTime[0]`]: dayjs(value[0])
|
||||
.startOf('day')
|
||||
.format('YYYY-MM-DD HH:mm:ss'),
|
||||
[`createTime[1]`]: dayjs(value[1])
|
||||
.endOf('day')
|
||||
.format('YYYY-MM-DD HH:mm:ss'),
|
||||
};
|
||||
},
|
||||
},
|
||||
render: (_, record: OperateLogVO) =>
|
||||
dayjs(record.createTime).format('YYYY-MM-DD HH:mm:ss'),
|
||||
},
|
||||
{
|
||||
title: '业务编号',
|
||||
dataIndex: 'bizId',
|
||||
},
|
||||
{
|
||||
title: '操作 IP',
|
||||
dataIndex: 'userIp',
|
||||
hideInSearch: true,
|
||||
},
|
||||
];
|
||||
|
||||
export const descriptionsColumns = (): ProDescriptionsItemProps<
|
||||
Record<string, any>,
|
||||
'text'
|
||||
>[] => [
|
||||
{
|
||||
title: '日志主键',
|
||||
key: 'id',
|
||||
dataIndex: 'id',
|
||||
},
|
||||
{
|
||||
title: '链路追踪',
|
||||
key: 'traceId',
|
||||
dataIndex: 'traceId',
|
||||
},
|
||||
{
|
||||
title: '操作人编号',
|
||||
key: 'userId',
|
||||
dataIndex: 'userId',
|
||||
},
|
||||
{
|
||||
title: '操作人名字',
|
||||
key: 'userName',
|
||||
dataIndex: 'userName',
|
||||
},
|
||||
{
|
||||
title: '操作人 IP',
|
||||
key: 'userIp',
|
||||
dataIndex: 'userIp',
|
||||
},
|
||||
{
|
||||
title: '操作人 UA',
|
||||
key: 'userAgent',
|
||||
dataIndex: 'userAgent',
|
||||
},
|
||||
{
|
||||
title: '操作模块',
|
||||
key: 'type',
|
||||
dataIndex: 'type',
|
||||
},
|
||||
{
|
||||
title: '操作名',
|
||||
key: 'subType',
|
||||
dataIndex: 'subType',
|
||||
},
|
||||
{
|
||||
title: '操作内容',
|
||||
key: 'action',
|
||||
dataIndex: 'action',
|
||||
},
|
||||
{
|
||||
title: '操作拓展参数',
|
||||
key: 'extra',
|
||||
dataIndex: 'extra',
|
||||
},
|
||||
{
|
||||
title: '请求 URL',
|
||||
key: 'requestUrl',
|
||||
dataIndex: 'requestUrl',
|
||||
},
|
||||
{
|
||||
title: '操作时间',
|
||||
key: 'createTime',
|
||||
dataIndex: 'createTime',
|
||||
},
|
||||
{
|
||||
title: '业务编号',
|
||||
key: 'bizId',
|
||||
dataIndex: 'bizId',
|
||||
},
|
||||
];
|
||||
@@ -1,5 +1,70 @@
|
||||
import type { ActionType, ProColumns } from '@ant-design/pro-components';
|
||||
import React, { useRef } from 'react';
|
||||
import EnhancedProTable from '@/components/EnhancedProTable';
|
||||
import ModalDescriptions, {
|
||||
type DescriptionsFormRef,
|
||||
} from '@/components/ModalDescriptions';
|
||||
import {
|
||||
getOperateLogPage,
|
||||
type OperateLogVO,
|
||||
} from '@/services/system/log/operate';
|
||||
import { baseTenantColumns, descriptionsColumns } from './config';
|
||||
|
||||
const SyStemLogOperate = () => {
|
||||
return <>SyStemLogOperate</>;
|
||||
const tableRef = useRef<ActionType>(null);
|
||||
const descriptionsRef = useRef<DescriptionsFormRef>(null);
|
||||
const onFetch = async (
|
||||
params: OperateLogVO & {
|
||||
pageSize?: number;
|
||||
current?: number;
|
||||
},
|
||||
) => {
|
||||
const data = await getOperateLogPage({
|
||||
...params,
|
||||
pageNo: params.current,
|
||||
pageSize: params.pageSize,
|
||||
});
|
||||
return {
|
||||
data: data.list,
|
||||
success: true,
|
||||
total: data.total,
|
||||
};
|
||||
};
|
||||
|
||||
const handleDetail = (record: OperateLogVO) => {
|
||||
descriptionsRef.current?.open(record);
|
||||
};
|
||||
|
||||
const actionColumns: ProColumns<OperateLogVO> = {
|
||||
title: '操作',
|
||||
dataIndex: 'option',
|
||||
valueType: 'option',
|
||||
fixed: 'right',
|
||||
width: 80,
|
||||
render: (text: React.ReactNode, record: OperateLogVO) => [
|
||||
<a key="editable" onClick={() => handleDetail(record)}>
|
||||
详情
|
||||
</a>,
|
||||
],
|
||||
};
|
||||
const columns = [...baseTenantColumns, actionColumns];
|
||||
return (
|
||||
<>
|
||||
<EnhancedProTable<OperateLogVO>
|
||||
ref={tableRef}
|
||||
columns={columns}
|
||||
request={onFetch}
|
||||
headerTitle="操作日志"
|
||||
showIndex={false}
|
||||
showSelection={false}
|
||||
/>
|
||||
<ModalDescriptions
|
||||
ref={descriptionsRef}
|
||||
title="操作日志详情"
|
||||
columns={descriptionsColumns()}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SyStemLogOperate;
|
||||
export default React.memo(SyStemLogOperate);
|
||||
|
||||
@@ -1,33 +1,37 @@
|
||||
import { type TenantVO, deleteTenant } from "@/services/system/tenant/list";
|
||||
import { ProColumns, ProFormColumnsType } from "@ant-design/pro-components";
|
||||
import { DatePicker, Modal, Popconfirm } from "antd";
|
||||
import { FormInstance } from "antd/lib";
|
||||
import dayjs from "dayjs";
|
||||
import type {
|
||||
ProColumns,
|
||||
ProFormColumnsType,
|
||||
} from '@ant-design/pro-components';
|
||||
import { DatePicker, Modal, Popconfirm } from 'antd';
|
||||
import { FormInstance } from 'antd/lib';
|
||||
import dayjs from 'dayjs';
|
||||
import { deleteTenant, type TenantVO } from '@/services/system/tenant/list';
|
||||
import { getTenantPackageList } from '@/services/system/tenant/package';
|
||||
|
||||
export const baseTenantColumns: ProColumns<TenantVO>[] = [
|
||||
{
|
||||
title: "租户编号",
|
||||
dataIndex: "id",
|
||||
tip: "租户编号",
|
||||
title: '租户编号',
|
||||
dataIndex: 'id',
|
||||
tip: '租户编号',
|
||||
width: 100,
|
||||
hideInSearch: true, // 在搜索表单中隐藏
|
||||
},
|
||||
{
|
||||
title: "租户名",
|
||||
dataIndex: "name",
|
||||
tip: "租户名", // 提示信息
|
||||
title: '租户名',
|
||||
dataIndex: 'name',
|
||||
tip: '租户名', // 提示信息
|
||||
},
|
||||
{
|
||||
title: "租户套餐",
|
||||
dataIndex: "packageId",
|
||||
valueType: "select",
|
||||
title: '租户套餐',
|
||||
dataIndex: 'packageId',
|
||||
valueType: 'select',
|
||||
hideInSearch: true, // 在搜索表单中隐藏
|
||||
request: async () => {
|
||||
return [
|
||||
{
|
||||
label: "默认套餐",
|
||||
value: 1,
|
||||
},
|
||||
];
|
||||
const packageList: { id: number; name: string }[] =
|
||||
await getTenantPackageList();
|
||||
console.log(packageList);
|
||||
packageList.map((item) => ({ label: item.name, value: item.id }));
|
||||
return packageList.map((item) => ({ label: item.name, value: item.id }));
|
||||
},
|
||||
// valueEnum: {
|
||||
// all: { text: "全部", status: "Default" },
|
||||
@@ -36,60 +40,67 @@ export const baseTenantColumns: ProColumns<TenantVO>[] = [
|
||||
// },
|
||||
},
|
||||
{
|
||||
title: "联系人",
|
||||
dataIndex: "contactName",
|
||||
title: '联系人',
|
||||
dataIndex: 'contactName',
|
||||
},
|
||||
{
|
||||
title: "联系手机",
|
||||
dataIndex: "contactMobile",
|
||||
title: '联系手机',
|
||||
dataIndex: 'contactMobile',
|
||||
},
|
||||
{
|
||||
title: "账号额度",
|
||||
dataIndex: "accountCount",
|
||||
title: '账号额度',
|
||||
dataIndex: 'accountCount',
|
||||
hideInSearch: true, // 在搜索表单中隐藏
|
||||
},
|
||||
{
|
||||
title: "过期时间",
|
||||
dataIndex: "expireTime",
|
||||
valueType: "dateTime",
|
||||
title: '过期时间',
|
||||
dataIndex: 'expireTime',
|
||||
valueType: 'dateTime',
|
||||
|
||||
hideInSearch: true, // 在搜索表单中隐藏
|
||||
},
|
||||
{ title: "绑定域名", dataIndex: "website", width: 100 },
|
||||
{ title: '绑定域名', dataIndex: 'website', width: 100, hideInSearch: true },
|
||||
{
|
||||
title: "租户状态",
|
||||
dataIndex: "status",
|
||||
valueType: "select",
|
||||
valueEnum: {
|
||||
all: { text: "全部", status: "Default" },
|
||||
open: { text: "未解决", status: "Error" },
|
||||
closed: { text: "已解决", status: "Success" },
|
||||
title: '租户状态',
|
||||
dataIndex: 'status',
|
||||
valueType: 'select',
|
||||
fieldProps: {
|
||||
options: [
|
||||
{
|
||||
label: '开启',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
label: '关闭',
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "创建时间",
|
||||
dataIndex: "createTime",
|
||||
valueType: "dateRange",
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
valueType: 'dateRange',
|
||||
search: {
|
||||
transform: (value) => {
|
||||
return [`${value[0]} 00:00:00`, `${value[1]} 00:00:00`];
|
||||
},
|
||||
},
|
||||
render: (_, record: TenantVO) =>
|
||||
dayjs(record.createTime).format("YYYY-MM-DD HH:mm:ss"),
|
||||
dayjs(record.createTime).format('YYYY-MM-DD HH:mm:ss'),
|
||||
},
|
||||
];
|
||||
|
||||
export const formColumns = (type: string): ProFormColumnsType[] => [
|
||||
{
|
||||
title: "租户名",
|
||||
dataIndex: "name",
|
||||
tip: "租户名", // 提示信息
|
||||
title: '租户名',
|
||||
dataIndex: 'name',
|
||||
tip: '租户名', // 提示信息
|
||||
formItemProps: {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入用户名",
|
||||
message: '请输入用户名',
|
||||
},
|
||||
// {
|
||||
// min: 2,
|
||||
@@ -100,121 +111,121 @@ export const formColumns = (type: string): ProFormColumnsType[] => [
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "租户套餐",
|
||||
dataIndex: "packageId",
|
||||
valueType: "select",
|
||||
title: '租户套餐',
|
||||
dataIndex: 'packageId',
|
||||
valueType: 'select',
|
||||
formItemProps: {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: "请选择租户套餐",
|
||||
message: '请选择租户套餐',
|
||||
},
|
||||
],
|
||||
},
|
||||
fieldProps: {
|
||||
placeholder: "请选择套餐类型",
|
||||
placeholder: '请选择套餐类型',
|
||||
options: [
|
||||
{
|
||||
label: "普通套餐",
|
||||
label: '普通套餐',
|
||||
value: 111,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "联系人",
|
||||
dataIndex: "contactName",
|
||||
title: '联系人',
|
||||
dataIndex: 'contactName',
|
||||
},
|
||||
{
|
||||
title: "联系手机",
|
||||
dataIndex: "contactMobile",
|
||||
title: '联系手机',
|
||||
dataIndex: 'contactMobile',
|
||||
formItemProps: {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入联系手机",
|
||||
message: '请输入联系手机',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "用户名称",
|
||||
dataIndex: "username",
|
||||
hideInForm: type === "update",
|
||||
title: '用户名称',
|
||||
dataIndex: 'username',
|
||||
hideInForm: type === 'update',
|
||||
formItemProps: {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入用户名称",
|
||||
message: '请输入用户名称',
|
||||
},
|
||||
{
|
||||
pattern: /^[a-zA-Z0-9]+$/,
|
||||
message: "用户账号由 0-9、a-z、A-Z 组成",
|
||||
message: '用户账号由 0-9、a-z、A-Z 组成',
|
||||
},
|
||||
// 用户账号由 数字、字母组成
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "用户密码",
|
||||
dataIndex: "password",
|
||||
valueType: "password",
|
||||
hideInForm: type === "update",
|
||||
title: '用户密码',
|
||||
dataIndex: 'password',
|
||||
valueType: 'password',
|
||||
hideInForm: type === 'update',
|
||||
fieldProps: {
|
||||
placeholder: "请输入用户密码",
|
||||
autoComplete: "new-password",
|
||||
placeholder: '请输入用户密码',
|
||||
autoComplete: 'new-password',
|
||||
},
|
||||
formItemProps: {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入用户密码",
|
||||
message: '请输入用户密码',
|
||||
},
|
||||
{
|
||||
min: 4,
|
||||
max: 16,
|
||||
message: "密码长度为4-16个字符",
|
||||
message: '密码长度为4-16个字符',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "账号额度",
|
||||
dataIndex: "accountCount",
|
||||
valueType: "digit",
|
||||
title: '账号额度',
|
||||
dataIndex: 'accountCount',
|
||||
valueType: 'digit',
|
||||
},
|
||||
{
|
||||
title: "过期时间",
|
||||
dataIndex: "expireTime",
|
||||
valueType: "date",
|
||||
title: '过期时间',
|
||||
dataIndex: 'expireTime',
|
||||
valueType: 'date',
|
||||
|
||||
fieldProps: {
|
||||
placeholder: "请选择过期时间",
|
||||
format: "YYYY-MM-DD",
|
||||
placeholder: '请选择过期时间',
|
||||
format: 'YYYY-MM-DD',
|
||||
},
|
||||
},
|
||||
{ title: "绑定域名", dataIndex: "website" },
|
||||
{ title: '绑定域名', dataIndex: 'website' },
|
||||
{
|
||||
title: "租户状态",
|
||||
dataIndex: "status",
|
||||
valueType: "radio",
|
||||
title: '租户状态',
|
||||
dataIndex: 'status',
|
||||
valueType: 'radio',
|
||||
formItemProps: {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: "请选择租户状态",
|
||||
message: '请选择租户状态',
|
||||
},
|
||||
],
|
||||
},
|
||||
fieldProps: {
|
||||
placeholder: "请选择套餐类型",
|
||||
placeholder: '请选择套餐类型',
|
||||
options: [
|
||||
{
|
||||
label: "启用",
|
||||
label: '启用',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: "禁用",
|
||||
label: '禁用',
|
||||
value: 0,
|
||||
},
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user