199 lines
5.5 KiB
TypeScript
199 lines
5.5 KiB
TypeScript
/**
|
|
* 操作记录页面
|
|
* 与 GVA sysOperationRecord.vue 保持一致的功能
|
|
*/
|
|
import { DeleteOutlined, SearchOutlined, ReloadOutlined } from '@ant-design/icons';
|
|
import { PageContainer, ProTable } from '@ant-design/pro-components';
|
|
import type { ProColumns, ActionType } from '@ant-design/pro-components';
|
|
import { Button, message, Popconfirm, Space, Tag, Popover, Typography } from 'antd';
|
|
import { useRef, useState } from 'react';
|
|
import {
|
|
getSysOperationRecordList,
|
|
deleteSysOperationRecord,
|
|
deleteSysOperationRecordByIds,
|
|
} from '@/services/system/operationRecord';
|
|
import dayjs from 'dayjs';
|
|
|
|
const { Text } = Typography;
|
|
|
|
const OperationRecordPage: React.FC = () => {
|
|
const actionRef = useRef<ActionType>();
|
|
const [selectedRowKeys, setSelectedRowKeys] = useState<number[]>([]);
|
|
|
|
// 格式化JSON显示
|
|
const formatBody = (value: string) => {
|
|
try {
|
|
return JSON.stringify(JSON.parse(value), null, 2);
|
|
} catch {
|
|
return value;
|
|
}
|
|
};
|
|
|
|
// 删除单条记录
|
|
const handleDelete = async (id: number) => {
|
|
const res = await deleteSysOperationRecord({ ID: id });
|
|
if (res.code === 0) {
|
|
message.success('删除成功');
|
|
actionRef.current?.reload();
|
|
}
|
|
};
|
|
|
|
// 批量删除
|
|
const handleBatchDelete = async () => {
|
|
if (selectedRowKeys.length === 0) {
|
|
message.warning('请选择要删除的记录');
|
|
return;
|
|
}
|
|
const res = await deleteSysOperationRecordByIds({ ids: selectedRowKeys });
|
|
if (res.code === 0) {
|
|
message.success('删除成功');
|
|
setSelectedRowKeys([]);
|
|
actionRef.current?.reload();
|
|
}
|
|
};
|
|
|
|
const columns: ProColumns<API.OperationRecord>[] = [
|
|
{
|
|
title: '操作人',
|
|
dataIndex: ['user', 'userName'],
|
|
width: 140,
|
|
search: false,
|
|
render: (_, record) => (
|
|
<span>{record.user?.userName}({record.user?.nickName})</span>
|
|
),
|
|
},
|
|
{
|
|
title: '日期',
|
|
dataIndex: 'CreatedAt',
|
|
width: 180,
|
|
search: false,
|
|
render: (_, record) => dayjs(record.CreatedAt).format('YYYY-MM-DD HH:mm:ss'),
|
|
},
|
|
{
|
|
title: '状态码',
|
|
dataIndex: 'status',
|
|
width: 100,
|
|
render: (_, record) => <Tag color="success">{record.status}</Tag>,
|
|
},
|
|
{
|
|
title: '请求IP',
|
|
dataIndex: 'ip',
|
|
width: 120,
|
|
search: false,
|
|
},
|
|
{
|
|
title: '请求方法',
|
|
dataIndex: 'method',
|
|
width: 100,
|
|
},
|
|
{
|
|
title: '请求路径',
|
|
dataIndex: 'path',
|
|
width: 240,
|
|
ellipsis: true,
|
|
},
|
|
{
|
|
title: '请求',
|
|
dataIndex: 'body',
|
|
width: 80,
|
|
search: false,
|
|
render: (_, record) => (
|
|
record.body ? (
|
|
<Popover
|
|
content={
|
|
<div style={{ maxHeight: 400, maxWidth: 400, overflow: 'auto', background: '#112435', padding: 12, borderRadius: 4 }}>
|
|
<pre style={{ color: '#f08047', margin: 0, fontSize: 12 }}>{formatBody(record.body)}</pre>
|
|
</div>
|
|
}
|
|
trigger="click"
|
|
>
|
|
<Button type="link" size="small">查看</Button>
|
|
</Popover>
|
|
) : <Text type="secondary">无</Text>
|
|
),
|
|
},
|
|
{
|
|
title: '响应',
|
|
dataIndex: 'resp',
|
|
width: 80,
|
|
search: false,
|
|
render: (_, record) => (
|
|
record.resp ? (
|
|
<Popover
|
|
content={
|
|
<div style={{ maxHeight: 400, maxWidth: 400, overflow: 'auto', background: '#112435', padding: 12, borderRadius: 4 }}>
|
|
<pre style={{ color: '#f08047', margin: 0, fontSize: 12 }}>{formatBody(record.resp)}</pre>
|
|
</div>
|
|
}
|
|
trigger="click"
|
|
>
|
|
<Button type="link" size="small">查看</Button>
|
|
</Popover>
|
|
) : <Text type="secondary">无</Text>
|
|
),
|
|
},
|
|
{
|
|
title: '操作',
|
|
valueType: 'option',
|
|
width: 100,
|
|
render: (_, record) => (
|
|
<Popconfirm title="确定删除?" onConfirm={() => handleDelete(record.ID!)}>
|
|
<Button type="link" danger icon={<DeleteOutlined />}>删除</Button>
|
|
</Popconfirm>
|
|
),
|
|
},
|
|
];
|
|
|
|
return (
|
|
<PageContainer>
|
|
<ProTable<API.OperationRecord>
|
|
headerTitle="操作记录"
|
|
actionRef={actionRef}
|
|
rowKey="ID"
|
|
columns={columns}
|
|
rowSelection={{
|
|
selectedRowKeys,
|
|
onChange: (keys) => setSelectedRowKeys(keys as number[]),
|
|
}}
|
|
toolBarRender={() => [
|
|
<Popconfirm
|
|
key="batchDelete"
|
|
title="确定删除选中的记录?"
|
|
onConfirm={handleBatchDelete}
|
|
disabled={selectedRowKeys.length === 0}
|
|
>
|
|
<Button
|
|
danger
|
|
icon={<DeleteOutlined />}
|
|
disabled={selectedRowKeys.length === 0}
|
|
>
|
|
批量删除
|
|
</Button>
|
|
</Popconfirm>,
|
|
]}
|
|
request={async (params) => {
|
|
const res = await getSysOperationRecordList({
|
|
page: params.current,
|
|
pageSize: params.pageSize,
|
|
method: params.method,
|
|
path: params.path,
|
|
status: params.status ? Number(params.status) : undefined,
|
|
});
|
|
return {
|
|
data: res.data?.list || [],
|
|
total: res.data?.total || 0,
|
|
success: res.code === 0,
|
|
};
|
|
}}
|
|
pagination={{
|
|
defaultPageSize: 10,
|
|
showSizeChanger: true,
|
|
pageSizeOptions: ['10', '30', '50', '100'],
|
|
}}
|
|
/>
|
|
</PageContainer>
|
|
);
|
|
};
|
|
|
|
export default OperationRecordPage;
|