cfel-base-components 2.5.43 → 2.5.45
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/components/layout/index.scss +488 -60
- package/src/components/layout/index.tsx +391 -40
- package/src/components/layout-copy/index.scss +169 -0
- package/src/components/layout-copy/index.tsx +218 -0
- package/src/components/layout-copy/user-card/index.scss +180 -0
- package/src/components/layout-copy/user-card/index.tsx +162 -0
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import React, { useEffect, useState } from 'react'
|
|
2
|
-
import { Layout, Menu, MenuProps, Popover } from 'antd'
|
|
2
|
+
import { Layout, List, Menu, MenuProps, Popover } from 'antd'
|
|
3
3
|
import UserCard from './user-card'
|
|
4
|
+
import { useMemo } from 'react'
|
|
5
|
+
import RcMenu, { SubMenu, MenuItem } from 'rc-menu'
|
|
6
|
+
import { CloseCircleOutlined } from '@ant-design/icons'
|
|
4
7
|
import './index.scss'
|
|
5
|
-
|
|
6
8
|
const { Sider } = Layout
|
|
7
9
|
|
|
8
10
|
export interface LiosLayoutlProps {
|
|
@@ -10,9 +12,10 @@ export interface LiosLayoutlProps {
|
|
|
10
12
|
productCode: string
|
|
11
13
|
children: any
|
|
12
14
|
menuList: any
|
|
13
|
-
onMenuClick:
|
|
15
|
+
onMenuClick: any
|
|
14
16
|
selectedKeys: string[]
|
|
15
|
-
|
|
17
|
+
setSelectKeys: (keys: string[]) => void
|
|
18
|
+
customAction?: any
|
|
16
19
|
actions?: any[]
|
|
17
20
|
myWalletInfo?: {
|
|
18
21
|
availableCashAmount: string
|
|
@@ -26,22 +29,23 @@ export interface LiosLayoutlProps {
|
|
|
26
29
|
residueNum: string
|
|
27
30
|
currencyCode: string
|
|
28
31
|
}
|
|
29
|
-
myWalletInfoAction?:
|
|
30
|
-
myLoginInfoAction?:
|
|
32
|
+
myWalletInfoAction?: any
|
|
33
|
+
myLoginInfoAction?: any
|
|
31
34
|
logoutUrl?: string
|
|
32
35
|
switchTenantUrl?: string
|
|
33
36
|
defaultOpenKeys?: string[]
|
|
34
37
|
isHideHeader?: boolean //是否隐藏header
|
|
38
|
+
onCollapse?: (value: boolean) => void
|
|
39
|
+
type?: string
|
|
35
40
|
}
|
|
36
41
|
|
|
37
42
|
export default function LiosLayout(props: LiosLayoutlProps) {
|
|
38
43
|
const {
|
|
39
44
|
appName,
|
|
40
|
-
productCode,
|
|
41
45
|
menuList,
|
|
42
46
|
onMenuClick,
|
|
43
|
-
selectedKeys,
|
|
44
|
-
|
|
47
|
+
selectedKeys = [],
|
|
48
|
+
setSelectKeys = () => {},
|
|
45
49
|
customAction,
|
|
46
50
|
actions,
|
|
47
51
|
|
|
@@ -52,9 +56,21 @@ export default function LiosLayout(props: LiosLayoutlProps) {
|
|
|
52
56
|
myWalletInfoAction,
|
|
53
57
|
myLoginInfoAction,
|
|
54
58
|
isHideHeader,
|
|
59
|
+
onCollapse,
|
|
60
|
+
type,
|
|
55
61
|
} = props
|
|
56
62
|
|
|
57
|
-
const
|
|
63
|
+
const logoUrl =
|
|
64
|
+
type === 'console'
|
|
65
|
+
? 'https://cfel-front.oss-cn-hangzhou.aliyuncs.com/logo/company-logo/cfel-logo-white-compress.png'
|
|
66
|
+
: 'https://cfel-front.oss-cn-hangzhou.aliyuncs.com/logo/company-logo/chengfengerlai.png'
|
|
67
|
+
|
|
68
|
+
const subLogoUrl =
|
|
69
|
+
type === 'console'
|
|
70
|
+
? 'https://cfel-front.oss-cn-hangzhou.aliyuncs.com/logo/company-logo/chengfengerlai-white.png'
|
|
71
|
+
: 'https://cfel-front.oss-cn-hangzhou.aliyuncs.com/logo/company-logo/chengfengerlai.png'
|
|
72
|
+
|
|
73
|
+
const { user, logo, subLogo, productCode } = (window as any)?.g_config
|
|
58
74
|
const { name, avatar } = user || {}
|
|
59
75
|
|
|
60
76
|
const [openKeys, setOpenKeys] = useState<any>(defaultOpenKeys || [])
|
|
@@ -83,6 +99,7 @@ export default function LiosLayout(props: LiosLayoutlProps) {
|
|
|
83
99
|
findNode(menuList, [])
|
|
84
100
|
return result
|
|
85
101
|
}
|
|
102
|
+
|
|
86
103
|
useEffect(() => {
|
|
87
104
|
//在这里找到当前菜单的上层目录
|
|
88
105
|
const paMenu = findParentMenu(menuList, '/' + location.pathname.split('/')[2])
|
|
@@ -94,7 +111,6 @@ export default function LiosLayout(props: LiosLayoutlProps) {
|
|
|
94
111
|
setOpenKeys(Array.from(set))
|
|
95
112
|
}, [location.pathname])
|
|
96
113
|
|
|
97
|
-
|
|
98
114
|
const [collapsed, setCollapsed] = useState(localStorage.getItem('layout_collapsed') === 'true')
|
|
99
115
|
const [isCopied, setIsCopied] = useState({
|
|
100
116
|
account: false,
|
|
@@ -114,51 +130,204 @@ export default function LiosLayout(props: LiosLayoutlProps) {
|
|
|
114
130
|
} catch (err) {}
|
|
115
131
|
}
|
|
116
132
|
|
|
133
|
+
const style = useMemo(() => {
|
|
134
|
+
if (collapsed) {
|
|
135
|
+
return {
|
|
136
|
+
style: {
|
|
137
|
+
padding: '0',
|
|
138
|
+
paddingTop: '24px',
|
|
139
|
+
},
|
|
140
|
+
}
|
|
141
|
+
} else {
|
|
142
|
+
return {
|
|
143
|
+
style: {},
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}, [collapsed])
|
|
147
|
+
|
|
148
|
+
const collapseNode = () => {
|
|
149
|
+
return {
|
|
150
|
+
height: 0,
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const expandNode = (node: any) => {
|
|
154
|
+
return { height: node.scrollHeight }
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const inlineMotion = {
|
|
158
|
+
motionName: 'rc-menu-collapse',
|
|
159
|
+
onAppearStart: collapseNode,
|
|
160
|
+
onAppearActive: expandNode,
|
|
161
|
+
onEnterStart: collapseNode,
|
|
162
|
+
onEnterActive: expandNode,
|
|
163
|
+
onLeaveStart: expandNode,
|
|
164
|
+
onLeaveActive: collapseNode,
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const verticalMotion = {
|
|
168
|
+
motionName: 'rc-menu-open-zoom',
|
|
169
|
+
motionAppear: true,
|
|
170
|
+
motionEnter: true,
|
|
171
|
+
motionLeave: true,
|
|
172
|
+
}
|
|
173
|
+
|
|
117
174
|
return (
|
|
118
|
-
<Layout className="layout-
|
|
175
|
+
<Layout className="layout-warps">
|
|
119
176
|
{Array.isArray(menuList) && menuList.length > 0 && (
|
|
120
177
|
<Sider
|
|
121
178
|
className="layout-side"
|
|
122
|
-
style={{
|
|
123
|
-
backgroundSize: collapsed ? '1800%' : '900%',
|
|
124
|
-
}}
|
|
125
179
|
collapsible
|
|
180
|
+
trigger={null}
|
|
126
181
|
collapsed={collapsed}
|
|
127
|
-
width={
|
|
182
|
+
width={260}
|
|
128
183
|
onCollapse={(value) => {
|
|
184
|
+
if (onCollapse) {
|
|
185
|
+
onCollapse(value)
|
|
186
|
+
}
|
|
129
187
|
localStorage.setItem('layout_collapsed', value.toString())
|
|
130
188
|
setCollapsed(value)
|
|
131
189
|
}}
|
|
132
190
|
>
|
|
133
|
-
<div
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
<img
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
191
|
+
<div className="header-logo" style={{ justifyContent: collapsed ? 'center' : '', paddingLeft: collapsed ? '0' : '' }}>
|
|
192
|
+
<div
|
|
193
|
+
onClick={() => {
|
|
194
|
+
window.open('/home')
|
|
195
|
+
}}
|
|
196
|
+
>
|
|
197
|
+
{!collapsed && <img className={`logo-base current-logo`} src={logo || logoUrl} />}
|
|
198
|
+
|
|
199
|
+
{collapsed && <img className={`logo-base sub-logo`} src={logo || subLogoUrl} />}
|
|
200
|
+
</div>
|
|
201
|
+
|
|
202
|
+
{/* {!collapsed && (
|
|
203
|
+
<div
|
|
204
|
+
className="trigger"
|
|
205
|
+
onClick={() => {
|
|
206
|
+
setCollapsed(true)
|
|
207
|
+
}}
|
|
208
|
+
>
|
|
209
|
+
<Arrow collapsed={true} />
|
|
210
|
+
</div>
|
|
211
|
+
)} */}
|
|
212
|
+
</div>
|
|
213
|
+
|
|
214
|
+
{/* {collapsed && (
|
|
215
|
+
<div style={{ width: '100%', display: 'flex', justifyContent: 'center' }}>
|
|
216
|
+
<div
|
|
217
|
+
className="close-trigger"
|
|
218
|
+
onClick={() => {
|
|
219
|
+
setCollapsed(false)
|
|
220
|
+
}}
|
|
221
|
+
>
|
|
222
|
+
<Arrow collapsed={false} />
|
|
223
|
+
</div>
|
|
224
|
+
</div>
|
|
225
|
+
)} */}
|
|
226
|
+
|
|
227
|
+
<div style={{ height: 24 }}></div>
|
|
228
|
+
|
|
229
|
+
<div style={{ width: '100%', display: 'flex', justifyContent: 'center' }}>
|
|
230
|
+
<Search menuList={menuList} collapsed={collapsed} type={type || ''} />
|
|
147
231
|
</div>
|
|
148
232
|
|
|
149
|
-
<div
|
|
150
|
-
|
|
151
|
-
|
|
233
|
+
{!collapsed && <div style={{ height: 24 }}></div>}
|
|
234
|
+
|
|
235
|
+
<div className="layout-menu">
|
|
236
|
+
<RcMenu
|
|
237
|
+
mode={collapsed ? 'vertical' : 'inline'}
|
|
238
|
+
className={`menu${collapsed ? '-collapsed' : ''}`}
|
|
239
|
+
motion={collapsed ? verticalMotion : inlineMotion}
|
|
152
240
|
openKeys={openKeys}
|
|
153
241
|
onOpenChange={onOpenChange}
|
|
154
|
-
|
|
242
|
+
selectedKeys={selectedKeys}
|
|
155
243
|
onClick={(item): any => {
|
|
156
|
-
|
|
244
|
+
setSelectKeys(item.keyPath)
|
|
245
|
+
if (onMenuClick) {
|
|
246
|
+
onMenuClick(item)
|
|
247
|
+
}
|
|
157
248
|
}}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
249
|
+
triggerSubMenuAction="hover"
|
|
250
|
+
>
|
|
251
|
+
{menuList.map((item: any) => {
|
|
252
|
+
const isSelected = selectedKeys.includes(item.key)
|
|
253
|
+
if (item.children) {
|
|
254
|
+
let classNames = 'menu-item-label'
|
|
255
|
+
if (isSelected) {
|
|
256
|
+
classNames += ' submenu-selected'
|
|
257
|
+
}
|
|
258
|
+
return (
|
|
259
|
+
<SubMenu
|
|
260
|
+
popupClassName="rc-menu-submenu-popup"
|
|
261
|
+
key={item.key}
|
|
262
|
+
className="menu-item-content"
|
|
263
|
+
title={
|
|
264
|
+
<div className="sub-list">
|
|
265
|
+
<div className="menu-item-inner">
|
|
266
|
+
<span className={`menu-item-icon ${isSelected ? 'submenu-selected' : ''}`}>{item.icon}</span>
|
|
267
|
+
{!collapsed && <span className={classNames}>{item.label}</span>}
|
|
268
|
+
</div>
|
|
269
|
+
</div>
|
|
270
|
+
}
|
|
271
|
+
>
|
|
272
|
+
{item.children.map((child: any) => {
|
|
273
|
+
const isSelected = selectedKeys.includes(child.key)
|
|
274
|
+
if (item.children) {
|
|
275
|
+
let classNames = 'menu-item-label'
|
|
276
|
+
if (isSelected) {
|
|
277
|
+
classNames += ' submenu-selected'
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
if (child.children) {
|
|
281
|
+
return (
|
|
282
|
+
<SubMenu
|
|
283
|
+
popupClassName="rc-menu-submenu-popup"
|
|
284
|
+
className="menu-item-content sub-li"
|
|
285
|
+
key={child.key}
|
|
286
|
+
title={<div className="sub-list">{!collapsed && <span className={`menu-item-label ${isSelected ? 'submenu-selected' : ''}`}>{child.label}</span>}</div>}
|
|
287
|
+
>
|
|
288
|
+
{child.children.map((grandChild: any) => {
|
|
289
|
+
const isSelected = selectedKeys.includes(grandChild.key)
|
|
290
|
+
if (item.children) {
|
|
291
|
+
let classNames = 'menu-item-label'
|
|
292
|
+
if (isSelected) {
|
|
293
|
+
classNames += ' submenu-selected'
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return (
|
|
297
|
+
<MenuItem key={grandChild.key} className="grand-li">
|
|
298
|
+
<div className="menu-item-content">{!collapsed && <span className={`menu-item-label ${isSelected ? 'submenu-selected' : ''}`}>{grandChild.label}</span>}</div>
|
|
299
|
+
</MenuItem>
|
|
300
|
+
)
|
|
301
|
+
})}
|
|
302
|
+
</SubMenu>
|
|
303
|
+
)
|
|
304
|
+
}
|
|
305
|
+
return (
|
|
306
|
+
<MenuItem key={child.key} className="sub-li">
|
|
307
|
+
<div className="menu-item-content">{!collapsed && <span className={`menu-item-label ${isSelected ? 'submenu-selected' : ''}`}>{child.label}</span>}</div>
|
|
308
|
+
</MenuItem>
|
|
309
|
+
)
|
|
310
|
+
})}
|
|
311
|
+
</SubMenu>
|
|
312
|
+
)
|
|
313
|
+
}
|
|
314
|
+
// 没有子菜单的
|
|
315
|
+
else {
|
|
316
|
+
let classNames = 'menu-item-label'
|
|
317
|
+
if (isSelected) {
|
|
318
|
+
classNames += ' submenu-selected'
|
|
319
|
+
}
|
|
320
|
+
return (
|
|
321
|
+
<MenuItem key={item.key} className="menu-item-content">
|
|
322
|
+
<div>
|
|
323
|
+
<span className={`menu-item-icon ${isSelected ? 'submenu-selected' : ''}`}>{item.icon}</span>
|
|
324
|
+
{!collapsed && <span className={classNames}>{item.label}</span>}
|
|
325
|
+
</div>
|
|
326
|
+
</MenuItem>
|
|
327
|
+
)
|
|
328
|
+
}
|
|
329
|
+
})}
|
|
330
|
+
</RcMenu>
|
|
162
331
|
</div>
|
|
163
332
|
</Sider>
|
|
164
333
|
)}
|
|
@@ -199,7 +368,9 @@ export default function LiosLayout(props: LiosLayoutlProps) {
|
|
|
199
368
|
tenantName: false,
|
|
200
369
|
tenantId: false,
|
|
201
370
|
})
|
|
202
|
-
|
|
371
|
+
if (myLoginInfoAction) {
|
|
372
|
+
myLoginInfoAction()
|
|
373
|
+
}
|
|
203
374
|
}}
|
|
204
375
|
>
|
|
205
376
|
<div className="layout-header-user">
|
|
@@ -214,3 +385,183 @@ export default function LiosLayout(props: LiosLayoutlProps) {
|
|
|
214
385
|
</Layout>
|
|
215
386
|
)
|
|
216
387
|
}
|
|
388
|
+
|
|
389
|
+
function Arrow({ collapsed }: { collapsed?: boolean }) {
|
|
390
|
+
return (
|
|
391
|
+
<div>
|
|
392
|
+
<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">
|
|
393
|
+
<path
|
|
394
|
+
fill="#7D8295"
|
|
395
|
+
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"
|
|
396
|
+
></path>
|
|
397
|
+
</svg>
|
|
398
|
+
</div>
|
|
399
|
+
)
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
function Search({ menuList, collapsed, type }: { menuList: any; collapsed: boolean; type: string }) {
|
|
403
|
+
useEffect(() => {
|
|
404
|
+
const handleKeyDown = (event: KeyboardEvent) => {
|
|
405
|
+
// Check for Ctrl+K (Windows) or Cmd+K (Mac)
|
|
406
|
+
if ((navigator.platform.toLowerCase().includes('mac') ? event.metaKey : event.ctrlKey) && event.key.toLowerCase() === 'k') {
|
|
407
|
+
event.preventDefault()
|
|
408
|
+
const searchInput = document.querySelector('#menu-input') as HTMLInputElement
|
|
409
|
+
if (searchInput) {
|
|
410
|
+
searchInput.focus()
|
|
411
|
+
setIsHovered(true)
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
document.addEventListener('keydown', handleKeyDown)
|
|
417
|
+
return () => {
|
|
418
|
+
document.removeEventListener('keydown', handleKeyDown)
|
|
419
|
+
}
|
|
420
|
+
}, [])
|
|
421
|
+
type Router = { label: string; icon?: any; key: string; children?: Router[] }
|
|
422
|
+
|
|
423
|
+
const name = (window as any).g_config.productCode
|
|
424
|
+
|
|
425
|
+
const [searchTerm, setSearchTerm] = useState('')
|
|
426
|
+
const [searchHistory, setSearchHistory] = useState<Router[]>([])
|
|
427
|
+
const [searchResult, setSearchResult] = useState<Router[]>([])
|
|
428
|
+
const [isHovered, setIsHovered] = useState(false)
|
|
429
|
+
|
|
430
|
+
useEffect(() => {
|
|
431
|
+
const searchHistory = localStorage.getItem(name + 'searchHistory')
|
|
432
|
+
if (searchHistory) {
|
|
433
|
+
setSearchHistory(JSON.parse(searchHistory))
|
|
434
|
+
} else {
|
|
435
|
+
setSearchHistory([])
|
|
436
|
+
}
|
|
437
|
+
}, [])
|
|
438
|
+
|
|
439
|
+
useEffect(() => {
|
|
440
|
+
if (searchHistory.length > 5) {
|
|
441
|
+
searchHistory.shift()
|
|
442
|
+
}
|
|
443
|
+
localStorage.setItem(name + 'searchHistory', JSON.stringify(searchHistory))
|
|
444
|
+
}, [searchHistory])
|
|
445
|
+
|
|
446
|
+
const handleSearch = (value: string) => {
|
|
447
|
+
setSearchTerm(value)
|
|
448
|
+
//递归menulist判断是否有包含的
|
|
449
|
+
const searchResults: Router[] = []
|
|
450
|
+
search(menuList)
|
|
451
|
+
setSearchResult(searchResults)
|
|
452
|
+
function search(data: Router[]) {
|
|
453
|
+
data.forEach((item) => {
|
|
454
|
+
if (item.label.includes(value.toLocaleUpperCase())) {
|
|
455
|
+
searchResults.push(item)
|
|
456
|
+
}
|
|
457
|
+
if (item.children) {
|
|
458
|
+
search(item.children)
|
|
459
|
+
}
|
|
460
|
+
})
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
const enter = (item: Router) => {
|
|
465
|
+
setIsHovered(false)
|
|
466
|
+
//如果搜索历史里面有这个item,就不再添加
|
|
467
|
+
if (searchHistory.findIndex((i) => i.key === item.key) === -1) {
|
|
468
|
+
setSearchHistory([...searchHistory, item])
|
|
469
|
+
}
|
|
470
|
+
//如果是目录就找到目录下第一个菜单进入
|
|
471
|
+
if (!item.key.includes('/')) {
|
|
472
|
+
//递归找到目录下第一个菜单
|
|
473
|
+
const findFirst = (data: Router[]): Router | undefined => {
|
|
474
|
+
for (let i = 0; i < data.length; i++) {
|
|
475
|
+
if (data[i].key.includes('/')) {
|
|
476
|
+
return data[i]
|
|
477
|
+
} else {
|
|
478
|
+
return findFirst(data[i].children || [])
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
const firstItem = findFirst(item.children || [])
|
|
483
|
+
if (firstItem) {
|
|
484
|
+
//history.push(firstItem.key, '_self')
|
|
485
|
+
}
|
|
486
|
+
} else {
|
|
487
|
+
// history.push(item.key, '_self')
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
const deleteHistory = (item: Router) => {
|
|
492
|
+
setSearchHistory(searchHistory.filter((i) => i.key !== item.key))
|
|
493
|
+
}
|
|
494
|
+
return (
|
|
495
|
+
<>
|
|
496
|
+
{collapsed ? (
|
|
497
|
+
<div className="search-mobile">
|
|
498
|
+
{' '}
|
|
499
|
+
<div className="search-icon">
|
|
500
|
+
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="18" height="18">
|
|
501
|
+
<path
|
|
502
|
+
fill="#B3A6F4"
|
|
503
|
+
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
|
+
></path>
|
|
505
|
+
</svg>
|
|
506
|
+
</div>
|
|
507
|
+
</div>
|
|
508
|
+
) : (
|
|
509
|
+
<div onMouseEnter={() => setIsHovered(true)} onMouseLeave={() => setIsHovered(false)}>
|
|
510
|
+
<div className="search">
|
|
511
|
+
<input id="menu-input" value={searchTerm} onChange={(e) => handleSearch(e.target.value)} className="search-input" placeholder="搜索菜单" />
|
|
512
|
+
<div className="search-icon">
|
|
513
|
+
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="18" height="18">
|
|
514
|
+
<path
|
|
515
|
+
fill={type === 'console' ? '#C2B7F6' : '#817F9B'}
|
|
516
|
+
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"
|
|
517
|
+
></path>
|
|
518
|
+
</svg>
|
|
519
|
+
</div>
|
|
520
|
+
<div className="search-command">{navigator.platform.toLowerCase().includes('mac') ? '⌘' : '⊞'}K</div>
|
|
521
|
+
</div>
|
|
522
|
+
<div>
|
|
523
|
+
{isHovered && (
|
|
524
|
+
<>
|
|
525
|
+
{searchTerm ? (
|
|
526
|
+
<List split={false} className="list" size="small" bordered dataSource={searchResult} renderItem={(item) => <List.Item onClick={() => enter(item)}>{item.label}</List.Item>} />
|
|
527
|
+
) : (
|
|
528
|
+
<List
|
|
529
|
+
split={false}
|
|
530
|
+
className="list"
|
|
531
|
+
header={<div>最近访问</div>}
|
|
532
|
+
size="small"
|
|
533
|
+
bordered
|
|
534
|
+
dataSource={searchHistory}
|
|
535
|
+
renderItem={(item) => {
|
|
536
|
+
return (
|
|
537
|
+
<div
|
|
538
|
+
className={'search-item'}
|
|
539
|
+
style={{
|
|
540
|
+
display: 'flex',
|
|
541
|
+
justifyContent: 'space-between',
|
|
542
|
+
alignItems: 'center',
|
|
543
|
+
}}
|
|
544
|
+
onClick={() => enter(item)}
|
|
545
|
+
>
|
|
546
|
+
<List.Item>{item.label}</List.Item>
|
|
547
|
+
<div
|
|
548
|
+
style={{ paddingRight: 10 }}
|
|
549
|
+
onClick={() => {
|
|
550
|
+
deleteHistory(item)
|
|
551
|
+
}}
|
|
552
|
+
>
|
|
553
|
+
<CloseCircleOutlined />
|
|
554
|
+
</div>
|
|
555
|
+
</div>
|
|
556
|
+
)
|
|
557
|
+
}}
|
|
558
|
+
/>
|
|
559
|
+
)}
|
|
560
|
+
</>
|
|
561
|
+
)}
|
|
562
|
+
</div>
|
|
563
|
+
</div>
|
|
564
|
+
)}
|
|
565
|
+
</>
|
|
566
|
+
)
|
|
567
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
$header-height: 60px;
|
|
2
|
+
$base-color: #c6538c;
|
|
3
|
+
|
|
4
|
+
body {
|
|
5
|
+
overflow: hidden;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.layout-warp {
|
|
9
|
+
display: flex;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.ant-layout .ant-layout-sider {
|
|
13
|
+
background-image: linear-gradient(
|
|
14
|
+
-45deg,
|
|
15
|
+
rgba(103, 200, 21, 0.5),
|
|
16
|
+
rgba(55, 96, 244, 0.5),
|
|
17
|
+
rgba(245, 34, 45, 0.7)
|
|
18
|
+
);
|
|
19
|
+
background-position: center;
|
|
20
|
+
// background-color: #fff;
|
|
21
|
+
// background-color: #13c2c2;
|
|
22
|
+
background-color: #08979c;
|
|
23
|
+
// background-color: #531dab;
|
|
24
|
+
// background-color: #389e0d;
|
|
25
|
+
|
|
26
|
+
.ant-layout-sider-trigger {
|
|
27
|
+
background: transparent;
|
|
28
|
+
&:hover {
|
|
29
|
+
background: rgba(0, 0, 0, 0.12);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.layout-side {
|
|
35
|
+
height: 100vh;
|
|
36
|
+
user-select: none;
|
|
37
|
+
overflow: hidden;
|
|
38
|
+
|
|
39
|
+
.layout-logo {
|
|
40
|
+
cursor: pointer;
|
|
41
|
+
height: 60px;
|
|
42
|
+
margin: 8px auto;
|
|
43
|
+
display: flex;
|
|
44
|
+
justify-content: center;
|
|
45
|
+
align-items: center;
|
|
46
|
+
width: 100%;
|
|
47
|
+
z-index: 1;
|
|
48
|
+
|
|
49
|
+
.logo-img {
|
|
50
|
+
position: absolute;
|
|
51
|
+
height: 60px;
|
|
52
|
+
line-height: 60px;
|
|
53
|
+
object-fit: cover;
|
|
54
|
+
transition: all 0.8s cubic-bezier(0.645, 0.045, 0.355, 1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.current-logo {
|
|
58
|
+
left: 0;
|
|
59
|
+
right: 0;
|
|
60
|
+
margin: auto;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.hide-logo {
|
|
64
|
+
left: -500px;
|
|
65
|
+
}
|
|
66
|
+
.hide-sub-logo {
|
|
67
|
+
right: -500px;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.layout-menu-container {
|
|
72
|
+
height: calc(100vh - 60px - 16px - 48px);
|
|
73
|
+
overflow: auto;
|
|
74
|
+
.ant-menu {
|
|
75
|
+
background: transparent !important;
|
|
76
|
+
}
|
|
77
|
+
.ant-menu-item-selected {
|
|
78
|
+
background: rgba(255, 255, 255, 0.3) !important;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.layout-header {
|
|
84
|
+
height: $header-height;
|
|
85
|
+
background: white;
|
|
86
|
+
z-index: 1;
|
|
87
|
+
position: relative;
|
|
88
|
+
display: flex;
|
|
89
|
+
justify-content: flex-start;
|
|
90
|
+
align-items: center;
|
|
91
|
+
|
|
92
|
+
.app-name {
|
|
93
|
+
margin-left: 24px;
|
|
94
|
+
font-weight: 500;
|
|
95
|
+
color: rgba(0, 0, 0, 0.65);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.layout-header-fill {
|
|
99
|
+
flex: 1;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.layout-header-actions {
|
|
103
|
+
display: flex;
|
|
104
|
+
justify-content: flex-start;
|
|
105
|
+
align-items: center;
|
|
106
|
+
height: 100%;
|
|
107
|
+
max-width: 400px;
|
|
108
|
+
z-index: 2;
|
|
109
|
+
|
|
110
|
+
.actions-item {
|
|
111
|
+
height: 36px;
|
|
112
|
+
border-radius: 6px;
|
|
113
|
+
transition: all 0.3s;
|
|
114
|
+
cursor: pointer;
|
|
115
|
+
margin: 0 4px;
|
|
116
|
+
padding: 0 4px;
|
|
117
|
+
|
|
118
|
+
display: flex;
|
|
119
|
+
justify-content: center;
|
|
120
|
+
align-items: center;
|
|
121
|
+
|
|
122
|
+
&:hover {
|
|
123
|
+
background: rgba(0, 0, 0, 0.06);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.layout-header-user {
|
|
129
|
+
height: 48px;
|
|
130
|
+
display: flex;
|
|
131
|
+
justify-content: flex-start;
|
|
132
|
+
align-items: center;
|
|
133
|
+
z-index: 2;
|
|
134
|
+
transition: all 0.3s;
|
|
135
|
+
padding: 4px 12px;
|
|
136
|
+
margin: 0 12px;
|
|
137
|
+
border-radius: 6px;
|
|
138
|
+
cursor: pointer;
|
|
139
|
+
|
|
140
|
+
&:hover {
|
|
141
|
+
background: rgba(0, 0, 0, 0.06);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.avatar {
|
|
145
|
+
width: 40px;
|
|
146
|
+
height: 40px;
|
|
147
|
+
border-radius: 50%;
|
|
148
|
+
margin-right: 12px;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.layout-main {
|
|
154
|
+
flex: 1;
|
|
155
|
+
height: 100%;
|
|
156
|
+
overflow: auto;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.layout-content {
|
|
160
|
+
width: 100%;
|
|
161
|
+
height: calc(100vh - #{$header-height});
|
|
162
|
+
overflow: auto;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.ant-menu-submenu-popup {
|
|
166
|
+
.ant-menu-item-selected {
|
|
167
|
+
background: rgba(255, 255, 255, 0.12) !important;
|
|
168
|
+
}
|
|
169
|
+
}
|