Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
B
basic-vue-admin
概览
概览
详情
活动
周期分析
版本库
存储库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
Basic
basic-vue-admin
Commits
4baf90a5
提交
4baf90a5
authored
11月 10, 2020
作者:
vben
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
perf: optimize tab switching speed
上级
43929174
隐藏空白字符变更
内嵌
并排
正在显示
9 个修改的文件
包含
192 行增加
和
47 行删除
+192
-47
CHANGELOG.zh_CN.md
CHANGELOG.zh_CN.md
+1
-0
index.less
src/components/Menu/src/index.less
+8
-7
color.less
src/design/color.less
+1
-6
index.less
src/layouts/default/index.less
+1
-1
index.tsx
src/layouts/default/multitabs/index.tsx
+21
-25
index.ts
src/router/guard/index.ts
+15
-0
menu.ts
src/store/modules/menu.ts
+0
-6
tab.ts
src/store/modules/tab.ts
+15
-2
color.ts
src/utils/color.ts
+130
-0
没有找到文件。
CHANGELOG.zh_CN.md
浏览文件 @
4baf90a5
...
...
@@ -7,6 +7,7 @@
### ⚡ Performance Improvements
-
优化 settingDrawer 代码
-
优化多标签页切换速度
### 🐛 Bug Fixes
...
...
src/components/Menu/src/index.less
浏览文件 @
4baf90a5
...
...
@@ -206,7 +206,7 @@
// 层级样式
&.ant-menu-dark:not(.basic-menu__sidebar-hor) {
overflow-x: hidden;
background: @
first-
menu-item-dark-bg-color;
background: @menu-item-dark-bg-color;
.active-menu-style();
.ant-menu-item.ant-menu-item-selected.basic-menu-menu-item__level1,
...
...
@@ -215,20 +215,21 @@
}
.basic-menu-item__level1 {
background-color: @
first-
menu-item-dark-bg-color;
background-color: @menu-item-dark-bg-color;
> .ant-menu-sub > li {
background-color:
@sub-menu-item-dark-bg-color
;
background-color:
lighten(@menu-item-dark-bg-color, 6%)
;
}
}
.basic-menu-item__level2:not(.ant-menu-item-selected),
.ant-menu-sub {
background-color: @sub-menu-item-dark-bg-color;
background-color: lighten(@menu-item-dark-bg-color, 6%);
// background-color: @sub-menu-item-dark-bg-color;
}
.basic-menu-item__level3:not(.ant-menu-item-selected) {
background-color:
@children-menu-item-dark-bg-color
;
background-color:
lighten(@menu-item-dark-bg-color, 10%)
;
}
.ant-menu-submenu-title {
...
...
@@ -241,7 +242,7 @@
&.ant-menu-inline-collapsed {
.ant-menu-submenu-selected,
.ant-menu-item-selected {
background: darken(@
first-
menu-item-dark-bg-color, 6%) !important;
background: darken(@menu-item-dark-bg-color, 6%) !important;
}
}
}
...
...
@@ -310,7 +311,7 @@
.ant-menu-dark {
&.ant-menu-submenu-popup {
> ul {
background: @
first-
menu-item-dark-bg-color;
background: @menu-item-dark-bg-color;
}
.active-menu-style();
...
...
src/design/color.less
浏览文件 @
4baf90a5
...
...
@@ -64,12 +64,7 @@
// =================================
// let -menu
@first-menu-item-dark-bg-color: #273352;
// Level 2 menu dark background color
@sub-menu-item-dark-bg-color: #314268;
// Level 3 menu dark background color
@children-menu-item-dark-bg-color: #4f6088;
@menu-item-dark-bg-color: #273352;
// top-menu
@top-menu-active-bg-color: #273352;
...
...
src/layouts/default/index.less
浏览文件 @
4baf90a5
...
...
@@ -41,7 +41,7 @@
background-size: 100% 100%;
&.ant-layout-sider-dark {
background: @
first-
menu-item-dark-bg-color;
background: @menu-item-dark-bg-color;
}
&:not(.ant-layout-sider-dark) {
...
...
src/layouts/default/multitabs/index.tsx
浏览文件 @
4baf90a5
...
...
@@ -2,15 +2,10 @@ import type { TabContentProps } from './tab.data';
import
type
{
TabItem
}
from
'/@/store/modules/tab'
;
import
type
{
AppRouteRecordRaw
}
from
'/@/router/types'
;
import
{
defineComponent
,
watch
,
computed
,
// ref,
unref
,
// onMounted,
toRaw
,
}
from
'vue'
;
import
{
defineComponent
,
watch
,
computed
,
unref
,
toRaw
}
from
'vue'
;
import
{
useRouter
}
from
'vue-router'
;
import
router
from
'/@/router'
;
import
{
Tabs
}
from
'ant-design-vue'
;
import
TabContent
from
'./TabContent'
;
...
...
@@ -18,16 +13,13 @@ import { useGo } from '/@/hooks/web/usePage';
import
{
TabContentEnum
}
from
'./tab.data'
;
import
{
useRouter
}
from
'vue-router'
;
import
{
tabStore
}
from
'/@/store/modules/tab'
;
import
{
userStore
}
from
'/@/store/modules/user'
;
import
{
closeTab
}
from
'./useTabDropdown'
;
import
router
from
'/@/router'
;
import
{
useTabs
}
from
'/@/hooks/web/useTabs'
;
// import { PageEnum } from '/@/enums/pageEnum';
import
'./index.less'
;
import
{
userStore
}
from
'/@/store/modules/user'
;
export
default
defineComponent
({
name
:
'MultiTabs'
,
setup
()
{
...
...
@@ -41,20 +33,24 @@ export default defineComponent({
return
tabStore
.
getTabsState
;
});
if
(
!
isAddAffix
)
{
addAffixTabs
();
isAddAffix
=
true
;
}
// If you monitor routing changes, tab switching will be stuck. So use this method
watch
(
()
=>
unref
(
currentRoute
).
path
,
()
=>
tabStore
.
getLastChangeRouteState
,
()
=>
{
if
(
!
userStore
.
getTokenState
)
return
;
const
{
path
:
rPath
,
fullPath
}
=
unref
(
currentRoute
);
if
(
activeKeyRef
.
value
!==
(
fullPath
||
rPath
))
{
activeKeyRef
.
value
=
fullPath
||
rPath
;
if
(
!
isAddAffix
)
{
addAffixTabs
();
isAddAffix
=
true
;
}
const
lastChangeRoute
=
unref
(
tabStore
.
getLastChangeRouteState
);
if
(
!
lastChangeRoute
||
!
userStore
.
getTokenState
)
return
;
const
{
path
,
fullPath
}
=
lastChangeRoute
;
if
(
activeKeyRef
.
value
!==
(
fullPath
||
path
))
{
activeKeyRef
.
value
=
fullPath
||
path
;
}
tabStore
.
commitAddTab
((
unref
(
currentRoute
)
as
unknown
)
as
AppRouteRecordRaw
);
tabStore
.
commitAddTab
((
lastChangeRoute
as
unknown
)
as
AppRouteRecordRaw
);
},
{
immediate
:
true
,
...
...
src/router/guard/index.ts
浏览文件 @
4baf90a5
...
...
@@ -12,6 +12,8 @@ import { getIsOpenTab, setCurrentTo } from '/@/utils/helper/routeHelper';
import
{
setTitle
}
from
'/@/utils/browser'
;
import
{
AxiosCanceler
}
from
'/@/utils/http/axios/axiosCancel'
;
import
{
tabStore
}
from
'/@/store/modules/tab'
;
const
{
projectSetting
,
globSetting
}
=
useSetting
();
export
function
createGuard
(
router
:
Router
)
{
const
{
openNProgress
,
closeMessageOnSwitch
,
removeAllHttpPending
}
=
projectSetting
;
...
...
@@ -20,8 +22,21 @@ export function createGuard(router: Router) {
axiosCanceler
=
new
AxiosCanceler
();
}
router
.
beforeEach
(
async
(
to
)
=>
{
// Determine whether the tab has been opened
const
isOpen
=
getIsOpenTab
(
to
.
fullPath
);
to
.
meta
.
inTab
=
isOpen
;
// Notify routing changes
const
{
fullPath
,
path
,
query
,
params
,
name
,
meta
}
=
to
;
tabStore
.
commitLastChangeRouteState
({
fullPath
,
path
,
query
,
params
,
name
,
meta
,
}
as
any
);
try
{
if
(
closeMessageOnSwitch
)
{
Modal
.
destroyAll
();
...
...
src/store/modules/menu.ts
浏览文件 @
4baf90a5
...
...
@@ -8,12 +8,6 @@ const NAME = 'menu';
hotModuleUnregisterModule
(
NAME
);
@
Module
({
namespaced
:
true
,
name
:
NAME
,
dynamic
:
true
,
store
})
class
Menu
extends
VuexModule
{
// // 默认展开
// private collapsedState: boolean = appStore.getProjectConfig.menuSetting.collapsed;
// // 菜单宽度
// private menuWidthState: number = appStore.getProjectConfig.menuSetting.menuWidth;
// 是否开始拖拽
private
dragStartState
=
false
;
...
...
src/store/modules/tab.ts
浏览文件 @
4baf90a5
...
...
@@ -7,6 +7,7 @@ import { hotModuleUnregisterModule } from '/@/utils/helper/vuexHelper';
import
{
PageEnum
}
from
'/@/enums/pageEnum'
;
import
{
appStore
}
from
'/@/store/modules/app'
;
import
{
userStore
}
from
'./user'
;
import
store
from
'/@/store'
;
import
router
from
'/@/router'
;
...
...
@@ -43,10 +44,17 @@ class Tab extends VuexModule {
currentContextMenuState
:
TabItem
|
null
=
null
;
// Last route change
lastChangeRouteState
:
AppRouteRecordRaw
|
null
=
null
;
get
getTabsState
()
{
return
this
.
tabsState
;
}
get
getLastChangeRouteState
()
{
return
this
.
lastChangeRouteState
;
}
get
getCurrentContextMenuIndexState
()
{
return
this
.
currentContextMenuIndexState
;
}
...
...
@@ -65,6 +73,12 @@ class Tab extends VuexModule {
}
@
Mutation
commitLastChangeRouteState
(
route
:
AppRouteRecordRaw
):
void
{
if
(
!
userStore
.
getTokenState
)
return
;
this
.
lastChangeRouteState
=
route
;
}
@
Mutation
commitClearCache
():
void
{
this
.
keepAliveTabsState
=
[];
}
...
...
@@ -86,7 +100,7 @@ class Tab extends VuexModule {
commitAddTab
(
route
:
AppRouteRecordRaw
|
TabItem
):
void
{
const
{
path
,
name
,
meta
,
fullPath
,
params
,
query
}
=
route
as
TabItem
;
// 404 页面不需要添加tab
if
(
path
===
PageEnum
.
ERROR_PAGE
)
{
if
(
path
===
PageEnum
.
ERROR_PAGE
||
!
name
)
{
return
;
}
else
if
([
REDIRECT_ROUTE
.
name
,
PAGE_NOT_FOUND_ROUTE
.
name
].
includes
(
name
as
string
))
{
return
;
...
...
@@ -107,7 +121,6 @@ class Tab extends VuexModule {
this
.
tabsState
.
splice
(
updateIndex
,
1
,
curTab
);
return
;
}
this
.
tabsState
.
push
({
path
,
fullPath
,
name
,
meta
,
params
,
query
});
if
(
unref
(
getOpenKeepAliveRef
)
&&
name
)
{
const
noKeepAlive
=
meta
&&
meta
.
ignoreKeepAlive
;
...
...
src/utils/color.ts
0 → 100644
浏览文件 @
4baf90a5
/**
* 判断是否 十六进制颜色值.
* 输入形式可为 #fff000 #f00
*
* @param String color 十六进制颜色值
* @return Boolean
*/
export
const
isHexColor
=
function
(
color
:
string
)
{
const
reg
=
/^#
([
0-9a-fA-f
]{3}
|
[
0-9a-fA-f
]{6})
$/
;
return
reg
.
test
(
color
);
};
/**
* RGB 颜色值转换为 十六进制颜色值.
* r, g, 和 b 需要在 [0, 255] 范围内
*
* @param Number r 红色色值
* @param Number g 绿色色值
* @param Number b 蓝色色值
* @return String 类似#ff00ff
*/
export
const
rgbToHex
=
function
(
r
:
number
,
g
:
number
,
b
:
number
)
{
// tslint:disable-next-line:no-bitwise
const
hex
=
((
r
<<
16
)
|
(
g
<<
8
)
|
b
).
toString
(
16
);
return
'#'
+
new
Array
(
Math
.
abs
(
hex
.
length
-
7
)).
join
(
'0'
)
+
hex
;
};
/**
* Transform a HEX color to its RGB representation
* @param {string} hex The color to transform
* @returns The RGB representation of the passed color
*/
export
const
hexToRGB
=
function
(
hex
:
string
)
{
return
(
parseInt
(
hex
.
substring
(
0
,
2
),
16
)
+
','
+
parseInt
(
hex
.
substring
(
2
,
4
),
16
)
+
','
+
parseInt
(
hex
.
substring
(
4
,
6
),
16
)
);
};
/**
* Darkens a HEX color given the passed percentage
* @param {string} color The color to process
* @param {number} amount The amount to change the color by
* @returns {string} The HEX representation of the processed color
*/
export
const
darken
=
(
color
:
string
,
amount
:
number
)
=>
{
color
=
color
.
indexOf
(
'#'
)
>=
0
?
color
.
substring
(
1
,
color
.
length
)
:
color
;
amount
=
Math
.
trunc
((
255
*
amount
)
/
100
);
return
`#
${
subtractLight
(
color
.
substring
(
0
,
2
),
amount
)}${
subtractLight
(
color
.
substring
(
2
,
4
),
amount
)}${
subtractLight
(
color
.
substring
(
4
,
6
),
amount
)}
`
;
};
/**
* Lightens a 6 char HEX color according to the passed percentage
* @param {string} color The color to change
* @param {number} amount The amount to change the color by
* @returns {string} The processed color represented as HEX
*/
export
const
lighten
=
(
color
:
string
,
amount
:
number
)
=>
{
color
=
color
.
indexOf
(
'#'
)
>=
0
?
color
.
substring
(
1
,
color
.
length
)
:
color
;
amount
=
Math
.
trunc
((
255
*
amount
)
/
100
);
return
`#
${
addLight
(
color
.
substring
(
0
,
2
),
amount
)}${
addLight
(
color
.
substring
(
2
,
4
),
amount
)}${
addLight
(
color
.
substring
(
4
,
6
),
amount
)}
`
;
};
/* Suma el porcentaje indicado a un color (RR, GG o BB) hexadecimal para aclararlo */
/**
* Sums the passed percentage to the R, G or B of a HEX color
* @param {string} color The color to change
* @param {number} amount The amount to change the color by
* @returns {string} The processed part of the color
*/
const
addLight
=
(
color
:
string
,
amount
:
number
)
=>
{
const
cc
=
parseInt
(
color
,
16
)
+
amount
;
const
c
=
cc
>
255
?
255
:
cc
;
return
c
.
toString
(
16
).
length
>
1
?
c
.
toString
(
16
)
:
`0
${
c
.
toString
(
16
)}
`
;
};
/**
* Calculates luminance of an rgb color
* @param {number} r red
* @param {number} g green
* @param {number} b blue
*/
const
luminanace
=
(
r
:
stri
,
g
:
number
,
b
:
number
)
=>
{
const
a
=
[
r
,
g
,
b
].
map
((
v
)
=>
{
v
/=
255
;
return
v
<=
0.03928
?
v
/
12.92
:
Math
.
pow
((
v
+
0.055
)
/
1.055
,
2.4
);
});
return
a
[
0
]
*
0.2126
+
a
[
1
]
*
0.7152
+
a
[
2
]
*
0.0722
;
};
/**
* Calculates contrast between two rgb colors
* @param {string} rgb1 rgb color 1
* @param {string} rgb2 rgb color 2
*/
const
contrast
=
(
rgb1
:
string
[],
rgb2
:
number
[])
=>
(
luminanace
(
rgb1
[
0
],
~~
rgb1
[
1
],
~~
rgb1
[
2
])
+
0.05
)
/
(
luminanace
(
rgb2
[
0
],
rgb2
[
1
],
rgb2
[
2
])
+
0.05
);
/**
* Determines what the best text color is (black or white) based con the contrast with the background
* @param hexColor - Last selected color by the user
*/
export
const
calculateBestTextColor
=
(
hexColor
:
string
)
=>
{
const
rgbColor
=
hexToRGB
(
hexColor
.
substring
(
1
));
const
contrastWithBlack
=
contrast
(
rgbColor
.
split
(
','
),
[
0
,
0
,
0
]);
return
contrastWithBlack
>=
12
?
'#000000'
:
'#FFFFFF'
;
};
/**
* Subtracts the indicated percentage to the R, G or B of a HEX color
* @param {string} color The color to change
* @param {number} amount The amount to change the color by
* @returns {string} The processed part of the color
*/
const
subtractLight
=
(
color
:
string
,
amount
:
number
)
=>
{
const
cc
=
parseInt
(
color
,
16
)
-
amount
;
const
c
=
cc
<
0
?
0
:
cc
;
return
c
.
toString
(
16
).
length
>
1
?
c
.
toString
(
16
)
:
`0
${
c
.
toString
(
16
)}
`
;
};
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论