cfel-base-components 2.5.76 → 2.5.78
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/package.json +1 -1
- package/src/apiRequest/config.ts +54 -36
- package/src/components/layout/index.tsx +0 -1
- package/src/index.tsx +0 -4
- package/src/components/layout-cloud/index-cloud.scss +0 -886
- package/src/components/layout-cloud/index.tsx +0 -753
- package/src/components/layout-cloud/user-card/index.scss +0 -180
- package/src/components/layout-cloud/user-card/index.tsx +0 -162
- package/src/components/layout-console/index-console.scss +0 -943
- package/src/components/layout-console/index.tsx +0 -742
- package/src/components/layout-console/user-card/index.scss +0 -180
- package/src/components/layout-console/user-card/index.tsx +0 -162
|
@@ -1,742 +0,0 @@
|
|
|
1
|
-
import React, { useEffect, useState } from 'react'
|
|
2
|
-
import { Layout, List, Menu, MenuProps, Popover } from 'antd'
|
|
3
|
-
import UserCard from './user-card'
|
|
4
|
-
import RcMenu, { SubMenu, MenuItem } from 'rc-menu'
|
|
5
|
-
import { CloseCircleOutlined, RightOutlined } from '@ant-design/icons'
|
|
6
|
-
const { Sider } = Layout
|
|
7
|
-
import './index-console.scss'
|
|
8
|
-
|
|
9
|
-
interface TreeNode {
|
|
10
|
-
key: string
|
|
11
|
-
children?: TreeNode[]
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface LiosLayoutlProps {
|
|
15
|
-
appName?: any
|
|
16
|
-
productCode: string
|
|
17
|
-
children: any
|
|
18
|
-
menuList: any
|
|
19
|
-
onMenuClick: any
|
|
20
|
-
selectedKeys: string[]
|
|
21
|
-
setSelectKeys: any
|
|
22
|
-
customAction?: any
|
|
23
|
-
actions?: any[]
|
|
24
|
-
myWalletInfo?: {
|
|
25
|
-
availableCashAmount: string
|
|
26
|
-
availableAmount: string
|
|
27
|
-
currency: string
|
|
28
|
-
}
|
|
29
|
-
MyLoginInfo?: {
|
|
30
|
-
isAdmin: any
|
|
31
|
-
}
|
|
32
|
-
amountInfo?: {
|
|
33
|
-
residueNum: string
|
|
34
|
-
currencyCode: string
|
|
35
|
-
}
|
|
36
|
-
myWalletInfoAction?: any
|
|
37
|
-
myLoginInfoAction?: any
|
|
38
|
-
logoutUrl?: string
|
|
39
|
-
switchTenantUrl?: string
|
|
40
|
-
defaultOpenKeys?: string[]
|
|
41
|
-
isHideHeader?: boolean //是否隐藏header
|
|
42
|
-
onCollapse?: (value: boolean) => void
|
|
43
|
-
type?: string
|
|
44
|
-
|
|
45
|
-
umiHistory: any
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export default function LiosLayout(props: LiosLayoutlProps) {
|
|
49
|
-
const {
|
|
50
|
-
appName,
|
|
51
|
-
menuList,
|
|
52
|
-
onMenuClick,
|
|
53
|
-
selectedKeys = [],
|
|
54
|
-
setSelectKeys = () => {},
|
|
55
|
-
customAction,
|
|
56
|
-
actions,
|
|
57
|
-
|
|
58
|
-
defaultOpenKeys,
|
|
59
|
-
myWalletInfo,
|
|
60
|
-
MyLoginInfo,
|
|
61
|
-
amountInfo,
|
|
62
|
-
myWalletInfoAction,
|
|
63
|
-
myLoginInfoAction,
|
|
64
|
-
isHideHeader,
|
|
65
|
-
onCollapse,
|
|
66
|
-
type,
|
|
67
|
-
umiHistory,
|
|
68
|
-
} = props
|
|
69
|
-
|
|
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
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
findPath(menuList, pathname)
|
|
87
|
-
return path
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// 初始化选中菜单
|
|
91
|
-
const [selectKey, setSelectKey] = useState<any>(findKeyPath('/' + location.pathname.split('/')[2]))
|
|
92
|
-
|
|
93
|
-
const [infoOpen, setInfoOpen] = useState<string | null>(null)
|
|
94
|
-
|
|
95
|
-
const logoUrl =
|
|
96
|
-
type === 'console'
|
|
97
|
-
? 'https://cfel-front.oss-cn-hangzhou.aliyuncs.com/logo/company-logo/cfel-logo-white-compress.png'
|
|
98
|
-
: 'https://cfel-front.oss-cn-hangzhou.aliyuncs.com/logo/company-logo/chengfengerlai.png'
|
|
99
|
-
|
|
100
|
-
const subLogoUrl =
|
|
101
|
-
type === 'console'
|
|
102
|
-
? 'https://cfel-front.oss-cn-hangzhou.aliyuncs.com/logo/company-logo/chengfengerlai-white.png'
|
|
103
|
-
: 'https://cfel-front.oss-cn-hangzhou.aliyuncs.com/logo/company-logo/chengfengerlai.png'
|
|
104
|
-
|
|
105
|
-
const { user, logo, subLogo, productCode } = (window as any)?.g_config
|
|
106
|
-
const { name, avatar } = user || {}
|
|
107
|
-
|
|
108
|
-
// 初始化展开菜单
|
|
109
|
-
const [openKeys, setOpenKeys] = useState<any>(defaultOpenKeys || [])
|
|
110
|
-
|
|
111
|
-
//处理搜索菜单后自动展开目录
|
|
112
|
-
const findParentMenu = (menuList: any[], pathname: string) => {
|
|
113
|
-
const result: TreeNode[] = []
|
|
114
|
-
|
|
115
|
-
const findNode = (nodes: TreeNode[], path: TreeNode[]): boolean => {
|
|
116
|
-
for (const node of nodes) {
|
|
117
|
-
if (node.key === pathname) {
|
|
118
|
-
result.push(...path)
|
|
119
|
-
return true
|
|
120
|
-
}
|
|
121
|
-
if (node.children && findNode(node.children, [...path, node])) {
|
|
122
|
-
return true
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
return false
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
findNode(menuList, [])
|
|
129
|
-
return result
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
useEffect(() => {
|
|
133
|
-
//在这里找到当前菜单的上层目录
|
|
134
|
-
const paMenu = findParentMenu(menuList, '/' + location.pathname.split('/')[2])
|
|
135
|
-
//去重
|
|
136
|
-
const set = new Set(paMenu.map((item) => item.key))
|
|
137
|
-
|
|
138
|
-
openKeys.forEach((element: string) => {
|
|
139
|
-
set.add(element)
|
|
140
|
-
})
|
|
141
|
-
setOpenKeys(Array.from(set))
|
|
142
|
-
|
|
143
|
-
// 设置选中的菜单项
|
|
144
|
-
const selectedPath = findKeyPath('/' + location.pathname.split('/')[2])
|
|
145
|
-
setSelectKey(selectedPath)
|
|
146
|
-
}, [location.pathname])
|
|
147
|
-
|
|
148
|
-
// 初始化折叠状态
|
|
149
|
-
const [collapsed, setCollapsed] = useState(localStorage.getItem('layout_collapsed') === 'true')
|
|
150
|
-
const [isCopied, setIsCopied] = useState({
|
|
151
|
-
account: false,
|
|
152
|
-
id: false,
|
|
153
|
-
tenantName: false,
|
|
154
|
-
tenantId: false,
|
|
155
|
-
})
|
|
156
|
-
|
|
157
|
-
const onOpenChange: MenuProps['onOpenChange'] = (keys) => {
|
|
158
|
-
// Find the last opened key
|
|
159
|
-
const latestOpenKey = keys.find((key) => openKeys.indexOf(key) === -1)
|
|
160
|
-
|
|
161
|
-
if (latestOpenKey) {
|
|
162
|
-
// If opening a new key
|
|
163
|
-
const rootSubmenuKeys = menuList.map((item) => item.key)
|
|
164
|
-
|
|
165
|
-
if (rootSubmenuKeys.indexOf(latestOpenKey) === -1) {
|
|
166
|
-
// If it's a third level menu, only keep its parent menu open
|
|
167
|
-
const parentKey = keys.find((key) => rootSubmenuKeys.includes(key))
|
|
168
|
-
setOpenKeys(parentKey ? [parentKey, latestOpenKey] : [latestOpenKey])
|
|
169
|
-
} else {
|
|
170
|
-
// If it's a second level menu, only keep it open
|
|
171
|
-
setOpenKeys([latestOpenKey])
|
|
172
|
-
}
|
|
173
|
-
} else {
|
|
174
|
-
// If closing a menu
|
|
175
|
-
setOpenKeys(keys)
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
const copyTextToClipboard = async (text: string, key: string) => {
|
|
180
|
-
try {
|
|
181
|
-
await navigator.clipboard.writeText(text)
|
|
182
|
-
setIsCopied({ ...isCopied, [key]: true })
|
|
183
|
-
} catch (err) {}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// 菜单动画
|
|
187
|
-
const collapseNode = () => {
|
|
188
|
-
return {
|
|
189
|
-
height: 0,
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
const expandNode = (node: any) => {
|
|
193
|
-
return { height: node.scrollHeight }
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
const inlineMotion = {
|
|
197
|
-
motionName: 'rc-menu-collapse',
|
|
198
|
-
onAppearStart: collapseNode,
|
|
199
|
-
onAppearActive: expandNode,
|
|
200
|
-
onEnterStart: collapseNode,
|
|
201
|
-
onEnterActive: expandNode,
|
|
202
|
-
onLeaveStart: expandNode,
|
|
203
|
-
onLeaveActive: collapseNode,
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
const verticalMotion = {
|
|
207
|
-
motionName: 'rc-menu-open-zoom',
|
|
208
|
-
motionAppear: true,
|
|
209
|
-
motionEnter: true,
|
|
210
|
-
motionLeave: true,
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
return (
|
|
214
|
-
<Layout className="layout-warps-console">
|
|
215
|
-
{Array.isArray(menuList) && menuList.length > 0 && (
|
|
216
|
-
<Sider
|
|
217
|
-
className="layout-side-console"
|
|
218
|
-
collapsible
|
|
219
|
-
trigger={null}
|
|
220
|
-
collapsed={collapsed}
|
|
221
|
-
width={260}
|
|
222
|
-
onCollapse={(value) => {
|
|
223
|
-
if (onCollapse) {
|
|
224
|
-
onCollapse(value)
|
|
225
|
-
}
|
|
226
|
-
localStorage.setItem('layout_collapsed', value.toString())
|
|
227
|
-
setCollapsed(value)
|
|
228
|
-
}}
|
|
229
|
-
>
|
|
230
|
-
<div className="layout-side-mask1-console"></div>
|
|
231
|
-
<div className="layout-side-mask2-console"></div>
|
|
232
|
-
|
|
233
|
-
<div className="header-logo-console" style={{ justifyContent: collapsed ? 'center' : '', paddingLeft: collapsed ? '0' : '' }}>
|
|
234
|
-
<div
|
|
235
|
-
onClick={() => {
|
|
236
|
-
window.open('/home')
|
|
237
|
-
}}
|
|
238
|
-
>
|
|
239
|
-
{!collapsed && <img className={`logo-base current-logo`} src={logo || logoUrl} />}
|
|
240
|
-
{collapsed && <img className={`logo-sub`} src={subLogo || subLogoUrl} />}
|
|
241
|
-
{/* {collapsed && <img className={`logo-base sub-logo`} src={logo || subLogoUrl} />} */}
|
|
242
|
-
</div>
|
|
243
|
-
|
|
244
|
-
{/* {!collapsed && (
|
|
245
|
-
<div
|
|
246
|
-
className='trigger-console'
|
|
247
|
-
onClick={() => {
|
|
248
|
-
setCollapsed(true)
|
|
249
|
-
}}
|
|
250
|
-
>
|
|
251
|
-
<Arrow collapsed={true} type={type} />
|
|
252
|
-
</div>
|
|
253
|
-
)}
|
|
254
|
-
</div>
|
|
255
|
-
|
|
256
|
-
{collapsed && (
|
|
257
|
-
<div style={{ width: '100%', display: 'flex', justifyContent: 'center' }}>
|
|
258
|
-
<div
|
|
259
|
-
className='close-trigger-console'
|
|
260
|
-
onClick={() => {
|
|
261
|
-
localStorage.setItem('layout_collapsed', 'false')
|
|
262
|
-
setCollapsed(false)
|
|
263
|
-
}}
|
|
264
|
-
>
|
|
265
|
-
<Arrow collapsed={false} type={type} />
|
|
266
|
-
</div>
|
|
267
|
-
|
|
268
|
-
)} */}
|
|
269
|
-
</div>
|
|
270
|
-
{!collapsed && <div style={{ height: 24 }}></div>}
|
|
271
|
-
|
|
272
|
-
<div style={{ width: '100%', padding: '0 16px' }}>
|
|
273
|
-
<Search menuList={menuList} collapsed={collapsed} type={type || ''} umiHistory={umiHistory} setSelectKey={setSelectKey} findKeyPath={findKeyPath} />
|
|
274
|
-
</div>
|
|
275
|
-
|
|
276
|
-
{!collapsed && <div style={{ height: 12 }}></div>}
|
|
277
|
-
|
|
278
|
-
<div className="layout-menu-console">
|
|
279
|
-
<RcMenu
|
|
280
|
-
mode={collapsed ? 'vertical' : 'inline'}
|
|
281
|
-
className={`menu-console${collapsed ? '-collapsed' : ''}`}
|
|
282
|
-
motion={collapsed ? verticalMotion : inlineMotion}
|
|
283
|
-
openKeys={openKeys}
|
|
284
|
-
onOpenChange={onOpenChange}
|
|
285
|
-
selectedKeys={selectKey}
|
|
286
|
-
onClick={(item: any) => {
|
|
287
|
-
if (collapsed) return
|
|
288
|
-
setSelectKey(item.keyPath)
|
|
289
|
-
if (onMenuClick) {
|
|
290
|
-
onMenuClick(item)
|
|
291
|
-
}
|
|
292
|
-
}}
|
|
293
|
-
>
|
|
294
|
-
{menuList.map((item: any) => {
|
|
295
|
-
const isSelected = selectKey.includes(item.key)
|
|
296
|
-
if (item.children) {
|
|
297
|
-
let classNames = 'menu-item-label'
|
|
298
|
-
if (isSelected) {
|
|
299
|
-
classNames += ' submenu-selected'
|
|
300
|
-
}
|
|
301
|
-
if (collapsed) {
|
|
302
|
-
return (
|
|
303
|
-
<Popover
|
|
304
|
-
key={item.key}
|
|
305
|
-
align={{
|
|
306
|
-
offset: [33, 0],
|
|
307
|
-
}}
|
|
308
|
-
placement="right"
|
|
309
|
-
arrow={false}
|
|
310
|
-
content={
|
|
311
|
-
<div className="menu-popover">
|
|
312
|
-
{item.children.map((child: any) => {
|
|
313
|
-
if (child.children) {
|
|
314
|
-
return (
|
|
315
|
-
<Popover
|
|
316
|
-
key={child.key}
|
|
317
|
-
align={{
|
|
318
|
-
offset: [30, 0],
|
|
319
|
-
}}
|
|
320
|
-
placement="right"
|
|
321
|
-
arrow={false}
|
|
322
|
-
content={
|
|
323
|
-
<div className="menu-popover" style={{ width: '146px' }}>
|
|
324
|
-
{child.children.map((grandChild: any) => {
|
|
325
|
-
return (
|
|
326
|
-
<MenuItem
|
|
327
|
-
onClick={() => {
|
|
328
|
-
if (onMenuClick) {
|
|
329
|
-
onMenuClick(grandChild)
|
|
330
|
-
}
|
|
331
|
-
}}
|
|
332
|
-
key={grandChild.key}
|
|
333
|
-
className="grand-li"
|
|
334
|
-
>
|
|
335
|
-
<div className="menu-item-content">
|
|
336
|
-
<span className="menu-item-label">{grandChild.label}</span>
|
|
337
|
-
</div>
|
|
338
|
-
</MenuItem>
|
|
339
|
-
)
|
|
340
|
-
})}
|
|
341
|
-
</div>
|
|
342
|
-
}
|
|
343
|
-
>
|
|
344
|
-
<SubMenu
|
|
345
|
-
className="menu-item-content sub-li"
|
|
346
|
-
key={child.key}
|
|
347
|
-
title={
|
|
348
|
-
<div className="sub-list">
|
|
349
|
-
<span className="menu-item-label">{child.label}</span>
|
|
350
|
-
<RightOutlined />
|
|
351
|
-
</div>
|
|
352
|
-
}
|
|
353
|
-
></SubMenu>
|
|
354
|
-
</Popover>
|
|
355
|
-
)
|
|
356
|
-
}
|
|
357
|
-
return (
|
|
358
|
-
<MenuItem
|
|
359
|
-
onClick={() => {
|
|
360
|
-
if (onMenuClick) {
|
|
361
|
-
onMenuClick(child)
|
|
362
|
-
}
|
|
363
|
-
}}
|
|
364
|
-
key={child.key}
|
|
365
|
-
className={`sub-li ${isSelected ? 'sub-selected' : ''}`}
|
|
366
|
-
>
|
|
367
|
-
<div className="menu-item-content sub-list">{child.label}</div>
|
|
368
|
-
</MenuItem>
|
|
369
|
-
)
|
|
370
|
-
})}
|
|
371
|
-
</div>
|
|
372
|
-
}
|
|
373
|
-
>
|
|
374
|
-
<SubMenu
|
|
375
|
-
className="menu-item-content"
|
|
376
|
-
title={
|
|
377
|
-
<div className="sub-list">
|
|
378
|
-
<div>
|
|
379
|
-
<span className={`menu-item-icon ${isSelected ? 'submenu-selected' : ''}`}>{item.icon}</span>
|
|
380
|
-
</div>
|
|
381
|
-
</div>
|
|
382
|
-
}
|
|
383
|
-
></SubMenu>
|
|
384
|
-
</Popover>
|
|
385
|
-
)
|
|
386
|
-
}
|
|
387
|
-
return (
|
|
388
|
-
<SubMenu
|
|
389
|
-
key={item.key}
|
|
390
|
-
className="menu-item-content"
|
|
391
|
-
title={
|
|
392
|
-
<div className="sub-list">
|
|
393
|
-
<div className="menu-item-inner">
|
|
394
|
-
<span className={`menu-item-icon ${isSelected ? 'submenu-selected' : ''}`}>{item.icon}</span>
|
|
395
|
-
{!collapsed && <span className={classNames}>{item.label}</span>}
|
|
396
|
-
</div>
|
|
397
|
-
</div>
|
|
398
|
-
}
|
|
399
|
-
>
|
|
400
|
-
{item.children.map((child: any) => {
|
|
401
|
-
const isSelected = selectKey.includes(child.key)
|
|
402
|
-
if (item.children) {
|
|
403
|
-
let classNames = 'menu-item-label'
|
|
404
|
-
if (isSelected) {
|
|
405
|
-
classNames += ' submenu-selected'
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
if (child.children) {
|
|
409
|
-
return (
|
|
410
|
-
<SubMenu
|
|
411
|
-
className="menu-item-content sub-li"
|
|
412
|
-
key={child.key}
|
|
413
|
-
title={<div className="sub-list">{!collapsed && <span className={`menu-item-label ${isSelected ? 'submenu-selected' : ''}`}>{child.label}</span>}</div>}
|
|
414
|
-
>
|
|
415
|
-
{child.children.map((grandChild: any) => {
|
|
416
|
-
const isSelected = selectKey.includes(grandChild.key)
|
|
417
|
-
if (item.children) {
|
|
418
|
-
let classNames = 'menu-item-label'
|
|
419
|
-
if (isSelected) {
|
|
420
|
-
classNames += ' submenu-selected'
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
return (
|
|
424
|
-
<MenuItem key={grandChild.key} className="grand-li">
|
|
425
|
-
<div className="menu-item-content">{!collapsed && <span className={`menu-item-label ${isSelected ? 'submenu-selected' : ''}`}>{grandChild.label}</span>}</div>
|
|
426
|
-
</MenuItem>
|
|
427
|
-
)
|
|
428
|
-
})}
|
|
429
|
-
</SubMenu>
|
|
430
|
-
)
|
|
431
|
-
}
|
|
432
|
-
return (
|
|
433
|
-
<MenuItem key={child.key} className="sub-li">
|
|
434
|
-
<div className="menu-item-content">{!collapsed && <span className={`menu-item-label ${isSelected ? 'submenu-selected' : ''}`}>{child.label}</span>}</div>
|
|
435
|
-
</MenuItem>
|
|
436
|
-
)
|
|
437
|
-
})}
|
|
438
|
-
</SubMenu>
|
|
439
|
-
)
|
|
440
|
-
}
|
|
441
|
-
// 没有子菜单的
|
|
442
|
-
else {
|
|
443
|
-
let classNames = 'menu-item-label'
|
|
444
|
-
if (isSelected) {
|
|
445
|
-
classNames += ' submenu-selected'
|
|
446
|
-
}
|
|
447
|
-
return (
|
|
448
|
-
<MenuItem key={item.key} className="menu-item-content">
|
|
449
|
-
<div className="first-li">
|
|
450
|
-
<span className={`menu-item-icon ${isSelected ? 'submenu-selected' : ''}`}>{item.icon}</span>
|
|
451
|
-
{!collapsed && <span className={classNames}>{item.label}</span>}
|
|
452
|
-
</div>
|
|
453
|
-
</MenuItem>
|
|
454
|
-
)
|
|
455
|
-
}
|
|
456
|
-
})}
|
|
457
|
-
</RcMenu>
|
|
458
|
-
</div>
|
|
459
|
-
</Sider>
|
|
460
|
-
)}
|
|
461
|
-
|
|
462
|
-
<div className="layout-main-console">
|
|
463
|
-
{!isHideHeader && (
|
|
464
|
-
<div className="layout-header-console">
|
|
465
|
-
{appName && (
|
|
466
|
-
<div className="app-name">
|
|
467
|
-
<strong>{appName}</strong>
|
|
468
|
-
</div>
|
|
469
|
-
)}
|
|
470
|
-
|
|
471
|
-
<div className="layout-header-fill-console" />
|
|
472
|
-
|
|
473
|
-
<div className="layout-header-actions-console">
|
|
474
|
-
{actions?.map((item, index) => {
|
|
475
|
-
return (
|
|
476
|
-
<div className="actions-item" key={index}>
|
|
477
|
-
{item}
|
|
478
|
-
</div>
|
|
479
|
-
)
|
|
480
|
-
})}
|
|
481
|
-
</div>
|
|
482
|
-
|
|
483
|
-
<Popover
|
|
484
|
-
placement="bottom"
|
|
485
|
-
content={
|
|
486
|
-
<UserCard myWalletInfo={myWalletInfo} MyLoginInfo={MyLoginInfo} amountInfo={amountInfo} customAction={customAction} isCopied={isCopied} copyTextToClipboard={copyTextToClipboard} />
|
|
487
|
-
}
|
|
488
|
-
arrow={false}
|
|
489
|
-
trigger="click"
|
|
490
|
-
onOpenChange={(e) => {
|
|
491
|
-
setInfoOpen(e ? 'up' : 'down')
|
|
492
|
-
if (!e) return
|
|
493
|
-
setIsCopied({
|
|
494
|
-
account: false,
|
|
495
|
-
id: false,
|
|
496
|
-
tenantName: false,
|
|
497
|
-
tenantId: false,
|
|
498
|
-
})
|
|
499
|
-
if (myLoginInfoAction) {
|
|
500
|
-
myLoginInfoAction()
|
|
501
|
-
}
|
|
502
|
-
}}
|
|
503
|
-
>
|
|
504
|
-
<div className="layout-header-user-console">
|
|
505
|
-
<img className="avatar" src={avatar} />
|
|
506
|
-
<div className="name">{name}</div>
|
|
507
|
-
<span
|
|
508
|
-
style={{
|
|
509
|
-
display: 'inline-block',
|
|
510
|
-
marginLeft: '4px',
|
|
511
|
-
}}
|
|
512
|
-
className={`iconfont icon-zhankai ${infoOpen ? (infoOpen === 'up' ? 'up' : 'down') : ''}`}
|
|
513
|
-
></span>
|
|
514
|
-
</div>
|
|
515
|
-
</Popover>
|
|
516
|
-
</div>
|
|
517
|
-
)}
|
|
518
|
-
<div className="layout-content-console">{props.children}</div>
|
|
519
|
-
</div>
|
|
520
|
-
</Layout>
|
|
521
|
-
)
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
function Arrow({ collapsed, type }: { collapsed?: boolean; type?: string }) {
|
|
525
|
-
return (
|
|
526
|
-
<svg style={{ transform: !collapsed ? 'rotate(180deg)' : 'rotate(0deg)' }} viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="20" height="20">
|
|
527
|
-
<path
|
|
528
|
-
fill="#FFFFFF"
|
|
529
|
-
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"
|
|
530
|
-
></path>
|
|
531
|
-
</svg>
|
|
532
|
-
)
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
type SearchProps = {
|
|
536
|
-
menuList: TreeNode[]
|
|
537
|
-
collapsed: boolean
|
|
538
|
-
type: string
|
|
539
|
-
umiHistory: any
|
|
540
|
-
setSelectKey: any
|
|
541
|
-
findKeyPath: (pathname: string) => string[]
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
type Router = { label: string; icon?: any; key: string; children?: Router[] }
|
|
545
|
-
|
|
546
|
-
function Search({ menuList, collapsed, type, umiHistory, setSelectKey, findKeyPath }: SearchProps) {
|
|
547
|
-
const [searchTerm, setSearchTerm] = useState('')
|
|
548
|
-
const [searchHistory, setSearchHistory] = useState<Router[]>([])
|
|
549
|
-
const [searchResult, setSearchResult] = useState<Router[]>([])
|
|
550
|
-
const [isFocused, setIsFocused] = useState(false)
|
|
551
|
-
|
|
552
|
-
const name = (window as any).g_config.productCode
|
|
553
|
-
|
|
554
|
-
useEffect(() => {
|
|
555
|
-
const handleKeyDown = (event: KeyboardEvent) => {
|
|
556
|
-
if ((navigator.platform.toLowerCase().includes('mac') ? event.metaKey : event.ctrlKey) && event.key.toLowerCase() === 'k') {
|
|
557
|
-
event.preventDefault()
|
|
558
|
-
const searchInput = document.querySelector('#menu-input') as HTMLInputElement
|
|
559
|
-
if (searchInput) {
|
|
560
|
-
searchInput.focus()
|
|
561
|
-
setIsFocused(true)
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
const handleClickOutside = (event: MouseEvent) => {
|
|
567
|
-
const searchContainer = document.querySelector('.search-container')
|
|
568
|
-
if (searchContainer && !searchContainer.contains(event.target as Node)) {
|
|
569
|
-
setIsFocused(false)
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
document.addEventListener('keydown', handleKeyDown)
|
|
574
|
-
document.addEventListener('mousedown', handleClickOutside)
|
|
575
|
-
|
|
576
|
-
return () => {
|
|
577
|
-
document.removeEventListener('keydown', handleKeyDown)
|
|
578
|
-
document.removeEventListener('mousedown', handleClickOutside)
|
|
579
|
-
}
|
|
580
|
-
}, [])
|
|
581
|
-
|
|
582
|
-
useEffect(() => {
|
|
583
|
-
const searchHistory = localStorage.getItem(name + 'searchHistory')
|
|
584
|
-
if (searchHistory) {
|
|
585
|
-
setSearchHistory(JSON.parse(searchHistory))
|
|
586
|
-
} else {
|
|
587
|
-
setSearchHistory([])
|
|
588
|
-
}
|
|
589
|
-
}, [])
|
|
590
|
-
|
|
591
|
-
useEffect(() => {
|
|
592
|
-
if (searchHistory.length > 5) {
|
|
593
|
-
searchHistory.shift()
|
|
594
|
-
}
|
|
595
|
-
localStorage.setItem(name + 'searchHistory', JSON.stringify(searchHistory))
|
|
596
|
-
}, [searchHistory])
|
|
597
|
-
|
|
598
|
-
const handleSearch = (value: string) => {
|
|
599
|
-
setSearchTerm(value)
|
|
600
|
-
//递归menulist判断是否有包含的
|
|
601
|
-
const searchResults: Router[] = []
|
|
602
|
-
search(menuList as Router[])
|
|
603
|
-
setSearchResult(searchResults)
|
|
604
|
-
function search(data: Router[]) {
|
|
605
|
-
data.forEach((item) => {
|
|
606
|
-
if (typeof item.label === 'string' && item.label.includes(value.toLocaleUpperCase())) {
|
|
607
|
-
searchResults.push(item)
|
|
608
|
-
}
|
|
609
|
-
if (item.children) {
|
|
610
|
-
search(item.children)
|
|
611
|
-
}
|
|
612
|
-
})
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
const enter = (item: Router) => {
|
|
617
|
-
setIsFocused(false)
|
|
618
|
-
//如果搜索历史里面有这个item,就不再添加
|
|
619
|
-
if (searchHistory.findIndex((i) => i.key === item.key) === -1) {
|
|
620
|
-
setSearchHistory([...searchHistory, item])
|
|
621
|
-
}
|
|
622
|
-
//如果是目录就找到目录下第一个菜单进入
|
|
623
|
-
if (!item.key.includes('/')) {
|
|
624
|
-
//递归找到目录下第一个菜单
|
|
625
|
-
const findFirst = (data: Router[]): Router | undefined => {
|
|
626
|
-
for (let i = 0; i < data.length; i++) {
|
|
627
|
-
if (data[i].key.includes('/')) {
|
|
628
|
-
return data[i]
|
|
629
|
-
} else {
|
|
630
|
-
return findFirst(data[i].children || [])
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
const firstItem = findFirst(item.children || [])
|
|
635
|
-
if (firstItem) {
|
|
636
|
-
setSelectKey(findKeyPath(firstItem.key)) // 记住keypath
|
|
637
|
-
umiHistory.push(firstItem.key, '_self')
|
|
638
|
-
}
|
|
639
|
-
} else {
|
|
640
|
-
setSelectKey(findKeyPath(item.key)) // 记住keypath
|
|
641
|
-
umiHistory.push(item.key, '_self')
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
const deleteHistory = (item: Router) => {
|
|
646
|
-
setSearchHistory(searchHistory.filter((i) => i.key !== item.key))
|
|
647
|
-
}
|
|
648
|
-
return (
|
|
649
|
-
<>
|
|
650
|
-
{!collapsed && (
|
|
651
|
-
<div className="search-container">
|
|
652
|
-
<div className="search-console">
|
|
653
|
-
<div className="search-bg-mask">
|
|
654
|
-
<img src="https://cfel-front.oss-cn-hangzhou.aliyuncs.com/logo/base-component/menu-search-bg-console.png" />
|
|
655
|
-
</div>
|
|
656
|
-
<input
|
|
657
|
-
autoComplete="off"
|
|
658
|
-
id="menu-input"
|
|
659
|
-
value={searchTerm}
|
|
660
|
-
onChange={(e) => handleSearch(e.target.value)}
|
|
661
|
-
className="search-input"
|
|
662
|
-
placeholder="搜索菜单..."
|
|
663
|
-
onFocus={() => setIsFocused(true)}
|
|
664
|
-
onBlur={(e) => {
|
|
665
|
-
if (!e.relatedTarget?.closest('.lists-console')) {
|
|
666
|
-
setIsFocused(false)
|
|
667
|
-
}
|
|
668
|
-
}}
|
|
669
|
-
/>
|
|
670
|
-
<div className="search-icon">
|
|
671
|
-
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="18" height="18">
|
|
672
|
-
<path
|
|
673
|
-
fill="#C3CAEF"
|
|
674
|
-
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"
|
|
675
|
-
></path>
|
|
676
|
-
</svg>
|
|
677
|
-
</div>
|
|
678
|
-
<div className="search-command" style={{ width: navigator.platform.toLowerCase().includes('mac') ? '' : '50px' }}>
|
|
679
|
-
{navigator.platform.toLowerCase().includes('mac') ? '⌘' : 'Ctrl+'}K
|
|
680
|
-
</div>
|
|
681
|
-
|
|
682
|
-
{/* <div
|
|
683
|
-
className='search-command'
|
|
684
|
-
style={{ width: '50px' }}
|
|
685
|
-
>
|
|
686
|
-
{'Ctrl+'}K
|
|
687
|
-
</div> */}
|
|
688
|
-
</div>
|
|
689
|
-
<div>
|
|
690
|
-
{isFocused && (
|
|
691
|
-
<>
|
|
692
|
-
{searchTerm ? (
|
|
693
|
-
<List
|
|
694
|
-
tabIndex={-1}
|
|
695
|
-
split={false}
|
|
696
|
-
className="lists-console"
|
|
697
|
-
size="small"
|
|
698
|
-
bordered
|
|
699
|
-
dataSource={searchResult}
|
|
700
|
-
renderItem={(item) => <List.Item onClick={() => enter(item)}>{item.label}</List.Item>}
|
|
701
|
-
/>
|
|
702
|
-
) : (
|
|
703
|
-
<List
|
|
704
|
-
tabIndex={-1}
|
|
705
|
-
split={false}
|
|
706
|
-
className="lists-console"
|
|
707
|
-
header="最近访问"
|
|
708
|
-
size="small"
|
|
709
|
-
bordered
|
|
710
|
-
dataSource={searchHistory}
|
|
711
|
-
renderItem={(item) => {
|
|
712
|
-
return (
|
|
713
|
-
<div
|
|
714
|
-
className={'search-item'}
|
|
715
|
-
style={{
|
|
716
|
-
display: 'flex',
|
|
717
|
-
justifyContent: 'space-between',
|
|
718
|
-
alignItems: 'center',
|
|
719
|
-
}}
|
|
720
|
-
>
|
|
721
|
-
<List.Item onClick={() => enter(item)}>{item.label}</List.Item>
|
|
722
|
-
<div
|
|
723
|
-
style={{ paddingRight: 10, cursor: 'pointer' }}
|
|
724
|
-
onClick={() => {
|
|
725
|
-
deleteHistory(item)
|
|
726
|
-
}}
|
|
727
|
-
>
|
|
728
|
-
<CloseCircleOutlined />
|
|
729
|
-
</div>
|
|
730
|
-
</div>
|
|
731
|
-
)
|
|
732
|
-
}}
|
|
733
|
-
/>
|
|
734
|
-
)}
|
|
735
|
-
</>
|
|
736
|
-
)}
|
|
737
|
-
</div>
|
|
738
|
-
</div>
|
|
739
|
-
)}
|
|
740
|
-
</>
|
|
741
|
-
)
|
|
742
|
-
}
|