cfel-base-components 2.5.46 → 2.5.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/demo/src/index.jsx +40 -84
- package/package.json +1 -1
- package/src/.umi/core/helmet.ts +1 -1
- package/src/components/layout/index.scss +416 -210
- package/src/components/layout/index.tsx +262 -108
- package/src/components/{layout → layout-console}/index-console.scss +317 -84
- package/src/components/layout-console/index.tsx +712 -0
- package/src/components/layout-console/user-card/index.scss +180 -0
- package/src/components/layout-console/user-card/index.tsx +162 -0
- package/src/global.d.ts +2 -0
- package/src/index.tsx +25 -27
- package/.vscode/settings.json +0 -3
|
@@ -4,6 +4,12 @@ import UserCard from './user-card'
|
|
|
4
4
|
import RcMenu, { SubMenu, MenuItem } from 'rc-menu'
|
|
5
5
|
import { CloseCircleOutlined } from '@ant-design/icons'
|
|
6
6
|
const { Sider } = Layout
|
|
7
|
+
import './index.scss'
|
|
8
|
+
|
|
9
|
+
interface TreeNode {
|
|
10
|
+
key: string
|
|
11
|
+
children?: TreeNode[]
|
|
12
|
+
}
|
|
7
13
|
|
|
8
14
|
export interface LiosLayoutlProps {
|
|
9
15
|
appName?: any
|
|
@@ -35,6 +41,8 @@ export interface LiosLayoutlProps {
|
|
|
35
41
|
isHideHeader?: boolean //是否隐藏header
|
|
36
42
|
onCollapse?: (value: boolean) => void
|
|
37
43
|
type?: string
|
|
44
|
+
|
|
45
|
+
umiHistory: any
|
|
38
46
|
}
|
|
39
47
|
|
|
40
48
|
export default function LiosLayout(props: LiosLayoutlProps) {
|
|
@@ -56,17 +64,35 @@ export default function LiosLayout(props: LiosLayoutlProps) {
|
|
|
56
64
|
isHideHeader,
|
|
57
65
|
onCollapse,
|
|
58
66
|
type,
|
|
67
|
+
umiHistory
|
|
59
68
|
} = props
|
|
60
69
|
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
70
|
+
const findKeyPath = (pathname: string) => {
|
|
71
|
+
const path: string[] = []
|
|
72
|
+
const findPath = (nodes: TreeNode[], target: string): boolean => {
|
|
73
|
+
for (const node of nodes) {
|
|
74
|
+
if (node.key === target) {
|
|
75
|
+
path.unshift(node.key)
|
|
76
|
+
return true
|
|
77
|
+
}
|
|
78
|
+
if (node.children && findPath(node.children, target)) {
|
|
79
|
+
path.unshift(node.key)
|
|
80
|
+
return true
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return false
|
|
68
84
|
}
|
|
69
|
-
|
|
85
|
+
|
|
86
|
+
findPath(menuList, pathname)
|
|
87
|
+
return path
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// 初始化选中菜单
|
|
91
|
+
const [selectKey, setSelectKey] = useState<any>(
|
|
92
|
+
findKeyPath('/' + location.pathname.split('/')[2])
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
const [infoOpen, setInfoOpen] = useState<string | null>(null)
|
|
70
96
|
|
|
71
97
|
const logoUrl =
|
|
72
98
|
type === 'console'
|
|
@@ -81,13 +107,10 @@ export default function LiosLayout(props: LiosLayoutlProps) {
|
|
|
81
107
|
const { user, logo, subLogo, productCode } = (window as any)?.g_config
|
|
82
108
|
const { name, avatar } = user || {}
|
|
83
109
|
|
|
110
|
+
// 初始化展开菜单
|
|
84
111
|
const [openKeys, setOpenKeys] = useState<any>(defaultOpenKeys || [])
|
|
85
112
|
|
|
86
113
|
//处理搜索菜单后自动展开目录
|
|
87
|
-
interface TreeNode {
|
|
88
|
-
key: string
|
|
89
|
-
children?: TreeNode[]
|
|
90
|
-
}
|
|
91
114
|
const findParentMenu = (menuList: any[], pathname: string) => {
|
|
92
115
|
const result: TreeNode[] = []
|
|
93
116
|
|
|
@@ -112,22 +135,23 @@ export default function LiosLayout(props: LiosLayoutlProps) {
|
|
|
112
135
|
//在这里找到当前菜单的上层目录
|
|
113
136
|
const paMenu = findParentMenu(menuList, '/' + location.pathname.split('/')[2])
|
|
114
137
|
//去重
|
|
115
|
-
const set = new Set(paMenu.map(
|
|
138
|
+
const set = new Set(paMenu.map(item => item.key))
|
|
116
139
|
openKeys.forEach((element: string) => {
|
|
117
140
|
set.add(element)
|
|
118
141
|
})
|
|
119
142
|
setOpenKeys(Array.from(set))
|
|
120
143
|
}, [location.pathname])
|
|
121
144
|
|
|
145
|
+
// 初始化折叠状态
|
|
122
146
|
const [collapsed, setCollapsed] = useState(localStorage.getItem('layout_collapsed') === 'true')
|
|
123
147
|
const [isCopied, setIsCopied] = useState({
|
|
124
148
|
account: false,
|
|
125
149
|
id: false,
|
|
126
150
|
tenantName: false,
|
|
127
|
-
tenantId: false
|
|
151
|
+
tenantId: false
|
|
128
152
|
})
|
|
129
153
|
|
|
130
|
-
const onOpenChange: MenuProps['onOpenChange'] =
|
|
154
|
+
const onOpenChange: MenuProps['onOpenChange'] = keys => {
|
|
131
155
|
setOpenKeys(keys)
|
|
132
156
|
}
|
|
133
157
|
|
|
@@ -138,9 +162,10 @@ export default function LiosLayout(props: LiosLayoutlProps) {
|
|
|
138
162
|
} catch (err) {}
|
|
139
163
|
}
|
|
140
164
|
|
|
165
|
+
// 菜单动画
|
|
141
166
|
const collapseNode = () => {
|
|
142
167
|
return {
|
|
143
|
-
height: 0
|
|
168
|
+
height: 0
|
|
144
169
|
}
|
|
145
170
|
}
|
|
146
171
|
const expandNode = (node: any) => {
|
|
@@ -154,26 +179,26 @@ export default function LiosLayout(props: LiosLayoutlProps) {
|
|
|
154
179
|
onEnterStart: collapseNode,
|
|
155
180
|
onEnterActive: expandNode,
|
|
156
181
|
onLeaveStart: expandNode,
|
|
157
|
-
onLeaveActive: collapseNode
|
|
182
|
+
onLeaveActive: collapseNode
|
|
158
183
|
}
|
|
159
184
|
|
|
160
185
|
const verticalMotion = {
|
|
161
186
|
motionName: 'rc-menu-open-zoom',
|
|
162
187
|
motionAppear: true,
|
|
163
188
|
motionEnter: true,
|
|
164
|
-
motionLeave: true
|
|
189
|
+
motionLeave: true
|
|
165
190
|
}
|
|
166
191
|
|
|
167
192
|
return (
|
|
168
|
-
<Layout className=
|
|
193
|
+
<Layout className='layout-warps'>
|
|
169
194
|
{Array.isArray(menuList) && menuList.length > 0 && (
|
|
170
195
|
<Sider
|
|
171
|
-
className=
|
|
196
|
+
className='layout-side'
|
|
172
197
|
collapsible
|
|
173
198
|
trigger={null}
|
|
174
199
|
collapsed={collapsed}
|
|
175
200
|
width={260}
|
|
176
|
-
onCollapse={
|
|
201
|
+
onCollapse={value => {
|
|
177
202
|
if (onCollapse) {
|
|
178
203
|
onCollapse(value)
|
|
179
204
|
}
|
|
@@ -181,45 +206,63 @@ export default function LiosLayout(props: LiosLayoutlProps) {
|
|
|
181
206
|
setCollapsed(value)
|
|
182
207
|
}}
|
|
183
208
|
>
|
|
184
|
-
<div className=
|
|
209
|
+
<div className='layout-side-mask1'></div>
|
|
210
|
+
|
|
211
|
+
<div
|
|
212
|
+
className='header-logo'
|
|
213
|
+
style={{ justifyContent: collapsed ? 'center' : '', paddingLeft: collapsed ? '0' : '' }}
|
|
214
|
+
>
|
|
185
215
|
<div
|
|
186
216
|
onClick={() => {
|
|
187
217
|
window.open('/home')
|
|
188
218
|
}}
|
|
189
219
|
>
|
|
190
220
|
{!collapsed && <img className={`logo-base current-logo`} src={logo || logoUrl} />}
|
|
191
|
-
|
|
192
|
-
{collapsed && <img className={`logo-base sub-logo`} src={logo || subLogoUrl} />}
|
|
221
|
+
{collapsed && <img className={`logo-sub`} src={subLogoUrl} />}
|
|
222
|
+
{/* {collapsed && <img className={`logo-base sub-logo`} src={logo || subLogoUrl} />} */}
|
|
193
223
|
</div>
|
|
194
224
|
|
|
195
|
-
{/*
|
|
225
|
+
{/* {!collapsed && (
|
|
196
226
|
<div
|
|
197
|
-
className=
|
|
227
|
+
className='trigger'
|
|
198
228
|
onClick={() => {
|
|
199
229
|
setCollapsed(true)
|
|
200
230
|
}}
|
|
201
231
|
>
|
|
202
|
-
<Arrow collapsed={true} />
|
|
232
|
+
<Arrow collapsed={true} type={type} />
|
|
203
233
|
</div>
|
|
204
234
|
)} */}
|
|
205
235
|
</div>
|
|
206
236
|
|
|
207
|
-
{
|
|
237
|
+
{collapsed && (
|
|
208
238
|
<div style={{ width: '100%', display: 'flex', justifyContent: 'center' }}>
|
|
209
239
|
<div
|
|
210
|
-
className=
|
|
240
|
+
className='close-trigger'
|
|
211
241
|
onClick={() => {
|
|
212
242
|
setCollapsed(false)
|
|
213
243
|
}}
|
|
214
244
|
>
|
|
215
|
-
<Arrow collapsed={false} />
|
|
245
|
+
<Arrow collapsed={false} type={type} />
|
|
216
246
|
</div>
|
|
217
247
|
</div>
|
|
218
|
-
)}
|
|
248
|
+
)}
|
|
249
|
+
|
|
250
|
+
<div style={{ height: 24 }}></div>
|
|
251
|
+
|
|
252
|
+
<div style={{ width: '100%', padding: '0 16px' }}>
|
|
253
|
+
<Search
|
|
254
|
+
menuList={menuList}
|
|
255
|
+
collapsed={collapsed}
|
|
256
|
+
type={type || ''}
|
|
257
|
+
umiHistory={umiHistory}
|
|
258
|
+
setSelectKey={setSelectKey}
|
|
259
|
+
findKeyPath={findKeyPath}
|
|
260
|
+
/>
|
|
261
|
+
</div>
|
|
219
262
|
|
|
220
|
-
{!collapsed && <div style={{ height:
|
|
263
|
+
{!collapsed && <div style={{ height: 12 }}></div>}
|
|
221
264
|
|
|
222
|
-
<div className=
|
|
265
|
+
<div className='layout-menu'>
|
|
223
266
|
<RcMenu
|
|
224
267
|
mode={collapsed ? 'vertical' : 'inline'}
|
|
225
268
|
className={`menu${collapsed ? '-collapsed' : ''}`}
|
|
@@ -233,7 +276,7 @@ export default function LiosLayout(props: LiosLayoutlProps) {
|
|
|
233
276
|
onMenuClick(item)
|
|
234
277
|
}
|
|
235
278
|
}}
|
|
236
|
-
triggerSubMenuAction=
|
|
279
|
+
triggerSubMenuAction='hover'
|
|
237
280
|
>
|
|
238
281
|
{menuList.map((item: any) => {
|
|
239
282
|
const isSelected = selectKey.includes(item.key)
|
|
@@ -244,13 +287,17 @@ export default function LiosLayout(props: LiosLayoutlProps) {
|
|
|
244
287
|
}
|
|
245
288
|
return (
|
|
246
289
|
<SubMenu
|
|
247
|
-
popupClassName=
|
|
290
|
+
popupClassName='rc-menu-submenu-popup'
|
|
248
291
|
key={item.key}
|
|
249
|
-
className=
|
|
292
|
+
className='menu-item-content'
|
|
250
293
|
title={
|
|
251
|
-
<div className=
|
|
252
|
-
<div className=
|
|
253
|
-
<span
|
|
294
|
+
<div className='sub-list'>
|
|
295
|
+
<div className='menu-item-inner'>
|
|
296
|
+
<span
|
|
297
|
+
className={`menu-item-icon ${isSelected ? 'submenu-selected' : ''}`}
|
|
298
|
+
>
|
|
299
|
+
{item.icon}
|
|
300
|
+
</span>
|
|
254
301
|
{!collapsed && <span className={classNames}>{item.label}</span>}
|
|
255
302
|
</div>
|
|
256
303
|
</div>
|
|
@@ -267,10 +314,20 @@ export default function LiosLayout(props: LiosLayoutlProps) {
|
|
|
267
314
|
if (child.children) {
|
|
268
315
|
return (
|
|
269
316
|
<SubMenu
|
|
270
|
-
popupClassName=
|
|
271
|
-
className=
|
|
317
|
+
popupClassName='rc-menu-submenu-popup'
|
|
318
|
+
className='menu-item-content sub-li'
|
|
272
319
|
key={child.key}
|
|
273
|
-
title={
|
|
320
|
+
title={
|
|
321
|
+
<div className='sub-list'>
|
|
322
|
+
{!collapsed && (
|
|
323
|
+
<span
|
|
324
|
+
className={`menu-item-label ${isSelected ? 'submenu-selected' : ''}`}
|
|
325
|
+
>
|
|
326
|
+
{child.label}
|
|
327
|
+
</span>
|
|
328
|
+
)}
|
|
329
|
+
</div>
|
|
330
|
+
}
|
|
274
331
|
>
|
|
275
332
|
{child.children.map((grandChild: any) => {
|
|
276
333
|
const isSelected = selectKey.includes(grandChild.key)
|
|
@@ -281,8 +338,16 @@ export default function LiosLayout(props: LiosLayoutlProps) {
|
|
|
281
338
|
}
|
|
282
339
|
}
|
|
283
340
|
return (
|
|
284
|
-
<MenuItem key={grandChild.key} className=
|
|
285
|
-
<div className=
|
|
341
|
+
<MenuItem key={grandChild.key} className='grand-li'>
|
|
342
|
+
<div className='menu-item-content'>
|
|
343
|
+
{!collapsed && (
|
|
344
|
+
<span
|
|
345
|
+
className={`menu-item-label ${isSelected ? 'submenu-selected' : ''}`}
|
|
346
|
+
>
|
|
347
|
+
{grandChild.label}
|
|
348
|
+
</span>
|
|
349
|
+
)}
|
|
350
|
+
</div>
|
|
286
351
|
</MenuItem>
|
|
287
352
|
)
|
|
288
353
|
})}
|
|
@@ -290,8 +355,16 @@ export default function LiosLayout(props: LiosLayoutlProps) {
|
|
|
290
355
|
)
|
|
291
356
|
}
|
|
292
357
|
return (
|
|
293
|
-
<MenuItem key={child.key} className=
|
|
294
|
-
<div className=
|
|
358
|
+
<MenuItem key={child.key} className='sub-li'>
|
|
359
|
+
<div className='menu-item-content'>
|
|
360
|
+
{!collapsed && (
|
|
361
|
+
<span
|
|
362
|
+
className={`menu-item-label ${isSelected ? 'submenu-selected' : ''}`}
|
|
363
|
+
>
|
|
364
|
+
{child.label}
|
|
365
|
+
</span>
|
|
366
|
+
)}
|
|
367
|
+
</div>
|
|
295
368
|
</MenuItem>
|
|
296
369
|
)
|
|
297
370
|
})}
|
|
@@ -305,9 +378,11 @@ export default function LiosLayout(props: LiosLayoutlProps) {
|
|
|
305
378
|
classNames += ' submenu-selected'
|
|
306
379
|
}
|
|
307
380
|
return (
|
|
308
|
-
<MenuItem key={item.key} className=
|
|
381
|
+
<MenuItem key={item.key} className='menu-item-content'>
|
|
309
382
|
<div>
|
|
310
|
-
<span className={`menu-item-icon ${isSelected ? 'submenu-selected' : ''}`}>
|
|
383
|
+
<span className={`menu-item-icon ${isSelected ? 'submenu-selected' : ''}`}>
|
|
384
|
+
{item.icon}
|
|
385
|
+
</span>
|
|
311
386
|
{!collapsed && <span className={classNames}>{item.label}</span>}
|
|
312
387
|
</div>
|
|
313
388
|
</MenuItem>
|
|
@@ -319,21 +394,21 @@ export default function LiosLayout(props: LiosLayoutlProps) {
|
|
|
319
394
|
</Sider>
|
|
320
395
|
)}
|
|
321
396
|
|
|
322
|
-
<div className=
|
|
397
|
+
<div className='layout-main'>
|
|
323
398
|
{!isHideHeader && (
|
|
324
|
-
<div className=
|
|
399
|
+
<div className='layout-header'>
|
|
325
400
|
{appName && (
|
|
326
|
-
<div className=
|
|
401
|
+
<div className='app-name'>
|
|
327
402
|
<strong>{appName}</strong>
|
|
328
403
|
</div>
|
|
329
404
|
)}
|
|
330
405
|
|
|
331
|
-
<div className=
|
|
406
|
+
<div className='layout-header-fill' />
|
|
332
407
|
|
|
333
|
-
<div className=
|
|
408
|
+
<div className='layout-header-actions'>
|
|
334
409
|
{actions?.map((item, index) => {
|
|
335
410
|
return (
|
|
336
|
-
<div className=
|
|
411
|
+
<div className='actions-item' key={index}>
|
|
337
412
|
{item}
|
|
338
413
|
</div>
|
|
339
414
|
)
|
|
@@ -341,70 +416,112 @@ export default function LiosLayout(props: LiosLayoutlProps) {
|
|
|
341
416
|
</div>
|
|
342
417
|
|
|
343
418
|
<Popover
|
|
344
|
-
placement=
|
|
419
|
+
placement='bottom'
|
|
345
420
|
content={
|
|
346
|
-
<UserCard
|
|
421
|
+
<UserCard
|
|
422
|
+
myWalletInfo={myWalletInfo}
|
|
423
|
+
MyLoginInfo={MyLoginInfo}
|
|
424
|
+
amountInfo={amountInfo}
|
|
425
|
+
customAction={customAction}
|
|
426
|
+
isCopied={isCopied}
|
|
427
|
+
copyTextToClipboard={copyTextToClipboard}
|
|
428
|
+
/>
|
|
347
429
|
}
|
|
348
430
|
arrow={false}
|
|
349
|
-
trigger=
|
|
350
|
-
onOpenChange={
|
|
431
|
+
trigger='click'
|
|
432
|
+
onOpenChange={e => {
|
|
433
|
+
setInfoOpen(e ? 'up' : 'down')
|
|
351
434
|
if (!e) return
|
|
352
435
|
setIsCopied({
|
|
353
436
|
account: false,
|
|
354
437
|
id: false,
|
|
355
438
|
tenantName: false,
|
|
356
|
-
tenantId: false
|
|
439
|
+
tenantId: false
|
|
357
440
|
})
|
|
358
441
|
if (myLoginInfoAction) {
|
|
359
442
|
myLoginInfoAction()
|
|
360
443
|
}
|
|
361
444
|
}}
|
|
362
445
|
>
|
|
363
|
-
<div className=
|
|
364
|
-
<img className=
|
|
365
|
-
<div className=
|
|
446
|
+
<div className='layout-header-user'>
|
|
447
|
+
<img className='avatar' src={avatar} />
|
|
448
|
+
<div className='name'>{name}</div>
|
|
449
|
+
<span
|
|
450
|
+
style={{
|
|
451
|
+
display: 'inline-block',
|
|
452
|
+
marginLeft: '8px'
|
|
453
|
+
}}
|
|
454
|
+
className={`iconfont icon-zhankai ${infoOpen ? (infoOpen === 'up' ? 'up' : 'down') : ''}`}
|
|
455
|
+
></span>
|
|
366
456
|
</div>
|
|
367
457
|
</Popover>
|
|
368
458
|
</div>
|
|
369
459
|
)}
|
|
370
|
-
<div className=
|
|
460
|
+
<div className='layout-content'>{props.children}</div>
|
|
371
461
|
</div>
|
|
372
462
|
</Layout>
|
|
373
463
|
)
|
|
374
464
|
}
|
|
375
465
|
|
|
376
|
-
function Arrow({ collapsed }: { collapsed?: boolean }) {
|
|
466
|
+
function Arrow({ collapsed, type }: { collapsed?: boolean; type?: string }) {
|
|
377
467
|
return (
|
|
378
|
-
<
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
468
|
+
<svg
|
|
469
|
+
style={{ transform: !collapsed ? 'rotate(180deg)' : 'rotate(0deg)' }}
|
|
470
|
+
viewBox='0 0 1024 1024'
|
|
471
|
+
version='1.1'
|
|
472
|
+
xmlns='http://www.w3.org/2000/svg'
|
|
473
|
+
width='20'
|
|
474
|
+
height='20'
|
|
475
|
+
>
|
|
476
|
+
<path
|
|
477
|
+
fill={type === 'console' ? '#FFFFFF' : '#817F9B'}
|
|
478
|
+
d='M564.6336 775.168a41.5744 41.5744 0 0 0-13.312-28.672l-230.4-234.4448 229.9904-234.1888a42.0864 42.0864 0 0 0-26.3168-73.0112 42.0864 42.0864 0 0 0-30.6176 11.264L231.0656 481.024a41.984 41.984 0 0 0-2.4576 59.5968l1.9968 2.048 263.7824 265.6256a41.984 41.984 0 0 0 70.2464-33.0752z m254.5152 0a41.472 41.472 0 0 0-13.312-28.672L575.488 512l229.9904-234.1376a41.984 41.984 0 1 0-56.9344-61.7984L485.632 480.9728a42.0864 42.0864 0 0 0-2.4064 59.6992l0.8704 0.9216 0.8704 0.8192 0.4096 0.4096 263.5776 265.4208a41.984 41.984 0 0 0 70.1952-33.0752z'
|
|
479
|
+
></path>
|
|
480
|
+
</svg>
|
|
386
481
|
)
|
|
387
482
|
}
|
|
388
483
|
|
|
389
|
-
|
|
484
|
+
type SearchProps = {
|
|
485
|
+
menuList: TreeNode[]
|
|
486
|
+
collapsed: boolean
|
|
487
|
+
type: string
|
|
488
|
+
umiHistory: any
|
|
489
|
+
setSelectKey: any
|
|
490
|
+
findKeyPath: (pathname: string) => string[]
|
|
491
|
+
}
|
|
492
|
+
function Search({ menuList, collapsed, type, umiHistory, setSelectKey, findKeyPath }: SearchProps) {
|
|
390
493
|
useEffect(() => {
|
|
391
494
|
const handleKeyDown = (event: KeyboardEvent) => {
|
|
392
|
-
|
|
393
|
-
|
|
495
|
+
if (
|
|
496
|
+
(navigator.platform.toLowerCase().includes('mac') ? event.metaKey : event.ctrlKey) &&
|
|
497
|
+
event.key.toLowerCase() === 'k'
|
|
498
|
+
) {
|
|
394
499
|
event.preventDefault()
|
|
395
500
|
const searchInput = document.querySelector('#menu-input') as HTMLInputElement
|
|
396
501
|
if (searchInput) {
|
|
397
502
|
searchInput.focus()
|
|
398
|
-
|
|
503
|
+
setIsFocused(true)
|
|
399
504
|
}
|
|
400
505
|
}
|
|
401
506
|
}
|
|
402
507
|
|
|
508
|
+
// Add click outside listener to close dropdown
|
|
509
|
+
const handleClickOutside = (event: MouseEvent) => {
|
|
510
|
+
const searchContainer = document.querySelector('.search-container')
|
|
511
|
+
if (searchContainer && !searchContainer.contains(event.target as Node)) {
|
|
512
|
+
setIsFocused(false)
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
403
516
|
document.addEventListener('keydown', handleKeyDown)
|
|
517
|
+
document.addEventListener('mousedown', handleClickOutside)
|
|
518
|
+
|
|
404
519
|
return () => {
|
|
405
520
|
document.removeEventListener('keydown', handleKeyDown)
|
|
521
|
+
document.removeEventListener('mousedown', handleClickOutside)
|
|
406
522
|
}
|
|
407
523
|
}, [])
|
|
524
|
+
|
|
408
525
|
type Router = { label: string; icon?: any; key: string; children?: Router[] }
|
|
409
526
|
|
|
410
527
|
const name = (window as any).g_config.productCode
|
|
@@ -412,7 +529,7 @@ function Search({ menuList, collapsed, type }: { menuList: any; collapsed: boole
|
|
|
412
529
|
const [searchTerm, setSearchTerm] = useState('')
|
|
413
530
|
const [searchHistory, setSearchHistory] = useState<Router[]>([])
|
|
414
531
|
const [searchResult, setSearchResult] = useState<Router[]>([])
|
|
415
|
-
const [
|
|
532
|
+
const [isFocused, setIsFocused] = useState(false)
|
|
416
533
|
|
|
417
534
|
useEffect(() => {
|
|
418
535
|
const searchHistory = localStorage.getItem(name + 'searchHistory')
|
|
@@ -434,11 +551,11 @@ function Search({ menuList, collapsed, type }: { menuList: any; collapsed: boole
|
|
|
434
551
|
setSearchTerm(value)
|
|
435
552
|
//递归menulist判断是否有包含的
|
|
436
553
|
const searchResults: Router[] = []
|
|
437
|
-
search(menuList)
|
|
554
|
+
search(menuList as Router[])
|
|
438
555
|
setSearchResult(searchResults)
|
|
439
556
|
function search(data: Router[]) {
|
|
440
|
-
data.forEach(
|
|
441
|
-
if (item.label.includes(value.toLocaleUpperCase())) {
|
|
557
|
+
data.forEach(item => {
|
|
558
|
+
if (typeof item.label === 'string' && item.label.includes(value.toLocaleUpperCase())) {
|
|
442
559
|
searchResults.push(item)
|
|
443
560
|
}
|
|
444
561
|
if (item.children) {
|
|
@@ -449,9 +566,9 @@ function Search({ menuList, collapsed, type }: { menuList: any; collapsed: boole
|
|
|
449
566
|
}
|
|
450
567
|
|
|
451
568
|
const enter = (item: Router) => {
|
|
452
|
-
|
|
569
|
+
setIsFocused(false)
|
|
453
570
|
//如果搜索历史里面有这个item,就不再添加
|
|
454
|
-
if (searchHistory.findIndex(
|
|
571
|
+
if (searchHistory.findIndex(i => i.key === item.key) === -1) {
|
|
455
572
|
setSearchHistory([...searchHistory, item])
|
|
456
573
|
}
|
|
457
574
|
//如果是目录就找到目录下第一个菜单进入
|
|
@@ -468,71 +585,108 @@ function Search({ menuList, collapsed, type }: { menuList: any; collapsed: boole
|
|
|
468
585
|
}
|
|
469
586
|
const firstItem = findFirst(item.children || [])
|
|
470
587
|
if (firstItem) {
|
|
471
|
-
|
|
588
|
+
setSelectKey(findKeyPath(firstItem.key)) // 记住keypath
|
|
589
|
+
umiHistory.push(firstItem.key, '_self')
|
|
472
590
|
}
|
|
473
591
|
} else {
|
|
474
|
-
|
|
592
|
+
setSelectKey(findKeyPath(item.key)) // 记住keypath
|
|
593
|
+
umiHistory.push(item.key, '_self')
|
|
475
594
|
}
|
|
476
595
|
}
|
|
477
596
|
|
|
478
597
|
const deleteHistory = (item: Router) => {
|
|
479
|
-
setSearchHistory(searchHistory.filter(
|
|
598
|
+
setSearchHistory(searchHistory.filter(i => i.key !== item.key))
|
|
480
599
|
}
|
|
481
600
|
return (
|
|
482
601
|
<>
|
|
483
602
|
{collapsed ? (
|
|
484
|
-
<div className=
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
603
|
+
<div className='search-mobile-console'>
|
|
604
|
+
<div className='search-icon'>
|
|
605
|
+
<svg
|
|
606
|
+
viewBox='0 0 1024 1024'
|
|
607
|
+
version='1.1'
|
|
608
|
+
xmlns='http://www.w3.org/2000/svg'
|
|
609
|
+
width='18'
|
|
610
|
+
height='18'
|
|
611
|
+
>
|
|
488
612
|
<path
|
|
489
|
-
fill=
|
|
490
|
-
d=
|
|
613
|
+
fill={type === 'console' ? '#C2B7F6' : '#817F9B'}
|
|
614
|
+
d='M962.048 907.776l-229.0176-229.0176a384.3072 384.3072 0 1 0-54.272 54.272l229.0176 229.0176a38.4 38.4 0 0 0 54.272-54.272zM436.1216 743.0656a306.944 306.944 0 1 1 306.944-306.944 307.3024 307.3024 0 0 1-306.944 306.944z'
|
|
491
615
|
></path>
|
|
492
616
|
</svg>
|
|
493
617
|
</div>
|
|
494
618
|
</div>
|
|
495
619
|
) : (
|
|
496
|
-
<div
|
|
497
|
-
<div className=
|
|
498
|
-
<
|
|
499
|
-
|
|
500
|
-
|
|
620
|
+
<div className='search-container'>
|
|
621
|
+
<div className='search'>
|
|
622
|
+
<div className='search-bg-mask'>
|
|
623
|
+
<img src='https://cfel-front.oss-cn-hangzhou.aliyuncs.com/logo/base-component/menu-search-bg.png' />
|
|
624
|
+
</div>
|
|
625
|
+
<input
|
|
626
|
+
autoComplete='off'
|
|
627
|
+
id='menu-input'
|
|
628
|
+
value={searchTerm}
|
|
629
|
+
onChange={e => handleSearch(e.target.value)}
|
|
630
|
+
className='search-input'
|
|
631
|
+
placeholder='搜索菜单...'
|
|
632
|
+
onFocus={() => setIsFocused(true)}
|
|
633
|
+
/>
|
|
634
|
+
<div className='search-icon'>
|
|
635
|
+
<svg
|
|
636
|
+
viewBox='0 0 1024 1024'
|
|
637
|
+
version='1.1'
|
|
638
|
+
xmlns='http://www.w3.org/2000/svg'
|
|
639
|
+
width='18'
|
|
640
|
+
height='18'
|
|
641
|
+
>
|
|
501
642
|
<path
|
|
502
643
|
fill={type === 'console' ? '#C2B7F6' : '#817F9B'}
|
|
503
|
-
d=
|
|
644
|
+
d='M962.048 907.776l-229.0176-229.0176a384.3072 384.3072 0 1 0-54.272 54.272l229.0176 229.0176a38.4 38.4 0 0 0 54.272-54.272zM436.1216 743.0656a306.944 306.944 0 1 1 306.944-306.944 307.3024 307.3024 0 0 1-306.944 306.944z'
|
|
504
645
|
></path>
|
|
505
646
|
</svg>
|
|
506
647
|
</div>
|
|
507
|
-
<div
|
|
648
|
+
<div
|
|
649
|
+
className='search-command'
|
|
650
|
+
style={{ width: navigator.platform.toLowerCase().includes('mac') ? '' : '50px' }}
|
|
651
|
+
>
|
|
652
|
+
{navigator.platform.toLowerCase().includes('mac') ? '⌘' : 'Ctrl+'}K
|
|
653
|
+
</div>
|
|
508
654
|
</div>
|
|
509
655
|
<div>
|
|
510
|
-
{
|
|
656
|
+
{isFocused && (
|
|
511
657
|
<>
|
|
512
658
|
{searchTerm ? (
|
|
513
|
-
<List
|
|
659
|
+
<List
|
|
660
|
+
split={false}
|
|
661
|
+
className='lists'
|
|
662
|
+
size='small'
|
|
663
|
+
bordered
|
|
664
|
+
dataSource={searchResult}
|
|
665
|
+
renderItem={item => (
|
|
666
|
+
<List.Item onClick={() => enter(item)}>{item.label}</List.Item>
|
|
667
|
+
)}
|
|
668
|
+
/>
|
|
514
669
|
) : (
|
|
515
670
|
<List
|
|
516
671
|
split={false}
|
|
517
|
-
className=
|
|
518
|
-
header=
|
|
519
|
-
size=
|
|
672
|
+
className='lists'
|
|
673
|
+
header='最近访问'
|
|
674
|
+
size='small'
|
|
520
675
|
bordered
|
|
521
676
|
dataSource={searchHistory}
|
|
522
|
-
renderItem={
|
|
677
|
+
renderItem={item => {
|
|
523
678
|
return (
|
|
524
679
|
<div
|
|
525
680
|
className={'search-item'}
|
|
526
681
|
style={{
|
|
527
682
|
display: 'flex',
|
|
528
683
|
justifyContent: 'space-between',
|
|
529
|
-
alignItems: 'center'
|
|
684
|
+
alignItems: 'center'
|
|
530
685
|
}}
|
|
531
|
-
onClick={() => enter(item)}
|
|
532
686
|
>
|
|
533
|
-
<List.Item>{item.label}</List.Item>
|
|
687
|
+
<List.Item onClick={() => enter(item)}>{item.label}</List.Item>
|
|
534
688
|
<div
|
|
535
|
-
style={{ paddingRight: 10 }}
|
|
689
|
+
style={{ paddingRight: 10, cursor: 'pointer' }}
|
|
536
690
|
onClick={() => {
|
|
537
691
|
deleteHistory(item)
|
|
538
692
|
}}
|