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