imeeting/frontend/src/pages/Logs.tsx

172 lines
4.5 KiB
TypeScript
Raw Normal View History

import { Card, Table, Tabs, Tag, Input, Space, Button, DatePicker, Select } from "antd";
import { useEffect, useState } from "react";
import { fetchLogs } from "../api";
import { SearchOutlined, ReloadOutlined } from "@ant-design/icons";
import dayjs from "dayjs";
const { RangePicker } = DatePicker;
export default function Logs() {
const [activeTab, setActiveTab] = useState("OPERATION");
const [loading, setLoading] = useState(false);
const [data, setData] = useState([]);
const [total, setTotal] = useState(0);
const [params, setParams] = useState({
current: 1,
size: 10,
username: "",
status: undefined,
startDate: "",
endDate: ""
});
const loadData = async (currentParams = params) => {
setLoading(true);
try {
const operationType = activeTab === "LOGIN" ? "LOGIN" : "OPERATION";
const result = await fetchLogs({ ...currentParams, operationType });
setData(result.records || []);
setTotal(result.total || 0);
} finally {
setLoading(false);
}
};
useEffect(() => {
loadData();
}, [activeTab, params.current, params.size]);
const handleSearch = () => {
setParams({ ...params, current: 1 });
loadData({ ...params, current: 1 });
};
const handleReset = () => {
const resetParams = {
current: 1,
size: 10,
username: "",
status: undefined,
startDate: "",
endDate: ""
};
setParams(resetParams);
loadData(resetParams);
};
const columns = [
{
title: "用户名",
dataIndex: "username",
key: "username",
width: 120,
render: (text: string) => text || "系统/访客"
},
{
title: activeTab === "LOGIN" ? "登录模块" : "操作模块",
dataIndex: "resourceType",
key: "resourceType",
width: 150
},
{
title: "操作详情",
dataIndex: "detail",
key: "detail",
ellipsis: true
},
{
title: "IP地址",
dataIndex: "ipAddress",
key: "ipAddress",
width: 140
},
{
title: "状态",
dataIndex: "status",
key: "status",
width: 100,
render: (status: number) => (
<Tag color={status === 1 ? "green" : "red"}>
{status === 1 ? "成功" : "失败"}
</Tag>
)
},
{
title: "操作时间",
dataIndex: "createdAt",
key: "createdAt",
width: 180,
render: (text: string) => text?.replace('T', ' ').substring(0, 19)
}
];
if (activeTab === "OPERATION") {
columns.splice(1, 0, {
title: "请求方式",
dataIndex: "operationType",
key: "operationType",
width: 100,
render: (t: string) => <Tag>{t}</Tag>
});
}
return (
<div className="p-6">
<Card className="mb-4">
<Space wrap size="middle">
<Input
placeholder="用户名"
style={{ width: 160 }}
value={params.username}
onChange={e => setParams({ ...params, username: e.target.value })}
/>
<Select
placeholder="状态"
style={{ width: 120 }}
allowClear
value={params.status}
onChange={v => setParams({ ...params, status: v })}
options={[
{ label: "成功", value: 1 },
{ label: "失败", value: 0 }
]}
/>
<RangePicker
onChange={(dates) => {
setParams({
...params,
startDate: dates ? dates[0]?.format("YYYY-MM-DD") || "" : "",
endDate: dates ? dates[1]?.format("YYYY-MM-DD") || "" : ""
});
}}
/>
<Button type="primary" icon={<SearchOutlined />} onClick={handleSearch}></Button>
<Button icon={<ReloadOutlined />} onClick={handleReset}></Button>
</Space>
</Card>
<Card>
<Tabs activeKey={activeTab} onChange={setActiveTab}>
<Tabs.TabPane tab="操作日志" key="OPERATION" />
<Tabs.TabPane tab="登录日志" key="LOGIN" />
</Tabs>
<Table
rowKey="id"
columns={columns}
dataSource={data}
loading={loading}
pagination={{
current: params.current,
pageSize: params.size,
total: total,
showSizeChanger: true,
onChange: (page, size) => setParams({ ...params, current: page, size }),
showTotal: (total) => `${total}`
}}
/>
</Card>
</div>
);
}