blob: 5a392811c609dc49462eb5c42b21ded3ed52bef8 [file] [log] [blame]
86133aaa3f5d2025-04-20 21:33:29 +08001
2import React, { useState, useRef, useEffect } from 'react';
3import { useIntl, FormattedMessage, useAccess } from '@umijs/max';
4import type { FormInstance } from 'antd';
5import { Button, message, Modal } from 'antd';
6import { ActionType, FooterToolbar, PageContainer, ProColumns, ProTable } from '@ant-design/pro-components';
7import { PlusOutlined, DeleteOutlined, ExclamationCircleOutlined, UnlockOutlined } from '@ant-design/icons';
8import { getLogininforList, removeLogininfor, exportLogininfor, unlockLogininfor, cleanLogininfor } from '@/services/monitor/logininfor';
9import DictTag from '@/components/DictTag';
10
11/**
12 * 删除节点
13 *
14 * @param selectedRows
15 */
16const handleRemove = async (selectedRows: API.Monitor.Logininfor[]) => {
17 const hide = message.loading('正在删除');
18 if (!selectedRows) return true;
19 try {
20 const resp = await removeLogininfor(selectedRows.map((row) => row.infoId).join(','));
21 hide();
22 if (resp.code === 200) {
23 message.success('删除成功,即将刷新');
24 } else {
25 message.error(resp.msg);
26 }
27 return true;
28 } catch (error) {
29 hide();
30 message.error('删除失败,请重试');
31 return false;
32 }
33};
34
35const handleClean = async () => {
36 const hide = message.loading('请稍候');
37 try {
38 const resp = await cleanLogininfor();
39 hide();
40 if (resp.code === 200) {
41 message.success('清空成功,即将刷新');
42 } else {
43 message.error(resp.msg);
44 }
45 return true;
46 } catch (error) {
47 hide();
48 message.error('请求失败,请重试');
49 return false;
50 }
51};
52
53const handleUnlock = async (userName: string) => {
54 const hide = message.loading('正在解锁');
55 try {
56 const resp = await unlockLogininfor(userName);
57 hide();
58 if (resp.code === 200) {
59 message.success('解锁成功,即将刷新');
60 } else {
61 message.error(resp.msg);
62 }
63 return true;
64 } catch (error) {
65 hide();
66 message.error('解锁失败,请重试');
67 return false;
68 }
69};
70
71/**
72 * 导出数据
73 *
74 * @param id
75 */
76const handleExport = async () => {
77 const hide = message.loading('正在导出');
78 try {
79 await exportLogininfor();
80 hide();
81 message.success('导出成功');
82 return true;
83 } catch (error) {
84 hide();
85 message.error('导出失败,请重试');
86 return false;
87 }
88};
89
90
91const LogininforTableList: React.FC = () => {
92 const formTableRef = useRef<FormInstance>();
93
94 const actionRef = useRef<ActionType>();
95 const [selectedRows, setSelectedRows] = useState<API.Monitor.Logininfor[]>([]);
96
97 const access = useAccess();
98
99 const statusOptions = {
100 0: {
101 label: '成功',
102 key: '0',
103 value: '0',
104 text: '成功',
105 status: 'success',
106 listClass: 'success'
107 },
108 1: {
109 label: '失败',
110 key: '1',
111 value: '1',
112 text: '失败',
113 status: 'error',
114 listClass: 'danger'
115 },
116 };
117
118 /** 国际化配置 */
119 const intl = useIntl();
120
121 useEffect(() => {
122
123 }, []);
124
125 const columns: ProColumns<API.Monitor.Logininfor>[] = [
126 {
127 title: <FormattedMessage id="monitor.logininfor.info_id" defaultMessage="访问编号" />,
128 dataIndex: 'infoId',
129 valueType: 'text',
130 hideInSearch: true,
131 },
132 {
133 title: <FormattedMessage id="monitor.logininfor.user_name" defaultMessage="用户账号" />,
134 dataIndex: 'userName',
135 valueType: 'text',
136 },
137 {
138 title: <FormattedMessage id="monitor.logininfor.ipaddr" defaultMessage="登录IP地址" />,
139 dataIndex: 'ipaddr',
140 valueType: 'text',
141 },
142 {
143 title: <FormattedMessage id="monitor.logininfor.login_location" defaultMessage="登录地点" />,
144 dataIndex: 'loginLocation',
145 valueType: 'text',
146 hideInSearch: true,
147 },
148 {
149 title: <FormattedMessage id="monitor.logininfor.browser" defaultMessage="浏览器类型" />,
150 dataIndex: 'browser',
151 valueType: 'text',
152 hideInSearch: true,
153 },
154 {
155 title: <FormattedMessage id="monitor.logininfor.os" defaultMessage="操作系统" />,
156 dataIndex: 'os',
157 valueType: 'text',
158 hideInSearch: true,
159 },
160 {
161 title: <FormattedMessage id="monitor.logininfor.status" defaultMessage="登录状态" />,
162 dataIndex: 'status',
163 valueType: 'select',
164 render: (_, record) => {
165 return (<DictTag enums={statusOptions} value={record.status} />);
166 },
167 },
168 {
169 title: <FormattedMessage id="monitor.logininfor.msg" defaultMessage="提示消息" />,
170 dataIndex: 'msg',
171 valueType: 'text',
172 hideInSearch: true,
173 },
174 {
175 title: <FormattedMessage id="monitor.logininfor.login_time" defaultMessage="访问时间" />,
176 dataIndex: 'loginTime',
177 valueType: 'dateTime',
178 },
179 ];
180
181 return (
182 <PageContainer>
183 <div style={{ width: '100%', float: 'right' }}>
184 <ProTable<API.Monitor.Logininfor>
185 headerTitle={intl.formatMessage({
186 id: 'pages.searchTable.title',
187 defaultMessage: '信息',
188 })}
189 actionRef={actionRef}
190 formRef={formTableRef}
191 rowKey="infoId"
192 key="logininforList"
193 search={{
194 labelWidth: 120,
195 }}
196 toolBarRender={() => [
197 <Button
198 key="remove"
199 danger
200 hidden={selectedRows?.length === 0 || !access.hasPerms('monitor:logininfor:remove')}
201 onClick={async () => {
202 Modal.confirm({
203 title: '是否确认删除所选数据项?',
204 icon: <ExclamationCircleOutlined />,
205 content: '请谨慎操作',
206 async onOk() {
207 const success = await handleRemove(selectedRows);
208 if (success) {
209 setSelectedRows([]);
210 actionRef.current?.reloadAndRest?.();
211 }
212 },
213 onCancel() { },
214 });
215 }}
216 >
217 <DeleteOutlined />
218 <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" />
219 </Button>,
220 <Button
221 type="primary"
222 key="clean"
223 danger
224 hidden={selectedRows?.length === 0 || !access.hasPerms('monitor:logininfor:remove')}
225 onClick={async () => {
226 Modal.confirm({
227 title: '是否确认清空所有数据项?',
228 icon: <ExclamationCircleOutlined />,
229 content: '请谨慎操作',
230 async onOk() {
231 const success = await handleClean();
232 if (success) {
233 setSelectedRows([]);
234 actionRef.current?.reloadAndRest?.();
235 }
236 },
237 onCancel() { },
238 });
239 }}
240 >
241 <DeleteOutlined />
242 <FormattedMessage id="pages.searchTable.cleanAll" defaultMessage="清空" />
243 </Button>,
244 <Button
245 type="primary"
246 key="unlock"
247 hidden={selectedRows?.length === 0 || !access.hasPerms('monitor:logininfor:unlock')}
248 onClick={async () => {
249 Modal.confirm({
250 title: '是否确认解锁该用户的数据项?',
251 icon: <ExclamationCircleOutlined />,
252 content: '请谨慎操作',
253 async onOk() {
254 const success = await handleUnlock(selectedRows[0].userName);
255 if (success) {
256 setSelectedRows([]);
257 actionRef.current?.reloadAndRest?.();
258 }
259 },
260 onCancel() { },
261 });
262 }}
263 >
264 <UnlockOutlined />
265 <FormattedMessage id="monitor.logininfor.unlock" defaultMessage="解锁" />
266 </Button>,
267 <Button
268 type="primary"
269 key="export"
270 hidden={!access.hasPerms('monitor:logininfor:export')}
271 onClick={async () => {
272 handleExport();
273 }}
274 >
275 <PlusOutlined />
276 <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" />
277 </Button>,
278 ]}
279 request={(params) =>
280 getLogininforList({ ...params } as API.Monitor.LogininforListParams).then((res) => {
281 const result = {
282 data: res.rows,
283 total: res.total,
284 success: true,
285 };
286 return result;
287 })
288 }
289 columns={columns}
290 rowSelection={{
291 onChange: (_, selectedRows) => {
292 setSelectedRows(selectedRows);
293 },
294 }}
295 />
296 </div>
297 {selectedRows?.length > 0 && (
298 <FooterToolbar
299 extra={
300 <div>
301 <FormattedMessage id="pages.searchTable.chosen" defaultMessage="已选择" />
302 <a style={{ fontWeight: 600 }}>{selectedRows.length}</a>
303 <FormattedMessage id="pages.searchTable.item" defaultMessage="项" />
304 </div>
305 }
306 >
307 <Button
308 key="remove"
309 danger
310 hidden={!access.hasPerms('monitor:logininfor:remove')}
311 onClick={async () => {
312 Modal.confirm({
313 title: '删除',
314 content: '确定删除该项吗?',
315 okText: '确认',
316 cancelText: '取消',
317 onOk: async () => {
318 const success = await handleRemove(selectedRows);
319 if (success) {
320 setSelectedRows([]);
321 actionRef.current?.reloadAndRest?.();
322 }
323 },
324 });
325 }}
326 >
327 <FormattedMessage id="pages.searchTable.batchDeletion" defaultMessage="批量删除" />
328 </Button>
329 </FooterToolbar>
330 )}
331 </PageContainer>
332 );
333};
334
335export default LogininforTableList;