| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
 | |   |  | import React, { useState, useRef, useEffect } from 'react';  |  | import { Button, message, Modal, Tag } from 'antd';  |  | import {  |  |     FooterToolbar,  |  |     PageContainer,  |  |     ProTable,  |  |     LightFilter,  |  | } from '@ant-design/pro-components';  |  | import { FormattedMessage, useIntl } from '@umijs/max';  |  | import { PlusOutlined, ExportOutlined } from '@ant-design/icons';  |  | import Http from '@/utils/http';  |  | import Edit from './components/edit'  |  | import { TextFilter, SelectFilter, DatetimeRangeFilter, LinkFilter } from '@/components/TableSearch'  |  | import { repairBug } from '@/utils/common-util';  |  |   |  | const TABLE_KEY = "pro-table-userLogin";  |  |   |  | const typeMap = {  |  |     0: {  |  |         color: '#87d068',  |  |         text: '登录成功',  |  |     },  |  |     1: {  |  |         color: '#f50',  |  |         text: '登录失败',  |  |     },  |  |     2: {  |  |         color: '',  |  |         text: '退出登录',  |  |     },  |  |     3: {  |  |         color: '#3b5999',  |  |         text: '续签token',  |  |     },  |  | };  |  |   |  | const handleExport = async (intl) => {  |  |     const hide = message.loading(intl.formatMessage({ id: 'page.exporting', defaultMessage: '正在导出' }));  |  |     try {  |  |         const resp = await Http.doPostBlob('api/userLogin/export');  |  |         const blob = new Blob([resp], { type: 'application/vnd.ms-excel' });  |  |         window.location.href = window.URL.createObjectURL(blob);  |  |         message.success(intl.formatMessage({ id: 'page.export.success', defaultMessage: '导出成功' }));  |  |         return true;  |  |     } catch (error) {  |  |         message.error(intl.formatMessage({ id: 'page.export.fail', defaultMessage: '导出失败,请重试' }));  |  |         return false;  |  |     } finally {  |  |         hide();  |  |     }  |  | };  |  |   |  |   |  | const Main = () => {  |  |     const intl = useIntl();  |  |     const formTableRef = useRef();  |  |     const actionRef = useRef();  |  |     const [selectedRows, setSelectedRows] = useState([]);  |  |     const [modalVisible, setModalVisible] = useState(false);  |  |     const [currentRow, setCurrentRow] = useState();  |  |     const [searchParam, setSearchParam] = useState({});  |  |   |  |     useEffect(() => {  |  |   |  |     }, []);  |  |   |  |     const columns = [  |  |         {  |  |             title: intl.formatMessage({  |  |                 id: 'page.table.no',  |  |                 defaultMessage: 'No'  |  |             }),  |  |             dataIndex: 'index',  |  |             valueType: 'indexBorder',  |  |             width: 48,  |  |         },  |  |         {  |  |             title: '用户',  |  |             dataIndex: 'userId$',  |  |             valueType: 'text',  |  |             hidden: false,  |  |             width: 140,  |  |             filterDropdown: (props) => <LinkFilter  |  |                 name='userId'  |  |                 major='user'  |  |                 {...props}  |  |                 actionRef={actionRef}  |  |                 setSearchParam={setSearchParam}  |  |             />,  |  |         },  |  |         {  |  |             title: '密钥',  |  |             dataIndex: 'token',  |  |             valueType: 'text',  |  |             hidden: false,  |  |             ellipsis: true,  |  |             width: 140,  |  |             copyable: true,  |  |             filterDropdown: (props) => <TextFilter  |  |                 name='token'  |  |                 {...props}  |  |                 actionRef={actionRef}  |  |                 setSearchParam={setSearchParam}  |  |             />,  |  |         },  |  |         {  |  |             title: '登录ip',  |  |             dataIndex: 'ip',  |  |             valueType: 'text',  |  |             hidden: false,  |  |             width: 140,  |  |             filterDropdown: (props) => <TextFilter  |  |                 name='ip'  |  |                 {...props}  |  |                 actionRef={actionRef}  |  |                 setSearchParam={setSearchParam}  |  |             />,  |  |         },  |  |         {  |  |             title: '类型',  |  |             dataIndex: 'type',  |  |             valueType: 'text',  |  |             hidden: false,  |  |             width: 140,  |  |             filterDropdown: (props) => <SelectFilter  |  |                 name='type'  |  |                 {...props}  |  |                 actionRef={actionRef}  |  |                 setSearchParam={setSearchParam}  |  |                 data={[  |  |                     { label: '登录成功', value: 0 },  |  |                     { label: '登录失败', value: 1 },  |  |                     { label: '退出登录', value: 2 },  |  |                     { label: '续签token', value: 3 },  |  |                 ]}  |  |             />,  |  |             render: (_, record) => {  |  |                 const type = typeMap[record.type]  |  |                 return <Tag color={type.color}>{type.text}</Tag>  |  |             },  |  |         },  |  |         {  |  |             title: '添加时间',  |  |             dataIndex: 'createTime$',  |  |             valueType: 'text',  |  |             hidden: false,  |  |             width: 140,  |  |             filterDropdown: (props) => <DatetimeRangeFilter  |  |                 name='createTime'  |  |                 {...props}  |  |                 actionRef={actionRef}  |  |                 setSearchParam={setSearchParam}  |  |             />,  |  |         },  |  |         {  |  |             title: '登录系统',  |  |             dataIndex: 'system',  |  |             valueType: 'text',  |  |             hidden: false,  |  |             width: 140,  |  |             filterDropdown: (props) => <TextFilter  |  |                 name='system'  |  |                 {...props}  |  |                 actionRef={actionRef}  |  |                 setSearchParam={setSearchParam}  |  |             />,  |  |         },  |  |         {  |  |             title: '备注',  |  |             dataIndex: 'memo',  |  |             valueType: 'text',  |  |             hidden: false,  |  |             width: 140,  |  |             filterDropdown: (props) => <TextFilter  |  |                 name='memo'  |  |                 {...props}  |  |                 actionRef={actionRef}  |  |                 setSearchParam={setSearchParam}  |  |             />,  |  |         },  |  |   |  |         {  |  |             title: '操作',  |  |             dataIndex: 'option',  |  |             width: 140,  |  |             hidden: true,  |  |             valueType: 'option',  |  |             render: (_, record) => [  |  |             ],  |  |         },  |  |     ];  |  |   |  |     return (  |  |         <PageContainer  |  |             header={{  |  |                 breadcrumb: {},  |  |             }}  |  |         >  |  |             <div style={{ width: '100%', float: 'right' }}>  |  |                 <ProTable  |  |                     key="userLogin"  |  |                     rowKey="id"  |  |                     actionRef={actionRef}  |  |                     formRef={formTableRef}  |  |                     columns={columns}  |  |                     cardBordered  |  |                     scroll={{ x: 1300 }}  |  |                     dateFormatter="string"  |  |                     pagination={{ pageSize: 16 }}  |  |                     search={false}  |  |                     style={{  |  |                         marginBottom: '20px'  |  |                     }}  |  |                     toolbar={{  |  |                         search: {  |  |                             onSearch: (value) => {  |  |                                 setSearchParam(prevState => ({  |  |                                     ...prevState,  |  |                                     condition: value  |  |                                 }));  |  |                                 actionRef.current?.reload();  |  |                             },  |  |                         },  |  |                         filter: (  |  |                             <LightFilter  |  |                                 onValuesChange={(val) => {  |  |                                 }}  |  |                             >  |  |                             </LightFilter>  |  |                         ),  |  |                         actions: [  |  |                             <Button  |  |                                 key="export"  |  |                                 onClick={async () => {  |  |                                     handleExport(intl);  |  |                                 }}  |  |                             >  |  |                                 <ExportOutlined />  |  |                                 <FormattedMessage id='page.export' defaultMessage='导出' />  |  |                             </Button>,  |  |                         ],  |  |                     }}  |  |                     request={(params, sorter, filter) =>  |  |                         Http.doPostPromise('/api/userLogin/page', { ...params, ...searchParam }, (res) => {  |  |                             return {  |  |                                 data: res.data.records,  |  |                                 total: res.data.total,  |  |                                 success: true,  |  |                             }  |  |                         })  |  |                     }  |  |                     rowSelection={undefined}  |  |                     columnsState={{  |  |                         persistenceKey: TABLE_KEY,  |  |                         persistenceType: 'localStorage',  |  |                         defaultValue: {  |  |                             system: { show: repairBug(TABLE_KEY, 'system', false) },  |  |                             option: { fixed: 'right', disable: true },  |  |                         },  |  |                         onChange(value) {  |  |                         },  |  |                     }}  |  |                 />  |  |             </div>  |  |   |  |             <Edit  |  |                 open={modalVisible}  |  |                 values={currentRow || {}}  |  |                 onCancel={  |  |                     () => {  |  |                         setModalVisible(false);  |  |                         setCurrentRow(undefined);  |  |                     }  |  |                 }  |  |                 onSubmit={async (values) => {  |  |                     setModalVisible(false);  |  |                     setCurrentRow(undefined);  |  |                     if (actionRef.current) {  |  |                         actionRef.current.reload();  |  |                     }  |  |                 }  |  |                 }  |  |             />  |  |         </PageContainer>  |  |     );  |  | };  |  |   |  | export default Main;  | 
 |