Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
B
basic-vue-admin
概览
概览
详情
活动
周期分析
版本库
存储库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
Basic
basic-vue-admin
Commits
a65ad9ed
提交
a65ad9ed
authored
12月 15, 2020
作者:
vben
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
wip(menu): perf menu
上级
ec7efcf0
隐藏空白字符变更
内嵌
并排
正在显示
80 个修改的文件
包含
1335 行增加
和
969 行删除
+1335
-969
CHANGELOG.zh_CN.md
CHANGELOG.zh_CN.md
+5
-1
index.ts
src/components/Application/index.ts
+1
-3
AppLocalePicker.vue
src/components/Application/src/AppLocalePicker.vue
+6
-5
AppLogo.vue
src/components/Application/src/AppLogo.vue
+1
-1
AppProvider.vue
src/components/Application/src/AppProvider.vue
+13
-2
AppSearch.vue
src/components/Application/src/search/AppSearch.vue
+1
-1
useAppContext.ts
src/components/Application/src/useAppContext.ts
+2
-0
index.tsx
src/components/Icon/index.tsx
+1
-1
BasicMenu.vue
src/components/Menu/src/BasicMenu.vue
+52
-83
MenuContent.tsx
src/components/Menu/src/MenuContent.tsx
+0
-96
BasicMenuItem.vue
src/components/Menu/src/components/BasicMenuItem.vue
+5
-12
BasicSubMenuItem.vue
src/components/Menu/src/components/BasicSubMenuItem.vue
+5
-5
MenuItemContent.vue
src/components/Menu/src/components/MenuItemContent.vue
+41
-0
MenuItemTag.vue
src/components/Menu/src/components/MenuItemTag.vue
+56
-0
index.less
src/components/Menu/src/index.less
+35
-107
props.ts
src/components/Menu/src/props.ts
+10
-3
useOpenKeys.ts
src/components/Menu/src/useOpenKeys.ts
+2
-0
PageFooter.vue
src/components/Page/src/PageFooter.vue
+3
-1
index.less
src/components/Preview/src/index.less
+1
-1
UploadModal.vue
src/components/Upload/src/UploadModal.vue
+1
-2
color.less
src/design/color.less
+1
-1
index.less
src/design/index.less
+4
-0
index.less
src/design/var/index.less
+13
-1
useBreakpoint.ts
src/hooks/event/useBreakpoint.ts
+12
-7
useHeaderSetting.ts
src/hooks/setting/useHeaderSetting.ts
+0
-5
useMenuSetting.ts
src/hooks/setting/useMenuSetting.ts
+5
-0
useMultipleTabSetting.ts
src/hooks/setting/useMultipleTabSetting.ts
+3
-0
useAppInject.ts
src/hooks/web/useAppInject.ts
+10
-0
useI18n.ts
src/hooks/web/useI18n.ts
+1
-1
usePage.ts
src/hooks/web/usePage.ts
+7
-5
useTabs.ts
src/hooks/web/useTabs.ts
+5
-1
index.vue
src/layouts/default/content/index.vue
+1
-2
LayoutHeader.tsx
src/layouts/default/header/LayoutHeader.tsx
+39
-115
LayoutMultipleHeader.less
src/layouts/default/header/LayoutMultipleHeader.less
+3
-1
LayoutMultipleHeader.tsx
src/layouts/default/header/LayoutMultipleHeader.tsx
+9
-7
UserDropdown.tsx
src/layouts/default/header/UserDropdown.tsx
+0
-125
Breadcrumb.vue
src/layouts/default/header/components/Breadcrumb.vue
+69
-11
ErrorAction.vue
src/layouts/default/header/components/ErrorAction.vue
+47
-0
FullScreen.vue
src/layouts/default/header/components/FullScreen.vue
+36
-0
index.ts
src/layouts/default/header/components/index.ts
+15
-0
LockAction.less
src/layouts/default/header/components/lock/LockAction.less
+0
-0
LockAction.tsx
src/layouts/default/header/components/lock/LockAction.tsx
+0
-0
LockModal.vue
src/layouts/default/header/components/lock/LockModal.vue
+116
-0
index.vue
src/layouts/default/header/components/lock/index.vue
+38
-0
NoticeList.vue
src/layouts/default/header/components/notify/NoticeList.vue
+10
-2
data.ts
src/layouts/default/header/components/notify/data.ts
+0
-0
index.vue
src/layouts/default/header/components/notify/index.vue
+14
-7
DropMenuItem.vue
.../default/header/components/user-dropdown/DropMenuItem.vue
+27
-0
index.vue
...layouts/default/header/components/user-dropdown/index.vue
+156
-0
index.less
src/layouts/default/header/index.less
+59
-172
index.vue
src/layouts/default/header/index.vue
+161
-0
index.vue
src/layouts/default/index.vue
+7
-14
index.tsx
src/layouts/default/menu/index.tsx
+35
-11
useLayoutMenu.ts
src/layouts/default/menu/useLayoutMenu.ts
+6
-6
SettingDrawer.tsx
src/layouts/default/setting/SettingDrawer.tsx
+8
-1
enum.ts
src/layouts/default/setting/enum.ts
+1
-0
handler.ts
src/layouts/default/setting/handler.ts
+2
-0
index.less
src/layouts/default/sider/index.less
+9
-3
index.tsx
src/layouts/default/sider/index.tsx
+17
-48
useLayoutSider.tsx
src/layouts/default/sider/useLayoutSider.tsx
+2
-7
TabContent.vue
src/layouts/default/tabs/components/TabContent.vue
+1
-1
TabRedo.vue
src/layouts/default/tabs/components/TabRedo.vue
+37
-0
index.less
src/layouts/default/tabs/index.less
+28
-21
index.vue
src/layouts/default/tabs/index.vue
+24
-29
useTabDropdown.ts
src/layouts/default/tabs/useTabDropdown.ts
+1
-5
useLayoutContext.ts
src/layouts/default/useLayoutContext.ts
+0
-1
header.ts
src/locales/lang/en/layout/header.ts
+1
-1
multipleTab.ts
src/locales/lang/en/layout/multipleTab.ts
+1
-0
setting.ts
src/locales/lang/en/layout/setting.ts
+1
-0
header.ts
src/locales/lang/zh_CN/layout/header.ts
+1
-1
multipleTab.ts
src/locales/lang/zh_CN/layout/multipleTab.ts
+1
-0
setting.ts
src/locales/lang/zh_CN/layout/setting.ts
+1
-0
tabChange.ts
src/logics/mitt/tabChange.ts
+28
-0
index.ts
src/router/guard/index.ts
+2
-4
index.ts
src/router/menus/index.ts
+1
-0
projectSetting.ts
src/settings/projectSetting.ts
+4
-2
tab.ts
src/store/modules/tab.ts
+4
-19
config.d.ts
src/types/config.d.ts
+4
-2
mitt.ts
src/utils/mitt.ts
+5
-5
LockPage.vue
src/views/sys/lock/LockPage.vue
+1
-1
没有找到文件。
CHANGELOG.zh_CN.md
浏览文件 @
a65ad9ed
...
@@ -7,11 +7,13 @@
...
@@ -7,11 +7,13 @@
### ⚡ Performance Improvements
### ⚡ Performance Improvements
-
异步引入组件
-
异步引入组件
-
优化整体结构
### 🎫 Chores
### 🎫 Chores
-
返回顶部样式调整,避免遮住其他元素
-
返回顶部样式调整,避免遮住其他元素
-
升级
`ant-design-vue`
到
`2.0.0-rc.4`
-
升级
`ant-design-vue`
到
`2.0.0-rc.5`
-
刷新按钮布局调整
### 🐛 Bug Fixes
### 🐛 Bug Fixes
...
@@ -23,6 +25,8 @@
...
@@ -23,6 +25,8 @@
-
修复按钮样式问题
-
修复按钮样式问题
-
修复菜单分割模式问题
-
修复菜单分割模式问题
-
修复
`Modal`
与
`Drawer`
组件在使用 emits 数据传递失效问题
-
修复
`Modal`
与
`Drawer`
组件在使用 emits 数据传递失效问题
-
修复菜单已知问题
-
修复上传组件 api 失效问题
## 2.0.0-rc.13 (2020-12-10)
## 2.0.0-rc.13 (2020-12-10)
...
...
src/components/Application/index.ts
浏览文件 @
a65ad9ed
...
@@ -2,9 +2,7 @@ import { withInstall } from '../util';
...
@@ -2,9 +2,7 @@ import { withInstall } from '../util';
import
{
createAsyncComponent
}
from
'/@/utils/factory/createAsyncComponent'
;
import
{
createAsyncComponent
}
from
'/@/utils/factory/createAsyncComponent'
;
import
AppLogo
from
'./src/AppLogo.vue'
;
import
AppLogo
from
'./src/AppLogo.vue'
;
export
const
AppLocalePicker
=
createAsyncComponent
(()
=>
import
(
'./src/AppLocalePicker.vue'
),
{
export
const
AppLocalePicker
=
createAsyncComponent
(()
=>
import
(
'./src/AppLocalePicker.vue'
));
loading
:
true
,
});
export
const
AppProvider
=
createAsyncComponent
(()
=>
import
(
'./src/AppProvider.vue'
));
export
const
AppProvider
=
createAsyncComponent
(()
=>
import
(
'./src/AppProvider.vue'
));
export
const
AppSearch
=
createAsyncComponent
(()
=>
import
(
'./src/search/AppSearch.vue'
),
{
export
const
AppSearch
=
createAsyncComponent
(()
=>
import
(
'./src/search/AppSearch.vue'
),
{
loading
:
true
,
loading
:
true
,
...
...
src/components/Application/src/AppLocalePicker.vue
浏览文件 @
a65ad9ed
...
@@ -11,8 +11,8 @@
...
@@ -11,8 +11,8 @@
:overlayClassName=
"`$
{prefixCls}-overlay`"
:overlayClassName=
"`$
{prefixCls}-overlay`"
>
>
<span
:class=
"prefixCls"
>
<span
:class=
"prefixCls"
>
<
GlobalOutlined
:class=
"`$
{prefixCls}__icon`
" />
<
Icon
icon=
"cil:language
"
/>
<span
v-if=
"showText"
>
{{
getLangText
}}
</span>
<span
v-if=
"showText"
:class=
"`$
{prefixCls}__text`"
>
{{
getLangText
}}
</span>
</span>
</span>
</Dropdown>
</Dropdown>
</
template
>
</
template
>
...
@@ -30,9 +30,10 @@
...
@@ -30,9 +30,10 @@
import
{
propTypes
}
from
'/@/utils/propTypes'
;
import
{
propTypes
}
from
'/@/utils/propTypes'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
import
Icon
from
'/@/components/Icon'
;
export
default
defineComponent
({
export
default
defineComponent
({
name
:
'AppLocalPicker'
,
name
:
'AppLocalPicker'
,
components
:
{
GlobalOutlined
,
Dropdown
},
components
:
{
GlobalOutlined
,
Dropdown
,
Icon
},
props
:
{
props
:
{
// Whether to display text
// Whether to display text
showText
:
propTypes
.
bool
.
def
(
true
),
showText
:
propTypes
.
bool
.
def
(
true
),
...
@@ -88,8 +89,8 @@
...
@@ -88,8 +89,8 @@
align-items
:
center
;
align-items
:
center
;
cursor
:
pointer
;
cursor
:
pointer
;
&__
icon
{
&__
text
{
margin-
right
:
4
px
;
margin-
left
:
6
px
;
}
}
}
}
</
style
>
</
style
>
src/components/Application/src/AppLogo.vue
浏览文件 @
a65ad9ed
...
@@ -87,7 +87,7 @@
...
@@ -87,7 +87,7 @@
}
}
&
__title
{
&
__title
{
font-size
:
1
8
px
;
font-size
:
1
6
px
;
font-weight
:
700
;
font-weight
:
700
;
opacity
:
0
;
opacity
:
0
;
transition
:
all
0.5s
;
transition
:
all
0.5s
;
...
...
src/components/Application/src/AppProvider.vue
浏览文件 @
a65ad9ed
...
@@ -3,11 +3,13 @@
...
@@ -3,11 +3,13 @@
</
template
>
</
template
>
<
script
lang=
"ts"
>
<
script
lang=
"ts"
>
import
type
{
PropType
}
from
'vue'
;
import
type
{
PropType
}
from
'vue'
;
import
{
defineComponent
,
toRefs
}
from
'vue'
;
import
{
defineComponent
,
toRefs
,
ref
}
from
'vue'
;
import
{
createAppProviderContext
}
from
'./useAppContext'
;
import
{
createAppProviderContext
}
from
'./useAppContext'
;
import
designSetting
from
'/@/settings/designSetting'
;
import
designSetting
from
'/@/settings/designSetting'
;
import
{
createBreakpointListen
}
from
'/@/hooks/event/useBreakpoint'
;
export
default
defineComponent
({
export
default
defineComponent
({
name
:
'AppProvider'
,
name
:
'AppProvider'
,
inheritAttrs
:
false
,
inheritAttrs
:
false
,
...
@@ -18,8 +20,17 @@
...
@@ -18,8 +20,17 @@
},
},
},
},
setup
(
props
)
{
setup
(
props
)
{
const
isMobileRef
=
ref
(
false
);
createBreakpointListen
(({
screenMap
,
sizeEnum
,
width
})
=>
{
const
lgWidth
=
screenMap
.
get
(
sizeEnum
.
LG
);
if
(
lgWidth
)
{
isMobileRef
.
value
=
width
.
value
-
1
<
lgWidth
;
}
});
const
{
prefixCls
}
=
toRefs
(
props
);
const
{
prefixCls
}
=
toRefs
(
props
);
createAppProviderContext
({
prefixCls
});
createAppProviderContext
({
prefixCls
,
isMobile
:
isMobileRef
});
return
{};
return
{};
},
},
});
});
...
...
src/components/Application/src/search/AppSearch.vue
浏览文件 @
a65ad9ed
...
@@ -50,6 +50,6 @@
...
@@ -50,6 +50,6 @@
@prefix-cls
:
~
'@{namespace}-app-search'
;
@prefix-cls
:
~
'@{namespace}-app-search'
;
.@
{
prefix-cls
}
{
.@
{
prefix-cls
}
{
padding
:
0
10
px
;
padding
:
2
px
;
}
}
</
style
>
</
style
>
src/components/Application/src/useAppContext.ts
浏览文件 @
a65ad9ed
...
@@ -3,6 +3,8 @@ import { createContext, useContext } from '/@/hooks/core/useContext';
...
@@ -3,6 +3,8 @@ import { createContext, useContext } from '/@/hooks/core/useContext';
export
interface
AppProviderContextProps
{
export
interface
AppProviderContextProps
{
prefixCls
:
Ref
<
string
>
;
prefixCls
:
Ref
<
string
>
;
isMobile
:
Ref
<
boolean
>
;
}
}
const
key
:
InjectionKey
<
AppProviderContextProps
>
=
Symbol
();
const
key
:
InjectionKey
<
AppProviderContextProps
>
=
Symbol
();
...
...
src/components/Icon/index.tsx
浏览文件 @
a65ad9ed
...
@@ -77,7 +77,7 @@ export default defineComponent({
...
@@ -77,7 +77,7 @@ export default defineComponent({
onMounted
(
update
);
onMounted
(
update
);
return
()
=>
(
return
()
=>
(
<
div
ref=
{
elRef
}
class=
{
[
attrs
.
class
,
'app-iconify anticon'
]
}
style=
{
unref
(
wrapStyleRef
)
}
/>
<
span
ref=
{
elRef
}
class=
{
[
attrs
.
class
,
'app-iconify anticon'
]
}
style=
{
unref
(
wrapStyleRef
)
}
/>
);
);
},
},
});
});
src/components/Menu/src/BasicMenu.vue
浏览文件 @
a65ad9ed
<
template
>
<
template
>
<slot
name=
"header"
v-if=
"!getIsHorizontal"
/>
<Menu
<ScrollContainer
:class=
"`$
{prefixCls}-wrapper`" :style="getWrapperStyle">
:selectedKeys=
"selectedKeys"
<Menu
:defaultSelectedKeys=
"defaultSelectedKeys"
:selectedKeys=
"selectedKeys"
:mode=
"mode"
:defaultSelectedKeys=
"defaultSelectedKeys"
:openKeys=
"getOpenKeys"
:mode=
"mode"
:inlineIndent=
"inlineIndent"
:openKeys=
"getOpenKeys"
:theme=
"theme"
:inlineIndent=
"inlineIndent"
@
openChange=
"handleOpenChange"
:theme=
"theme"
:class=
"getMenuClass"
@
openChange=
"handleOpenChange"
@
click=
"handleMenuClick"
:class=
"getMenuClass"
:subMenuOpenDelay=
"0.2"
@
click=
"handleMenuClick"
v-bind=
"getInlineCollapseOptions"
:subMenuOpenDelay=
"0.2"
>
v-bind=
"getInlineCollapseOptions"
<template
v-for=
"item in items"
:key=
"item.path"
>
>
<BasicSubMenuItem
<template
v-for=
"item in items"
:key=
"item.path"
>
:item=
"item"
<BasicSubMenuItem
:theme=
"theme"
:item=
"item"
:level=
"1"
:theme=
"theme"
:showTitle=
"showTitle"
:level=
"1"
:isHorizontal=
"isHorizontal"
:appendClass=
"appendClass"
/>
:parentPath=
"currentParentPath"
</
template
>
:showTitle=
"showTitle"
</Menu>
:isHorizontal=
"isHorizontal"
/>
</
template
>
</Menu>
</ScrollContainer>
</template>
</template>
<
script
lang=
"ts"
>
<
script
lang=
"ts"
>
import
type
{
MenuState
}
from
'./types'
;
import
type
{
MenuState
}
from
'./types'
;
import
{
import
{
computed
,
defineComponent
,
unref
,
reactive
,
watch
,
toRefs
,
ref
}
from
'vue'
;
computed
,
defineComponent
,
unref
,
reactive
,
watch
,
toRefs
,
ref
,
CSSProperties
,
}
from
'vue'
;
import
{
Menu
}
from
'ant-design-vue'
;
import
{
Menu
}
from
'ant-design-vue'
;
import
BasicSubMenuItem
from
'./components/BasicSubMenuItem.vue'
;
import
BasicSubMenuItem
from
'./components/BasicSubMenuItem.vue'
;
import
{
ScrollContainer
}
from
'/@/components/Container'
;
import
{
MenuModeEnum
,
MenuTypeEnum
}
from
'/@/enums/menuEnum'
;
import
{
MenuModeEnum
,
MenuTypeEnum
}
from
'/@/enums/menuEnum'
;
import
{
appStore
}
from
'/@/store/modules/app'
;
import
{
useOpenKeys
}
from
'./useOpenKeys'
;
import
{
useOpenKeys
}
from
'./useOpenKeys'
;
import
{
useRouter
}
from
'vue-router'
;
import
{
RouteLocationNormalizedLoaded
,
useRouter
}
from
'vue-router'
;
import
{
isFunction
}
from
'/@/utils/is'
;
import
{
isFunction
}
from
'/@/utils/is'
;
import
{
getCurrentParentPath
}
from
'/@/router/menus'
;
import
{
basicProps
}
from
'./props'
;
import
{
basicProps
}
from
'./props'
;
import
{
useMenuSetting
}
from
'/@/hooks/setting/useMenuSetting'
;
import
{
useMenuSetting
}
from
'/@/hooks/setting/useMenuSetting'
;
import
{
REDIRECT_NAME
}
from
'/@/router/constant'
;
import
{
REDIRECT_NAME
}
from
'/@/router/constant'
;
import
{
tabStore
}
from
'/@/store/modules/tab'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
import
{
getCurrentParentPath
}
from
'/@/router/menus'
;
// import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
// import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
import
{
listenerLastChangeTab
}
from
'/@/logics/mitt/tabChange'
;
export
default
defineComponent
({
export
default
defineComponent
({
name
:
'BasicMenu'
,
name
:
'BasicMenu'
,
components
:
{
components
:
{
Menu
,
Menu
,
ScrollContainer
,
BasicSubMenuItem
,
BasicSubMenuItem
,
// BasicSubMenuItem: createAsyncComponent(() => import('./components/BasicSubMenuItem.vue')),
// BasicSubMenuItem: createAsyncComponent(() => import('./components/BasicSubMenuItem.vue')),
},
},
props
:
basicProps
,
props
:
basicProps
,
emits
:
[
'menuClick'
],
emits
:
[
'menuClick'
],
setup
(
props
,
{
emit
})
{
setup
(
props
,
{
emit
})
{
const
currentParentPath
=
ref
(
''
);
const
isClickGo
=
ref
(
false
);
const
isClickGo
=
ref
(
false
);
const
menuState
=
reactive
<
MenuState
>
({
const
menuState
=
reactive
<
MenuState
>
({
...
@@ -97,18 +80,24 @@
...
@@ -97,18 +80,24 @@
accordion
accordion
);
);
const
get
MenuClass
=
computed
(()
=>
{
const
get
IsTopMenu
=
computed
(()
=>
{
const
{
type
,
mode
}
=
props
;
const
{
type
,
mode
}
=
props
;
return
(
(
type
===
MenuTypeEnum
.
TOP_MENU
&&
mode
===
MenuModeEnum
.
HORIZONTAL
)
||
(
props
.
isHorizontal
&&
unref
(
getSplit
))
);
});
const
getMenuClass
=
computed
(()
=>
{
return
[
return
[
prefixCls
,
prefixCls
,
`justify-
${
unref
(
getTopMenuAlign
)}
`
,
`justify-
${
unref
(
getTopMenuAlign
)}
`
,
{
{
[
`
${
prefixCls
}
--hide-title`
]:
!
unref
(
showTitle
),
[
`
${
prefixCls
}
--hide-title`
]:
!
unref
(
showTitle
),
[
`
${
prefixCls
}
--collapsed-show-title`
]:
props
.
collapsedShowTitle
,
[
`
${
prefixCls
}
--collapsed-show-title`
]:
props
.
collapsedShowTitle
,
[
`
${
prefixCls
}
__second`
]:
[
`
${
prefixCls
}
__second`
]:
!
props
.
isHorizontal
&&
unref
(
getSplit
),
!
props
.
isHorizontal
&&
appStore
.
getProjectConfig
.
menuSetting
.
split
,
[
`
${
prefixCls
}
__sidebar-hor`
]:
unref
(
getIsTopMenu
),
[
`
${
prefixCls
}
__sidebar-hor`
]:
type
===
MenuTypeEnum
.
TOP_MENU
&&
mode
===
MenuModeEnum
.
HORIZONTAL
,
},
},
];
];
});
});
...
@@ -125,23 +114,10 @@
...
@@ -125,23 +114,10 @@
return
inlineCollapseOptions
;
return
inlineCollapseOptions
;
});
});
const
getWrapperStyle
=
computed
(
listenerLastChangeTab
((
route
)
=>
{
():
CSSProperties
=>
{
if
(
route
.
name
===
REDIRECT_NAME
)
return
;
return
{
handleMenuChange
(
route
);
height
:
`calc(100% -
${
props
.
showLogo
?
'48px'
:
'0px'
}
)`
,
},
false
);
overflowY
:
'hidden'
,
};
}
);
watch
(
()
=>
tabStore
.
getCurrentTab
,
()
=>
{
if
(
unref
(
currentRoute
).
name
===
REDIRECT_NAME
)
return
;
handleMenuChange
();
unref
(
getSplit
)
&&
getParentPath
();
}
);
watch
(
watch
(
()
=>
props
.
items
,
()
=>
props
.
items
,
...
@@ -153,16 +129,6 @@
...
@@ -153,16 +129,6 @@
}
}
);
);
getParentPath
();
async
function
getParentPath
()
{
const
{
appendClass
}
=
props
;
if
(
!
appendClass
)
return
''
;
const
parentPath
=
await
getCurrentParentPath
(
unref
(
currentRoute
).
path
);
currentParentPath
.
value
=
parentPath
;
}
async
function
handleMenuClick
({
key
,
keyPath
}:
{
key
:
string
;
keyPath
:
string
[]
})
{
async
function
handleMenuClick
({
key
,
keyPath
}:
{
key
:
string
;
keyPath
:
string
[]
})
{
const
{
beforeClickFn
}
=
props
;
const
{
beforeClickFn
}
=
props
;
if
(
beforeClickFn
&&
isFunction
(
beforeClickFn
))
{
if
(
beforeClickFn
&&
isFunction
(
beforeClickFn
))
{
...
@@ -176,28 +142,31 @@
...
@@ -176,28 +142,31 @@
menuState
.
selectedKeys
=
[
key
];
menuState
.
selectedKeys
=
[
key
];
}
}
function
handleMenuChange
(
)
{
async
function
handleMenuChange
(
route
?:
RouteLocationNormalizedLoaded
)
{
if
(
unref
(
isClickGo
))
{
if
(
unref
(
isClickGo
))
{
isClickGo
.
value
=
false
;
isClickGo
.
value
=
false
;
return
;
return
;
}
}
const
path
=
unref
(
currentRoute
).
path
;
const
path
=
(
route
||
unref
(
currentRoute
)
).
path
;
if
(
props
.
mode
!==
MenuModeEnum
.
HORIZONTAL
)
{
if
(
props
.
mode
!==
MenuModeEnum
.
HORIZONTAL
)
{
setOpenKeys
(
path
);
setOpenKeys
(
path
);
}
}
menuState
.
selectedKeys
=
[
path
];
if
(
unref
(
getIsTopMenu
))
{
const
parentPath
=
await
getCurrentParentPath
(
path
);
menuState
.
selectedKeys
=
[
parentPath
];
}
else
{
menuState
.
selectedKeys
=
[
path
];
}
}
}
return
{
return
{
prefixCls
,
prefixCls
,
getIsHorizontal
,
getIsHorizontal
,
getWrapperStyle
,
handleMenuClick
,
handleMenuClick
,
getInlineCollapseOptions
,
getInlineCollapseOptions
,
getMenuClass
,
getMenuClass
,
handleOpenChange
,
handleOpenChange
,
getOpenKeys
,
getOpenKeys
,
currentParentPath
,
showTitle
,
showTitle
,
...
toRefs
(
menuState
),
...
toRefs
(
menuState
),
};
};
...
...
src/components/Menu/src/MenuContent.tsx
deleted
100644 → 0
浏览文件 @
ec7efcf0
import
type
{
Menu
as
MenuType
}
from
'/@/router/types'
;
import
type
{
PropType
}
from
'vue'
;
import
{
computed
,
unref
}
from
'vue'
;
import
{
defineComponent
}
from
'vue'
;
import
Icon
from
'/@/components/Icon/index'
;
import
{
useI18n
}
from
'/@/hooks/web/useI18n'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
const
{
t
}
=
useI18n
();
export
default
defineComponent
({
name
:
'MenuContent'
,
props
:
{
item
:
{
type
:
Object
as
PropType
<
MenuType
>
,
default
:
null
,
},
showTitle
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
true
,
},
level
:
{
type
:
Number
as
PropType
<
number
>
,
default
:
0
,
},
isHorizontal
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
true
,
},
},
setup
(
props
)
{
const
{
prefixCls
}
=
useDesign
(
'basic-menu'
);
const
getI18nName
=
computed
(()
=>
t
(
props
.
item
?.
name
));
const
getTagClass
=
computed
(()
=>
{
const
{
item
}
=
props
;
const
{
tag
=
{}
}
=
item
||
{};
const
{
dot
,
type
=
'error'
}
=
tag
;
return
[
`
${
prefixCls
}
__tag`
,
type
,
{
dot
,
},
];
});
const
getNameClass
=
computed
(()
=>
{
const
{
showTitle
}
=
props
;
return
{
[
`
${
prefixCls
}
--show-title`
]:
showTitle
,
[
`
${
prefixCls
}
__name`
]:
!
showTitle
};
});
/**
* @description: 渲染图标
*/
function
renderIcon
(
icon
?:
string
)
{
return
icon
?
<
Icon
icon=
{
icon
}
size=
{
18
}
class=
"menu-item-icon"
/>
:
null
;
}
function
renderTag
()
{
const
{
item
,
showTitle
,
isHorizontal
}
=
props
;
if
(
!
item
||
showTitle
||
isHorizontal
)
return
null
;
const
{
tag
}
=
item
;
if
(
!
tag
)
return
null
;
const
{
dot
,
content
}
=
tag
;
if
(
!
dot
&&
!
content
)
return
null
;
return
<
span
class=
{
unref
(
getTagClass
)
}
>
{
dot
?
''
:
content
}
</
span
>;
}
return
()
=>
{
const
{
item
}
=
props
;
if
(
!
item
)
{
return
null
;
}
const
{
icon
}
=
item
;
const
name
=
unref
(
getI18nName
);
return
(
<
span
class=
{
`${prefixCls}__content-wrapper`
}
>
{
renderIcon
(
icon
)
}
{
<
span
class=
{
unref
(
getNameClass
)
}
>
{
name
}
{
renderTag
()
}
</
span
>
}
</
span
>
);
};
},
});
src/components/Menu/src/components/BasicMenuItem.vue
浏览文件 @
a65ad9ed
<
template
>
<
template
>
<MenuItem
:class=
"getLevelClass"
>
<MenuItem
:class=
"getLevelClass"
>
<MenuContent
v-bind=
"$props"
:item=
"item"
/>
<Menu
Item
Content
v-bind=
"$props"
:item=
"item"
/>
</MenuItem>
</MenuItem>
</
template
>
</
template
>
<
script
lang=
"ts"
>
<
script
lang=
"ts"
>
...
@@ -9,25 +9,18 @@
...
@@ -9,25 +9,18 @@
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
import
{
itemProps
}
from
'../props'
;
import
{
itemProps
}
from
'../props'
;
import
Menu
Content
from
'../MenuContent
'
;
import
Menu
ItemContent
from
'./MenuItemContent.vue
'
;
export
default
defineComponent
({
export
default
defineComponent
({
name
:
'BasicMenuItem'
,
name
:
'BasicMenuItem'
,
components
:
{
MenuItem
:
Menu
.
Item
,
MenuContent
},
components
:
{
MenuItem
:
Menu
.
Item
,
Menu
Item
Content
},
props
:
itemProps
,
props
:
itemProps
,
setup
(
props
)
{
setup
(
props
)
{
const
{
prefixCls
}
=
useDesign
(
'basic-menu-item'
);
const
{
prefixCls
}
=
useDesign
(
'basic-menu-item'
);
const
getLevelClass
=
computed
(()
=>
{
const
getLevelClass
=
computed
(()
=>
{
const
{
appendClass
,
level
,
item
,
parentPath
,
theme
}
=
props
;
const
{
level
,
theme
}
=
props
;
const
isAppendActiveCls
=
appendClass
&&
level
===
1
&&
item
.
path
===
parentPath
;
const
levelCls
=
[
const
levelCls
=
[
`
${
prefixCls
}
__level
${
level
}
`
,
theme
];
`
${
prefixCls
}
__level
${
level
}
`
,
theme
,
{
'top-active-menu'
:
isAppendActiveCls
,
},
];
return
levelCls
;
return
levelCls
;
});
});
return
{
return
{
...
...
src/components/Menu/src/components/BasicSubMenuItem.vue
浏览文件 @
a65ad9ed
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
<BasicMenuItem
v-if=
"!menuHasChildren(item)"
v-bind=
"$props"
/>
<BasicMenuItem
v-if=
"!menuHasChildren(item)"
v-bind=
"$props"
/>
<SubMenu
v-else
:class=
"[`$
{prefixCls}__level${level}`, theme]">
<SubMenu
v-else
:class=
"[`$
{prefixCls}__level${level}`, theme]">
<template
#
title
>
<template
#
title
>
<MenuContent
v-bind=
"$props"
:item=
"item"
/>
<Menu
Item
Content
v-bind=
"$props"
:item=
"item"
/>
</
template
>
</
template
>
<!-- <template #expandIcon="{ key }">
<!-- <template #expandIcon="{ key }">
<ExpandIcon :key="key" />
<ExpandIcon :key="key" />
...
@@ -21,17 +21,17 @@
...
@@ -21,17 +21,17 @@
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
import
{
itemProps
}
from
'../props'
;
import
{
itemProps
}
from
'../props'
;
import
BasicMenuItem
from
'./BasicMenuItem.vue'
;
import
BasicMenuItem
from
'./BasicMenuItem.vue'
;
import
MenuContent
from
'../MenuContent'
;
import
MenuItemContent
from
'./MenuItemContent.vue'
;
// import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
// import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
export
default
defineComponent
({
export
default
defineComponent
({
name
:
'BasicSubMenuItem'
,
name
:
'BasicSubMenuItem'
,
isSubMenu
:
true
,
components
:
{
components
:
{
BasicMenuItem
,
BasicMenuItem
,
SubMenu
:
Menu
.
SubMenu
,
SubMenu
:
Menu
.
SubMenu
,
MenuItem
:
Menu
.
Item
,
MenuItem
:
Menu
.
Item
,
MenuContent
,
Menu
Item
Content
,
// ExpandIcon: createAsyncComponent(() => import('./ExpandIcon.vue')),
// ExpandIcon: createAsyncComponent(() => import('./ExpandIcon.vue')),
},
},
props
:
itemProps
,
props
:
itemProps
,
...
...
src/components/Menu/src/components/MenuItemContent.vue
0 → 100644
浏览文件 @
a65ad9ed
<
template
>
<span
:class=
"`$
{prefixCls}-wrapper`">
<Icon
v-if=
"getIcon"
:icon=
"getIcon"
:size=
"18"
:class=
"`$
{prefixCls}-wrapper__icon`" />
<span
:class=
"getNameClass"
>
{{
getI18nName
}}
<MenuItemTag
v-bind=
"$props"
/>
</span>
</span>
</
template
>
<
script
lang=
"ts"
>
import
{
computed
,
defineComponent
}
from
'vue'
;
import
Icon
from
'/@/components/Icon/index'
;
import
{
useI18n
}
from
'/@/hooks/web/useI18n'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
import
{
contentProps
}
from
'../props'
;
import
{
createAsyncComponent
}
from
'/@/utils/factory/createAsyncComponent'
;
const
{
t
}
=
useI18n
();
export
default
defineComponent
({
name
:
'MenuItemContent'
,
components
:
{
Icon
,
MenuItemTag
:
createAsyncComponent
(()
=>
import
(
'./MenuItemTag.vue'
))
},
props
:
contentProps
,
setup
(
props
)
{
const
{
prefixCls
}
=
useDesign
(
'basic-menu-item-content'
);
const
getI18nName
=
computed
(()
=>
t
(
props
.
item
?.
name
));
const
getIcon
=
computed
(()
=>
props
.
item
?.
icon
);
const
getNameClass
=
computed
(()
=>
{
const
{
showTitle
}
=
props
;
return
{
[
`
${
prefixCls
}
--show-title`
]:
showTitle
,
[
`
${
prefixCls
}
__name`
]:
!
showTitle
};
});
return
{
prefixCls
,
getNameClass
,
getI18nName
,
getIcon
,
};
},
});
</
script
>
src/components/Menu/src/components/MenuItemTag.vue
0 → 100644
浏览文件 @
a65ad9ed
<
template
>
<span
:class=
"getTagClass"
v-if=
"getShowTag"
>
{{
getContent
}}
</span>
</
template
>
<
script
lang=
"ts"
>
import
{
defineComponent
,
computed
}
from
'vue'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
import
{
contentProps
}
from
'../props'
;
export
default
defineComponent
({
name
:
'MenuItemTag'
,
props
:
contentProps
,
setup
(
props
)
{
const
{
prefixCls
}
=
useDesign
(
'basic-menu-item-tag'
);
const
getShowTag
=
computed
(()
=>
{
const
{
item
,
showTitle
,
isHorizontal
}
=
props
;
if
(
!
item
||
showTitle
||
isHorizontal
)
return
false
;
const
{
tag
}
=
item
;
if
(
!
tag
)
return
false
;
const
{
dot
,
content
}
=
tag
;
if
(
!
dot
&&
!
content
)
return
false
;
return
true
;
});
const
getContent
=
computed
(()
=>
{
if
(
!
getShowTag
.
value
)
return
''
;
const
{
item
}
=
props
;
const
{
tag
}
=
item
;
const
{
dot
,
content
}
=
tag
!
;
return
dot
?
''
:
content
;
});
const
getTagClass
=
computed
(()
=>
{
const
{
item
}
=
props
;
const
{
tag
=
{}
}
=
item
||
{};
const
{
dot
,
type
=
'error'
}
=
tag
;
return
[
prefixCls
,
[
`
${
prefixCls
}
--
${
type
}
`
],
{
[
`
${
prefixCls
}
--dot`
]:
dot
,
},
];
});
return
{
prefixCls
,
getTagClass
,
getShowTag
,
getContent
,
};
},
});
</
script
>
src/components/Menu/src/index.less
浏览文件 @
a65ad9ed
@import (reference) '../../../design/index.less';
@import (reference) '../../../design/index.less';
@basic-menu-prefix-cls: ~'@{namespace}-basic-menu';
@basic-menu-prefix-cls: ~'@{namespace}-basic-menu';
@basic-menu-content-prefix-cls: ~'@{namespace}-basic-menu-item-content';
@basic-menu-tag-prefix-cls: ~'@{namespace}-basic-menu-item-tag';
.active-style() {
.active-style() {
color: @white;
color: @white;
...
@@ -41,7 +43,7 @@
...
@@ -41,7 +43,7 @@
// }
// }
// collapsed show title start
// collapsed show title start
&
--show-title {
.@{basic-menu-content-prefix-cls}
--show-title {
max-width: unset !important;
max-width: unset !important;
opacity: 1 !important;
opacity: 1 !important;
}
}
...
@@ -78,104 +80,34 @@
...
@@ -78,104 +80,34 @@
& > li > .ant-menu-submenu-title {
& > li > .ant-menu-submenu-title {
line-height: 24px;
line-height: 24px;
}
}
.@{basic-menu-
prefix-cls}__content
-wrapper {
.@{basic-menu-
content-prefix-cls}
-wrapper {
display: flex;
display: flex;
justify-content: center;
justify-content: center;
align-items: center;
align-items: center;
flex-direction: column;
flex-direction: column;
.@{basic-menu-prefix-cls}--show-title {
.@{basic-menu-
content-
prefix-cls}--show-title {
line-height: 30px;
line-height: 30px;
}
}
}
}
}
}
.ant-menu-item {
.@{basic-menu-content-prefix-cls}-wrapper {
transition: unset;
width: 100%;
}
// scrollbar -s tart
// &-wrapper {
/* 滚动槽 */
// &::-webkit-scrollbar {
// width: 5px;
// height: 5px;
// }
// &::-webkit-scrollbar-track {
// background: rgba(0, 0, 0, 0);
// }
// &::-webkit-scrollbar-thumb {
// background: rgba(255, 255, 255, 0.2);
// border-radius: 3px;
// box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.1);
// }
// ::-webkit-scrollbar-thumb:hover {
// background: @border-color-dark;
// }
// }
// scrollbar end
&-item__level1.light {
&__icon {
&.top-active-menu {
vertical-align: text-top;
top: 0 !important;
}
}
}
&.top-active-menu:not(.ant-menu-item-selected) {
.ant-menu-item {
color: @primary-color;
transition: unset;
border-bottom: 3px solid @primary-color;
}
}
}
&__sidebar-hor {
&__sidebar-hor {
// overflow: hidden;
&.ant-menu-horizontal {
&.ant-menu-horizontal {
display: flex;
display: flex;
border: 0;
align-items: center;
align-items: center;
.@{basic-menu-prefix-cls}-item__level1 {
margin-right: 2px;
}
&.ant-menu-light {
.ant-menu-item {
&.@{basic-menu-prefix-cls}-item__level1 {
height: @header-height;
line-height: @header-height;
}
}
.ant-menu-submenu:hover,
.ant-menu-item-open,
.ant-menu-submenu-open,
.ant-menu-item-selected,
.ant-menu-submenu-selected,
.ant-menu-item:hover,
.ant-menu-item-active,
.ant-menu:not(.ant-menu-inline) .ant-menu-submenu-open,
.ant-menu-submenu-active,
.ant-menu-submenu-title:hover {
color: @primary-color !important;
border-bottom: 3px solid @primary-color;
}
.ant-menu-submenu {
&:hover {
border-bottom: 3px solid @primary-color;
}
&.ant-menu-selected,
&.ant-menu-submenu-selected {
border-bottom: 3px solid @primary-color;
}
}
}
&.ant-menu-dark {
&.ant-menu-dark {
background: transparent;
background: transparent;
...
@@ -204,12 +136,6 @@
...
@@ -204,12 +136,6 @@
.@{basic-menu-prefix-cls}-item__level1 {
.@{basic-menu-prefix-cls}-item__level1 {
background: transparent;
background: transparent;
&.top-active-menu {
color: @white;
background: @top-menu-active-bg-color;
border-radius: 2px 2px 0 0;
}
&.ant-menu-item-selected,
&.ant-menu-item-selected,
&.ant-menu-submenu-selected {
&.ant-menu-submenu-selected {
background: @top-menu-active-bg-color !important;
background: @top-menu-active-bg-color !important;
...
@@ -292,7 +218,7 @@
...
@@ -292,7 +218,7 @@
}
}
&.ant-menu-light:not(.@{basic-menu-prefix-cls}__sidebar-hor) {
&.ant-menu-light:not(.@{basic-menu-prefix-cls}__sidebar-hor) {
overflow: hidden;
//
overflow: hidden;
border-right: none;
border-right: none;
.ant-menu-item.ant-menu-item-selected.@{basic-menu-prefix-cls}-menu-item__level1,
.ant-menu-item.ant-menu-item-selected.@{basic-menu-prefix-cls}-menu-item__level1,
...
@@ -301,26 +227,32 @@
...
@@ -301,26 +227,32 @@
}
}
}
}
// 激活的子菜单样式
.ant-menu-item.ant-menu-item-selected {
position: relative;
}
&.@{basic-menu-prefix-cls}__second.ant-menu-inline-collapsed:not(.@{basic-menu-prefix-cls}__sidebar-hor) {
&.@{basic-menu-prefix-cls}__second.ant-menu-inline-collapsed:not(.@{basic-menu-prefix-cls}__sidebar-hor) {
// Reset menu item row height
// Reset menu item row height
.ant-menu-item,
.@{basic-menu-prefix-cls}-item__level1 {
.ant-menu-sub.ant-menu-inline > .ant-menu-item,
.ant-menu-sub.ant-menu-inline > .ant-menu-submenu > .ant-menu-submenu-title {
display: flex;
display: flex;
height: @app-menu-item-height * 1.4;
height: @app-menu-item-height * 1.4;
padding: 6px 0 !important;
padding: 6px 0 !important;
margin: 0;
margin: 0;
font-size: 12px;
line-height: @app-menu-item-height;
line-height: @app-menu-item-height;
align-items: center;
align-items: center;
text-align: center;
> div {
padding: 6px 0 !important;
font-size: 12px;
}
.@{basic-menu-content-prefix-cls}__name {
display: inline-block;
width: 50%;
overflow: hidden;
}
}
}
}
}
.@{basic-menu-
prefix-cls}__tag
{
.@{basic-menu-
tag-prefix-cls}
{
position: absolute;
position: absolute;
top: calc(50% - 8px);
top: calc(50% - 8px);
right: 30px;
right: 30px;
...
@@ -332,7 +264,7 @@
...
@@ -332,7 +264,7 @@
color: #fff;
color: #fff;
border-radius: 2px;
border-radius: 2px;
&
.
dot {
&
--
dot {
top: calc(50% - 4px);
top: calc(50% - 4px);
width: 8px;
width: 8px;
height: 8px;
height: 8px;
...
@@ -340,19 +272,19 @@
...
@@ -340,19 +272,19 @@
border-radius: 50%;
border-radius: 50%;
}
}
&
.
primary {
&
--
primary {
background: @primary-color;
background: @primary-color;
}
}
&
.
error {
&
--
error {
background: @error-color;
background: @error-color;
}
}
&
.
success {
&
--
success {
background: @success-color;
background: @success-color;
}
}
&
.
warn {
&
--
warn {
background: @warning-color;
background: @warning-color;
}
}
}
}
...
@@ -362,10 +294,6 @@
...
@@ -362,10 +294,6 @@
transition: unset;
transition: unset;
}
}
// .ant-menu-submenu-arrow {
// transition: all 0.15s ease 0s;
// }
.ant-menu-inline.ant-menu-sub {
.ant-menu-inline.ant-menu-sub {
box-shadow: unset !important;
box-shadow: unset !important;
transition: unset;
transition: unset;
...
@@ -384,10 +312,10 @@
...
@@ -384,10 +312,10 @@
// collapsed show title end
// collapsed show title end
.ant-menu-item,
.ant-menu-item,
.ant-menu-submenu-title {
.ant-menu-submenu-title {
> .@{basic-menu-prefix-cls}__name {
> .@{basic-menu-
content-
prefix-cls}__name {
width: 100%;
width: 100%;
.@{basic-menu-
prefix-cls}__tag
{
.@{basic-menu-
tag-prefix-cls}
{
float: right;
float: right;
margin-top: @app-menu-item-height / 2;
margin-top: @app-menu-item-height / 2;
transform: translate(0%, -50%);
transform: translate(0%, -50%);
...
...
src/components/Menu/src/props.ts
浏览文件 @
a65ad9ed
...
@@ -9,7 +9,6 @@ export const basicProps = {
...
@@ -9,7 +9,6 @@ export const basicProps = {
type
:
Array
as
PropType
<
Menu
[]
>
,
type
:
Array
as
PropType
<
Menu
[]
>
,
default
:
()
=>
[],
default
:
()
=>
[],
},
},
appendClass
:
propTypes
.
bool
,
collapsedShowTitle
:
propTypes
.
bool
,
collapsedShowTitle
:
propTypes
.
bool
,
...
@@ -42,8 +41,16 @@ export const itemProps = {
...
@@ -42,8 +41,16 @@ export const itemProps = {
},
},
level
:
propTypes
.
number
,
level
:
propTypes
.
number
,
theme
:
propTypes
.
oneOf
([
'dark'
,
'light'
]),
theme
:
propTypes
.
oneOf
([
'dark'
,
'light'
]),
appendClass
:
propTypes
.
bool
,
parentPath
:
propTypes
.
string
,
showTitle
:
propTypes
.
bool
,
showTitle
:
propTypes
.
bool
,
isHorizontal
:
propTypes
.
bool
,
isHorizontal
:
propTypes
.
bool
,
};
};
export
const
contentProps
=
{
item
:
{
type
:
Object
as
PropType
<
Menu
>
,
default
:
null
,
},
showTitle
:
propTypes
.
bool
.
def
(
true
),
level
:
propTypes
.
number
.
def
(
0
),
isHorizontal
:
propTypes
.
bool
.
def
(
true
),
};
src/components/Menu/src/useOpenKeys.ts
浏览文件 @
a65ad9ed
...
@@ -42,6 +42,8 @@ export function useOpenKeys(
...
@@ -42,6 +42,8 @@ export function useOpenKeys(
if
(
unref
(
mode
)
===
MenuModeEnum
.
HORIZONTAL
||
!
unref
(
accordion
))
{
if
(
unref
(
mode
)
===
MenuModeEnum
.
HORIZONTAL
||
!
unref
(
accordion
))
{
menuState
.
openKeys
=
openKeys
;
menuState
.
openKeys
=
openKeys
;
}
else
{
}
else
{
// const menuList = toRaw(menus.value);
// getAllParentPath(menuList, path);
const
rootSubMenuKeys
:
string
[]
=
[];
const
rootSubMenuKeys
:
string
[]
=
[];
for
(
const
{
children
,
path
}
of
unref
(
menus
))
{
for
(
const
{
children
,
path
}
of
unref
(
menus
))
{
if
(
children
&&
children
.
length
>
0
)
{
if
(
children
&&
children
.
length
>
0
)
{
...
...
src/components/Page/src/PageFooter.vue
浏览文件 @
a65ad9ed
...
@@ -22,11 +22,13 @@
...
@@ -22,11 +22,13 @@
});
});
</
script
>
</
script
>
<
style
lang=
"less"
scoped
>
<
style
lang=
"less"
scoped
>
@import
(
reference
)
'../../../design/index.less'
;
.app-footer
{
.app-footer
{
position
:
fixed
;
position
:
fixed
;
right
:
0
;
right
:
0
;
bottom
:
0
;
bottom
:
0
;
z-index
:
99
;
z-index
:
@
page-footer-z-index
;
display
:
flex
;
display
:
flex
;
width
:
100%
;
width
:
100%
;
align-items
:
center
;
align-items
:
center
;
...
...
src/components/Preview/src/index.less
浏览文件 @
a65ad9ed
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
right: 0;
right: 0;
bottom: 0;
bottom: 0;
left: 0;
left: 0;
z-index:
1000
;
z-index:
@preview-comp-z-index
;
background: rgba(0, 0, 0, 0.5);
background: rgba(0, 0, 0, 0.5);
user-select: none;
user-select: none;
...
...
src/components/Upload/src/UploadModal.vue
浏览文件 @
a65ad9ed
...
@@ -55,7 +55,6 @@
...
@@ -55,7 +55,6 @@
import
{
checkFileType
,
checkImgType
,
getBase64WithFile
}
from
'./helper'
;
import
{
checkFileType
,
checkImgType
,
getBase64WithFile
}
from
'./helper'
;
import
{
buildUUID
}
from
'/@/utils/uuid'
;
import
{
buildUUID
}
from
'/@/utils/uuid'
;
import
{
createImgPreview
}
from
'/@/components/Preview/index'
;
import
{
createImgPreview
}
from
'/@/components/Preview/index'
;
import
{
uploadApi
}
from
'/@/api/sys/upload'
;
import
{
isFunction
}
from
'/@/utils/is'
;
import
{
isFunction
}
from
'/@/utils/is'
;
import
{
warn
}
from
'/@/utils/log'
;
import
{
warn
}
from
'/@/utils/log'
;
import
FileList
from
'./FileList'
;
import
FileList
from
'./FileList'
;
...
@@ -176,7 +175,7 @@
...
@@ -176,7 +175,7 @@
}
}
try
{
try
{
item
.
status
=
UploadResultStatus
.
UPLOADING
;
item
.
status
=
UploadResultStatus
.
UPLOADING
;
const
{
data
}
=
await
uploadApi
(
const
{
data
}
=
await
props
.
api
?.
(
{
{
...(
props
.
uploadParams
||
{}),
...(
props
.
uploadParams
||
{}),
file
:
item
.
file
,
file
:
item
.
file
,
...
...
src/design/color.less
浏览文件 @
a65ad9ed
...
@@ -128,7 +128,7 @@
...
@@ -128,7 +128,7 @@
// =================================
// =================================
// ==============breadcrumb=========
// ==============breadcrumb=========
// =================================
// =================================
@breadcrumb-item-normal-color: #
6e90a7
;
@breadcrumb-item-normal-color: #
999
;
// =================================
// =================================
// ==============button=============
// ==============button=============
// =================================
// =================================
...
...
src/design/index.less
浏览文件 @
a65ad9ed
...
@@ -31,6 +31,10 @@ html,
...
@@ -31,6 +31,10 @@ html,
background-color: #fff !important;
background-color: #fff !important;
}
}
html {
overflow: hidden;
}
html,
html,
body {
body {
width: 100%;
width: 100%;
...
...
src/design/var/index.less
浏览文件 @
a65ad9ed
...
@@ -11,12 +11,24 @@
...
@@ -11,12 +11,24 @@
@header-height: 48px;
@header-height: 48px;
// logo width
// logo width
@logo-width: 3
6
px;
@logo-width: 3
2
px;
//
//
@side-drag-z-index: 200;
@side-drag-z-index: 200;
@page-loading-z-index: 10000;
@page-loading-z-index: 10000;
@lock-page-z-index: 3000;
@layout-header-fixed-z-index: 500;
@multiple-tab-fixed-z-index: 505;
@layout-sider-fixed-z-index: 510;
@preview-comp-z-index: 1000;
@page-footer-z-index: 99;
// left-menu
// left-menu
@app-menu-item-height: 42px;
@app-menu-item-height: 42px;
src/hooks/event/useBreakpoint.ts
浏览文件 @
a65ad9ed
...
@@ -10,6 +10,9 @@ export interface CreateCallbackParams {
...
@@ -10,6 +10,9 @@ export interface CreateCallbackParams {
screen
:
ComputedRef
<
sizeEnum
|
undefined
>
;
screen
:
ComputedRef
<
sizeEnum
|
undefined
>
;
width
:
ComputedRef
<
number
>
;
width
:
ComputedRef
<
number
>
;
realWidth
:
ComputedRef
<
number
>
;
realWidth
:
ComputedRef
<
number
>
;
screenEnum
:
typeof
screenEnum
;
screenMap
:
Map
<
sizeEnum
,
number
>
;
sizeEnum
:
typeof
sizeEnum
;
}
}
export
function
useBreakpoint
()
{
export
function
useBreakpoint
()
{
...
@@ -54,8 +57,8 @@ export function createBreakpointListen(fn?: (opt: CreateCallbackParams) => void)
...
@@ -54,8 +57,8 @@ export function createBreakpointListen(fn?: (opt: CreateCallbackParams) => void)
name
:
'resize'
,
name
:
'resize'
,
listener
:
()
=>
{
listener
:
()
=>
{
resizeFn
();
getWindowWidth
();
getWindowWidth
();
resizeFn
();
},
},
});
});
...
@@ -65,12 +68,14 @@ export function createBreakpointListen(fn?: (opt: CreateCallbackParams) => void)
...
@@ -65,12 +68,14 @@ export function createBreakpointListen(fn?: (opt: CreateCallbackParams) => void)
globalRealWidthRef
=
computed
(():
number
=>
unref
(
realWidthRef
));
globalRealWidthRef
=
computed
(():
number
=>
unref
(
realWidthRef
));
function
resizeFn
()
{
function
resizeFn
()
{
fn
&&
fn
?.({
fn
({
screen
:
globalScreenRef
,
screen
:
globalScreenRef
,
width
:
globalWidthRef
,
width
:
globalWidthRef
,
realWidth
:
globalRealWidthRef
,
realWidth
:
globalRealWidthRef
,
screenEnum
,
});
screenMap
,
sizeEnum
,
});
}
}
resizeFn
();
resizeFn
();
...
...
src/hooks/setting/useHeaderSetting.ts
浏览文件 @
a65ad9ed
...
@@ -4,7 +4,6 @@ import { computed, unref } from 'vue';
...
@@ -4,7 +4,6 @@ import { computed, unref } from 'vue';
import
{
appStore
}
from
'/@/store/modules/app'
;
import
{
appStore
}
from
'/@/store/modules/app'
;
import
{
useMultipleTabSetting
}
from
'/@/hooks/setting/useMultipleTabSetting'
;
import
{
useMenuSetting
}
from
'/@/hooks/setting/useMenuSetting'
;
import
{
useMenuSetting
}
from
'/@/hooks/setting/useMenuSetting'
;
import
{
useRootSetting
}
from
'/@/hooks/setting/useRootSetting'
;
import
{
useRootSetting
}
from
'/@/hooks/setting/useRootSetting'
;
import
{
useFullContent
}
from
'/@/hooks/web/useFullContent'
;
import
{
useFullContent
}
from
'/@/hooks/web/useFullContent'
;
...
@@ -12,7 +11,6 @@ import { useFullContent } from '/@/hooks/web/useFullContent';
...
@@ -12,7 +11,6 @@ import { useFullContent } from '/@/hooks/web/useFullContent';
import
{
MenuModeEnum
}
from
'/@/enums/menuEnum'
;
import
{
MenuModeEnum
}
from
'/@/enums/menuEnum'
;
const
{
getFullContent
}
=
useFullContent
();
const
{
getFullContent
}
=
useFullContent
();
const
{
getShowMultipleTab
}
=
useMultipleTabSetting
();
const
{
const
{
getMenuMode
,
getMenuMode
,
getSplit
,
getSplit
,
...
@@ -53,8 +51,6 @@ const getHeaderBgColor = computed(() => unref(getHeaderSetting).bgColor);
...
@@ -53,8 +51,6 @@ const getHeaderBgColor = computed(() => unref(getHeaderSetting).bgColor);
const
getShowSearch
=
computed
(()
=>
unref
(
getHeaderSetting
).
showSearch
);
const
getShowSearch
=
computed
(()
=>
unref
(
getHeaderSetting
).
showSearch
);
const
getShowRedo
=
computed
(()
=>
unref
(
getHeaderSetting
).
showRedo
&&
unref
(
getShowMultipleTab
));
const
getUseLockPage
=
computed
(()
=>
unref
(
getHeaderSetting
).
useLockPage
);
const
getUseLockPage
=
computed
(()
=>
unref
(
getHeaderSetting
).
useLockPage
);
const
getShowFullScreen
=
computed
(()
=>
unref
(
getHeaderSetting
).
showFullScreen
);
const
getShowFullScreen
=
computed
(()
=>
unref
(
getHeaderSetting
).
showFullScreen
);
...
@@ -91,7 +87,6 @@ export function useHeaderSetting() {
...
@@ -91,7 +87,6 @@ export function useHeaderSetting() {
getShowDoc
,
getShowDoc
,
getShowSearch
,
getShowSearch
,
getHeaderTheme
,
getHeaderTheme
,
getShowRedo
,
getUseLockPage
,
getUseLockPage
,
getShowFullScreen
,
getShowFullScreen
,
getShowNotice
,
getShowNotice
,
...
...
src/hooks/setting/useMenuSetting.ts
浏览文件 @
a65ad9ed
...
@@ -65,6 +65,10 @@ const getIsHorizontal = computed(() => {
...
@@ -65,6 +65,10 @@ const getIsHorizontal = computed(() => {
return
unref
(
getMenuMode
)
===
MenuModeEnum
.
HORIZONTAL
;
return
unref
(
getMenuMode
)
===
MenuModeEnum
.
HORIZONTAL
;
});
});
const
getIsMixMode
=
computed
(()
=>
{
return
unref
(
getMenuMode
)
===
MenuModeEnum
.
INLINE
&&
unref
(
getMenuType
)
===
MenuTypeEnum
.
MIX
;
});
const
getRealWidth
=
computed
(()
=>
{
const
getRealWidth
=
computed
(()
=>
{
return
unref
(
getCollapsed
)
?
unref
(
getMiniWidthNumber
)
:
unref
(
getMenuWidth
);
return
unref
(
getCollapsed
)
?
unref
(
getMiniWidthNumber
)
:
unref
(
getMenuWidth
);
});
});
...
@@ -130,5 +134,6 @@ export function useMenuSetting() {
...
@@ -130,5 +134,6 @@ export function useMenuSetting() {
getIsTopMenu
,
getIsTopMenu
,
getMenuBgColor
,
getMenuBgColor
,
getShowSidebar
,
getShowSidebar
,
getIsMixMode
,
};
};
}
}
src/hooks/setting/useMultipleTabSetting.ts
浏览文件 @
a65ad9ed
...
@@ -10,6 +10,8 @@ const getShowMultipleTab = computed(() => unref(getMultipleTabSetting).show);
...
@@ -10,6 +10,8 @@ const getShowMultipleTab = computed(() => unref(getMultipleTabSetting).show);
const
getShowQuick
=
computed
(()
=>
unref
(
getMultipleTabSetting
).
showQuick
);
const
getShowQuick
=
computed
(()
=>
unref
(
getMultipleTabSetting
).
showQuick
);
const
getShowRedo
=
computed
(()
=>
unref
(
getMultipleTabSetting
).
showRedo
);
function
setMultipleTabSetting
(
multiTabsSetting
:
Partial
<
MultiTabsSetting
>
)
{
function
setMultipleTabSetting
(
multiTabsSetting
:
Partial
<
MultiTabsSetting
>
)
{
appStore
.
commitProjectConfigState
({
multiTabsSetting
});
appStore
.
commitProjectConfigState
({
multiTabsSetting
});
}
}
...
@@ -21,5 +23,6 @@ export function useMultipleTabSetting() {
...
@@ -21,5 +23,6 @@ export function useMultipleTabSetting() {
getMultipleTabSetting
,
getMultipleTabSetting
,
getShowMultipleTab
,
getShowMultipleTab
,
getShowQuick
,
getShowQuick
,
getShowRedo
,
};
};
}
}
src/hooks/web/useAppInject.ts
0 → 100644
浏览文件 @
a65ad9ed
import
{
useAppProviderContext
}
from
'/@/components/Application'
;
import
{
computed
,
unref
}
from
'vue'
;
export
function
useAppInject
()
{
const
values
=
useAppProviderContext
();
return
{
getIsMobile
:
computed
(()
=>
unref
(
values
.
isMobile
)),
};
}
src/hooks/web/useI18n.ts
浏览文件 @
a65ad9ed
...
@@ -25,7 +25,7 @@ export function useI18n(namespace?: string) {
...
@@ -25,7 +25,7 @@ export function useI18n(namespace?: string) {
return
{
return
{
...
methods
,
...
methods
,
t
:
(
key
:
string
,
...
arg
:
Partial
<
Parameters
<
typeof
t
>>
)
=>
{
t
:
(
key
:
string
,
...
arg
:
any
)
=>
{
if
(
!
key
)
return
''
;
if
(
!
key
)
return
''
;
return
t
(
getKey
(
key
),
...(
arg
as
Parameters
<
typeof
t
>
));
return
t
(
getKey
(
key
),
...(
arg
as
Parameters
<
typeof
t
>
));
},
},
...
...
src/hooks/web/usePage.ts
浏览文件 @
a65ad9ed
...
@@ -33,11 +33,13 @@ export function useGo() {
...
@@ -33,11 +33,13 @@ export function useGo() {
export
const
useRedo
=
()
=>
{
export
const
useRedo
=
()
=>
{
const
{
push
,
currentRoute
}
=
router
;
const
{
push
,
currentRoute
}
=
router
;
const
{
query
,
params
}
=
currentRoute
.
value
;
const
{
query
,
params
}
=
currentRoute
.
value
;
function
redo
()
{
function
redo
():
Promise
<
boolean
>
{
push
({
return
new
Promise
((
resolve
)
=>
{
path
:
'/redirect'
+
unref
(
currentRoute
).
fullPath
,
push
({
query
,
path
:
'/redirect'
+
unref
(
currentRoute
).
fullPath
,
params
,
query
,
params
,
}).
then
(()
=>
resolve
(
true
));
});
});
}
}
return
redo
;
return
redo
;
...
...
src/hooks/web/useTabs.ts
浏览文件 @
a65ad9ed
...
@@ -11,7 +11,11 @@ export function useTabs() {
...
@@ -11,7 +11,11 @@ export function useTabs() {
}
}
return
{
return
{
refreshPage
:
()
=>
canIUseFn
()
&&
tabStore
.
commitRedoPage
(),
refreshPage
:
async
()
=>
{
if
(
canIUseFn
())
{
await
tabStore
.
commitRedoPage
();
}
},
closeAll
:
()
=>
canIUseFn
()
&&
tabStore
.
closeAllTabAction
(),
closeAll
:
()
=>
canIUseFn
()
&&
tabStore
.
closeAllTabAction
(),
closeLeft
:
()
=>
canIUseFn
()
&&
tabStore
.
closeLeftTabAction
(
tabStore
.
getCurrentTab
),
closeLeft
:
()
=>
canIUseFn
()
&&
tabStore
.
closeLeftTabAction
(
tabStore
.
getCurrentTab
),
closeRight
:
()
=>
canIUseFn
()
&&
tabStore
.
closeRightTabAction
(
tabStore
.
getCurrentTab
),
closeRight
:
()
=>
canIUseFn
()
&&
tabStore
.
closeRightTabAction
(
tabStore
.
getCurrentTab
),
...
...
src/layouts/default/content/index.vue
浏览文件 @
a65ad9ed
...
@@ -20,11 +20,10 @@
...
@@ -20,11 +20,10 @@
import
{
useTransitionSetting
}
from
'/@/hooks/setting/useTransitionSetting'
;
import
{
useTransitionSetting
}
from
'/@/hooks/setting/useTransitionSetting'
;
import
PageLayout
from
'/@/layouts/page/index'
;
import
PageLayout
from
'/@/layouts/page/index'
;
import
{
Loading
}
from
'/@/components/Loading'
;
import
{
Loading
}
from
'/@/components/Loading'
;
import
Transition
from
'/@/views/demo/comp/lazy/Transition.vue'
;
export
default
defineComponent
({
export
default
defineComponent
({
name
:
'LayoutContent'
,
name
:
'LayoutContent'
,
components
:
{
PageLayout
,
Loading
,
Transition
},
components
:
{
PageLayout
,
Loading
},
setup
()
{
setup
()
{
const
{
prefixCls
}
=
useDesign
(
'layout-content'
);
const
{
prefixCls
}
=
useDesign
(
'layout-content'
);
const
{
getOpenPageLoading
}
=
useTransitionSetting
();
const
{
getOpenPageLoading
}
=
useTransitionSetting
();
...
...
src/layouts/default/header/LayoutHeader.tsx
浏览文件 @
a65ad9ed
...
@@ -3,38 +3,19 @@ import './index.less';
...
@@ -3,38 +3,19 @@ import './index.less';
import
type
{
FunctionalComponent
}
from
'vue'
;
import
type
{
FunctionalComponent
}
from
'vue'
;
import
type
{
Component
}
from
'/@/components/types'
;
import
type
{
Component
}
from
'/@/components/types'
;
import
{
import
{
defineComponent
,
unref
,
computed
}
from
'vue'
;
defineComponent
,
unref
,
computed
,
ref
,
nextTick
,
watchEffect
,
// nextTick
}
from
'vue'
;
import
{
Layout
,
Tooltip
,
Badge
}
from
'ant-design-vue'
;
import
{
Layout
,
Tooltip
,
Badge
}
from
'ant-design-vue'
;
import
{
AppLogo
}
from
'/@/components/Application'
;
import
{
AppLogo
}
from
'/@/components/Application'
;
import
UserDropdown
from
'./UserDropdown'
;
import
LayoutMenu
from
'../menu'
;
import
LayoutMenu
from
'../menu'
;
import
LayoutBreadcrumb
from
'./LayoutBreadcrumb.vue'
;
import
LockAction
from
'./actions/LockAction'
;
import
LockAction
from
'./actions/LockAction'
;
import
LayoutTrigger
from
'../trigger/index.vue'
;
import
LayoutTrigger
from
'../trigger/index.vue'
;
import
NoticeAction
from
'./notice/NoticeActionItem.vue'
;
import
NoticeAction
from
'./notice/NoticeActionItem.vue'
;
import
{
import
{
LockOutlined
,
BugOutlined
}
from
'@ant-design/icons-vue'
;
RedoOutlined
,
FullscreenExitOutlined
,
FullscreenOutlined
,
LockOutlined
,
BugOutlined
,
}
from
'@ant-design/icons-vue'
;
import
{
AppSearch
}
from
'/@/components/Application'
;
import
{
AppSearch
}
from
'/@/components/Application'
;
import
{
useModal
}
from
'/@/components/Modal'
;
import
{
useModal
}
from
'/@/components/Modal'
;
import
{
useFullscreen
}
from
'/@/hooks/web/useFullScreen'
;
import
{
useTabs
}
from
'/@/hooks/web/useTabs'
;
import
{
useWindowSizeFn
}
from
'/@/hooks/event/useWindowSizeFn'
;
import
{
useHeaderSetting
}
from
'/@/hooks/setting/useHeaderSetting'
;
import
{
useHeaderSetting
}
from
'/@/hooks/setting/useHeaderSetting'
;
import
{
useMenuSetting
}
from
'/@/hooks/setting/useMenuSetting'
;
import
{
useMenuSetting
}
from
'/@/hooks/setting/useMenuSetting'
;
import
{
useRootSetting
}
from
'/@/hooks/setting/useRootSetting'
;
import
{
useRootSetting
}
from
'/@/hooks/setting/useRootSetting'
;
...
@@ -49,8 +30,10 @@ import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
...
@@ -49,8 +30,10 @@ import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
import
{
AppLocalePicker
}
from
'/@/components/Application'
;
import
{
AppLocalePicker
}
from
'/@/components/Application'
;
import
{
useI18n
}
from
'/@/hooks/web/useI18n'
;
import
{
useI18n
}
from
'/@/hooks/web/useI18n'
;
import
{
propTypes
}
from
'/@/utils/propTypes'
;
import
{
propTypes
}
from
'/@/utils/propTypes'
;
import
{
useLayoutContext
}
from
'../useLayoutContext'
;
import
{
UserDropDown
,
LayoutBreadcrumb
,
FullScreen
}
from
'./components'
;
import
{
useAppInject
}
from
'/@/hooks/web/useAppInject'
;
import
{
useDesign
}
from
'../../../hooks/web/useDesign'
;
interface
TooltipItemProps
{
interface
TooltipItemProps
{
title
:
string
;
title
:
string
;
}
}
...
@@ -72,24 +55,14 @@ export default defineComponent({
...
@@ -72,24 +55,14 @@ export default defineComponent({
fixed
:
propTypes
.
bool
,
fixed
:
propTypes
.
bool
,
},
},
setup
(
props
)
{
setup
(
props
)
{
let
logoEl
:
Element
|
null
|
undefined
;
const
logoWidthRef
=
ref
(
200
);
const
logoRef
=
ref
<
ComponentRef
>
(
null
);
const
injectValue
=
useLayoutContext
();
const
{
refreshPage
}
=
useTabs
();
const
{
t
}
=
useI18n
();
const
{
t
}
=
useI18n
();
const
{
prefixCls
}
=
useDesign
(
'layout-header'
);
const
{
getShowTopMenu
,
getShowHeaderTrigger
,
getSplit
,
getIsHorizontal
}
=
useMenuSetting
();
const
{
getShowTopMenu
,
getShowHeaderTrigger
,
getSplit
}
=
useMenuSetting
();
const
{
getShowLocale
}
=
useLocaleSetting
();
const
{
getShowLocale
}
=
useLocaleSetting
();
const
{
getUseErrorHandle
,
getShowBreadCrumbIcon
}
=
useRootSetting
();
const
{
getUseErrorHandle
}
=
useRootSetting
();
const
{
const
{
getHeaderTheme
,
getHeaderTheme
,
getShowRedo
,
getUseLockPage
,
getUseLockPage
,
getShowFullScreen
,
getShowFullScreen
,
getShowNotice
,
getShowNotice
,
...
@@ -100,23 +73,11 @@ export default defineComponent({
...
@@ -100,23 +73,11 @@ export default defineComponent({
const
{
push
}
=
useRouter
();
const
{
push
}
=
useRouter
();
const
[
register
,
{
openModal
}]
=
useModal
();
const
[
register
,
{
openModal
}]
=
useModal
();
const
{
toggleFullscreen
,
isFullscreenRef
}
=
useFullscreen
();
const
{
getIsMobile
}
=
useAppInject
();
useWindowSizeFn
(
()
=>
{
calcTopMenuWidth
();
},
100
,
{
immediate
:
false
}
);
const
headerClass
=
computed
(()
=>
{
const
headerClass
=
computed
(()
=>
{
const
theme
=
unref
(
getHeaderTheme
);
const
theme
=
unref
(
getHeaderTheme
);
return
theme
?
`layout-header__header--
${
theme
}
`
:
''
;
return
theme
?
`
${
prefixCls
}
__header--
${
theme
}
`
:
''
;
});
const
isPc
=
computed
(()
=>
{
return
!
unref
(
injectValue
.
isMobile
);
});
});
const
getSplitType
=
computed
(()
=>
{
const
getSplitType
=
computed
(()
=>
{
...
@@ -127,25 +88,6 @@ export default defineComponent({
...
@@ -127,25 +88,6 @@ export default defineComponent({
return
unref
(
getSplit
)
?
MenuModeEnum
.
HORIZONTAL
:
null
;
return
unref
(
getSplit
)
?
MenuModeEnum
.
HORIZONTAL
:
null
;
});
});
watchEffect
(()
=>
{
if
(
unref
(
getIsHorizontal
))
{
calcTopMenuWidth
();
}
});
function
calcTopMenuWidth
()
{
nextTick
(()
=>
{
if
(
!
unref
(
getShowTopMenu
))
return
;
let
width
=
0
;
if
(
!
logoEl
)
{
logoEl
=
unref
(
logoRef
)?.
$el
;
}
if
(
!
logoEl
)
return
;
width
+=
logoEl
.
clientWidth
;
logoWidthRef
.
value
=
width
+
80
;
});
}
function
handleToErrorList
()
{
function
handleToErrorList
()
{
push
(
PageEnum
.
ERROR_LOG_PAGE
).
then
(()
=>
{
push
(
PageEnum
.
ERROR_LOG_PAGE
).
then
(()
=>
{
errorStore
.
commitErrorListCountState
(
0
);
errorStore
.
commitErrorListCountState
(
0
);
...
@@ -156,27 +98,28 @@ export default defineComponent({
...
@@ -156,27 +98,28 @@ export default defineComponent({
openModal
(
true
);
openModal
(
true
);
}
}
function
renderHeaderContent
()
{
function
renderHeaderLeft
()
{
const
width
=
unref
(
logoWidthRef
);
return
(
return
(
<
div
class=
"layout-header__content "
>
<>
{
unref
(
getShowHeaderLogo
)
&&
(
<
AppLogo
class=
{
`layout-header__logo`
}
ref=
{
logoRef
}
theme=
{
unref
(
getHeaderTheme
)
}
/>
)
}
{
unref
(
getShowContent
)
&&
(
{
unref
(
getShowContent
)
&&
(
<
div
class=
"layout-header__left"
>
<
div
class=
{
`${prefixCls}__left`
}
>
{
unref
(
getShowHeaderTrigger
)
&&
(
{
unref
(
getShowHeaderTrigger
)
&&
(
<
LayoutTrigger
theme=
{
unref
(
getHeaderTheme
)
}
sider=
{
false
}
/>
<
LayoutTrigger
theme=
{
unref
(
getHeaderTheme
)
}
sider=
{
false
}
/>
)
}
)
}
{
unref
(
getShowBread
)
&&
unref
(
isPc
)
&&
(
{
unref
(
getShowBread
)
&&
!
unref
(
getIsMobile
)
&&
(
<
LayoutBreadcrumb
showIcon=
{
unref
(
getShowBreadCrumbIcon
)
}
/>
<
LayoutBreadcrumb
theme=
{
unref
(
getHeaderTheme
)
}
/>
)
}
)
}
</
div
>
</
div
>
)
}
)
}
</>
);
}
{
unref
(
getShowTopMenu
)
&&
unref
(
isPc
)
&&
(
function
renderHeaderContent
()
{
<
div
class=
{
[
`layout-header__menu `
]
}
style=
{
{
width
:
`calc(100% - ${width}px)`
}
}
>
return
(
<
div
class=
{
`${prefixCls}__content`
}
>
{
unref
(
getShowTopMenu
)
&&
!
unref
(
getIsMobile
)
&&
(
<
div
class=
{
[
`${prefixCls}__menu `
]
}
>
{
/* <div class={[`layout-header__menu `]}> */
}
{
/* <div class={[`layout-header__menu `]}> */
}
<
LayoutMenu
<
LayoutMenu
isHorizontal=
{
true
}
isHorizontal=
{
true
}
...
@@ -193,18 +136,18 @@ export default defineComponent({
...
@@ -193,18 +136,18 @@ export default defineComponent({
function
renderActionDefault
(
Comp
:
Component
|
any
,
event
:
Fn
)
{
function
renderActionDefault
(
Comp
:
Component
|
any
,
event
:
Fn
)
{
return
(
return
(
<
div
class=
"layout-header__action-item"
onClick=
{
event
}
>
<
div
class=
{
`${prefixCls}__action-item`
}
onClick=
{
event
}
>
<
Comp
class=
"layout-header__action-icon"
/>
<
Comp
class=
{
`${prefixCls}__action-icon`
}
/>
</
div
>
</
div
>
);
);
}
}
function
renderAction
()
{
function
renderAction
()
{
return
(
return
(
<
div
class=
{
`
layout-header
__action`
}
>
<
div
class=
{
`
${prefixCls}
__action`
}
>
{
unref
(
isPc
)
&&
<
AppSearch
class=
"layout-header__action-item"
/>
}
{
!
unref
(
getIsMobile
)
&&
<
AppSearch
class=
{
`${prefixCls}__action-item`
}
/>
}
{
unref
(
getUseErrorHandle
)
&&
unref
(
isPc
)
&&
(
{
unref
(
getUseErrorHandle
)
&&
!
unref
(
getIsMobile
)
&&
(
<
TooltipItem
title=
{
t
(
'layout.header.tooltipErrorLog'
)
}
>
<
TooltipItem
title=
{
t
(
'layout.header.tooltipErrorLog'
)
}
>
{
()
=>
(
{
()
=>
(
<
Badge
<
Badge
...
@@ -219,48 +162,27 @@ export default defineComponent({
...
@@ -219,48 +162,27 @@ export default defineComponent({
</
TooltipItem
>
</
TooltipItem
>
)
}
)
}
{
unref
(
getUseLockPage
)
&&
unref
(
isPc
)
&&
(
{
unref
(
getUseLockPage
)
&&
!
unref
(
getIsMobile
)
&&
(
<
TooltipItem
title=
{
t
(
'layout.header.tooltipLock'
)
}
>
<
TooltipItem
title=
{
t
(
'layout.header.tooltipLock'
)
}
>
{
()
=>
renderActionDefault
(
LockOutlined
,
handleLockPage
)
}
{
()
=>
renderActionDefault
(
LockOutlined
,
handleLockPage
)
}
</
TooltipItem
>
</
TooltipItem
>
)
}
)
}
{
unref
(
getShowNotice
)
&&
unref
(
isPc
)
&&
(
{
unref
(
getShowNotice
)
&&
!
unref
(
getIsMobile
)
&&
(
<
TooltipItem
title=
{
t
(
'layout.header.tooltipNotify'
)
}
>
<
TooltipItem
title=
{
t
(
'layout.header.tooltipNotify'
)
}
>
{
()
=>
<
NoticeAction
/>
}
{
()
=>
<
NoticeAction
/>
}
</
TooltipItem
>
</
TooltipItem
>
)
}
)
}
{
unref
(
getShowRedo
)
&&
unref
(
isPc
)
&&
(
{
unref
(
getShowFullScreen
)
&&
!
unref
(
getIsMobile
)
&&
<
FullScreen
/>
}
<
TooltipItem
title=
{
t
(
'layout.header.tooltipRedo'
)
}
>
{
()
=>
renderActionDefault
(
RedoOutlined
,
refreshPage
)
}
<
UserDropDown
theme=
{
unref
(
getHeaderTheme
)
}
/>
</
TooltipItem
>
)
}
{
unref
(
getShowFullScreen
)
&&
unref
(
isPc
)
&&
(
<
TooltipItem
title=
{
unref
(
isFullscreenRef
)
?
t
(
'layout.header.tooltipExitFull'
)
:
t
(
'layout.header.tooltipEntryFull'
)
}
>
{
()
=>
{
const
Icon
=
!
unref
(
isFullscreenRef
)
?
(
<
FullscreenOutlined
/>
)
:
(
<
FullscreenExitOutlined
/>
);
return
renderActionDefault
(
Icon
,
toggleFullscreen
);
}
}
</
TooltipItem
>
)
}
<
UserDropdown
class=
"layout-header__user-dropdown"
/>
{
unref
(
getShowLocale
)
&&
(
{
unref
(
getShowLocale
)
&&
(
<
AppLocalePicker
<
AppLocalePicker
reload=
{
true
}
reload=
{
true
}
showText=
{
false
}
showText=
{
false
}
class=
"layout-header__action-item locale"
class=
{
`${prefixCls}__action-item locale`
}
/>
/>
)
}
)
}
</
div
>
</
div
>
...
@@ -270,6 +192,10 @@ export default defineComponent({
...
@@ -270,6 +192,10 @@ export default defineComponent({
function
renderHeaderDefault
()
{
function
renderHeaderDefault
()
{
return
(
return
(
<>
<>
{
unref
(
getShowHeaderLogo
)
&&
(
<
AppLogo
class=
{
`${prefixCls}__logo`
}
theme=
{
unref
(
getHeaderTheme
)
}
/>
)
}
{
renderHeaderLeft
()
}
{
renderHeaderContent
()
}
{
renderHeaderContent
()
}
{
renderAction
()
}
{
renderAction
()
}
<
LockAction
onRegister=
{
register
}
/>
<
LockAction
onRegister=
{
register
}
/>
...
@@ -279,9 +205,7 @@ export default defineComponent({
...
@@ -279,9 +205,7 @@ export default defineComponent({
return
()
=>
{
return
()
=>
{
return
(
return
(
<
Layout
.
Header
<
Layout
.
Header
class=
{
[
prefixCls
,
unref
(
headerClass
),
{
fixed
:
props
.
fixed
}]
}
>
class=
{
[
'layout-header'
,
'flex p-0 px-4 '
,
unref
(
headerClass
),
{
fixed
:
props
.
fixed
}]
}
>
{
()
=>
renderHeaderDefault
()
}
{
()
=>
renderHeaderDefault
()
}
</
Layout
.
Header
>
</
Layout
.
Header
>
);
);
...
...
src/layouts/default/header/LayoutMultipleHeader.less
浏览文件 @
a65ad9ed
@import (reference) '../../../design/index.less';
.multiple-tab-header {
.multiple-tab-header {
margin-left: 1px;
margin-left: 1px;
transition: width 0.2s;
transition: width 0.2s;
...
@@ -10,7 +12,7 @@
...
@@ -10,7 +12,7 @@
&.fixed {
&.fixed {
position: fixed;
position: fixed;
top: 0;
top: 0;
z-index:
100
;
z-index:
@multiple-tab-fixed-z-index
;
width: 100%;
width: 100%;
}
}
}
}
src/layouts/default/header/LayoutMultipleHeader.tsx
浏览文件 @
a65ad9ed
...
@@ -2,7 +2,7 @@ import './LayoutMultipleHeader.less';
...
@@ -2,7 +2,7 @@ import './LayoutMultipleHeader.less';
import
{
defineComponent
,
unref
,
computed
,
ref
,
watch
,
nextTick
,
CSSProperties
}
from
'vue'
;
import
{
defineComponent
,
unref
,
computed
,
ref
,
watch
,
nextTick
,
CSSProperties
}
from
'vue'
;
import
LayoutHeader
from
'./
LayoutHeader
'
;
import
LayoutHeader
from
'./
index.vue
'
;
import
MultipleTabs
from
'../tabs/index.vue'
;
import
MultipleTabs
from
'../tabs/index.vue'
;
import
{
useHeaderSetting
}
from
'/@/hooks/setting/useHeaderSetting'
;
import
{
useHeaderSetting
}
from
'/@/hooks/setting/useHeaderSetting'
;
...
@@ -10,6 +10,7 @@ import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
...
@@ -10,6 +10,7 @@ import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
import
{
useFullContent
}
from
'/@/hooks/web/useFullContent'
;
import
{
useFullContent
}
from
'/@/hooks/web/useFullContent'
;
import
{
useMultipleTabSetting
}
from
'/@/hooks/setting/useMultipleTabSetting'
;
import
{
useMultipleTabSetting
}
from
'/@/hooks/setting/useMultipleTabSetting'
;
import
{
useLayoutContext
}
from
'../useLayoutContext'
;
import
{
useLayoutContext
}
from
'../useLayoutContext'
;
import
{
useAppInject
}
from
'/@/hooks/web/useAppInject'
;
export
default
defineComponent
({
export
default
defineComponent
({
name
:
'LayoutMultipleHeader'
,
name
:
'LayoutMultipleHeader'
,
...
@@ -21,8 +22,8 @@ export default defineComponent({
...
@@ -21,8 +22,8 @@ export default defineComponent({
const
injectValue
=
useLayoutContext
();
const
injectValue
=
useLayoutContext
();
const
{
getCalcContentWidth
}
=
useMenuSetting
();
const
{
getCalcContentWidth
,
getSplit
}
=
useMenuSetting
();
const
{
getIsMobile
}
=
useAppInject
();
const
{
const
{
getFixed
,
getFixed
,
getShowInsetHeaderRef
,
getShowInsetHeaderRef
,
...
@@ -36,7 +37,7 @@ export default defineComponent({
...
@@ -36,7 +37,7 @@ export default defineComponent({
const
{
getShowMultipleTab
}
=
useMultipleTabSetting
();
const
{
getShowMultipleTab
}
=
useMultipleTabSetting
();
const
showTabsRef
=
computed
(()
=>
{
const
getShowTabs
=
computed
(()
=>
{
return
unref
(
getShowMultipleTab
)
&&
!
unref
(
getFullContent
);
return
unref
(
getShowMultipleTab
)
&&
!
unref
(
getFullContent
);
});
});
...
@@ -56,7 +57,7 @@ export default defineComponent({
...
@@ -56,7 +57,7 @@ export default defineComponent({
():
CSSProperties
=>
{
():
CSSProperties
=>
{
const
style
:
CSSProperties
=
{};
const
style
:
CSSProperties
=
{};
if
(
unref
(
getFixed
))
{
if
(
unref
(
getFixed
))
{
style
.
width
=
unref
(
injectValue
.
i
sMobile
)
?
'100%'
:
unref
(
getCalcContentWidth
);
style
.
width
=
unref
(
getI
sMobile
)
?
'100%'
:
unref
(
getCalcContentWidth
);
}
}
if
(
unref
(
getShowFullHeaderRef
))
{
if
(
unref
(
getShowFullHeaderRef
))
{
style
.
top
=
`
${
unref
(
fullHeaderHeightRef
)}
px`
;
style
.
top
=
`
${
unref
(
fullHeaderHeightRef
)}
px`
;
...
@@ -84,7 +85,7 @@ export default defineComponent({
...
@@ -84,7 +85,7 @@ export default defineComponent({
const
fullHeaderEl
=
unref
(
injectValue
.
fullHeader
)?.
$el
;
const
fullHeaderEl
=
unref
(
injectValue
.
fullHeader
)?.
$el
;
let
height
=
0
;
let
height
=
0
;
if
(
headerEl
&&
!
unref
(
getShowFullHeaderRef
))
{
if
(
headerEl
&&
!
unref
(
getShowFullHeaderRef
)
&&
!
unref
(
getSplit
)
)
{
height
+=
headerEl
.
offsetHeight
;
height
+=
headerEl
.
offsetHeight
;
}
}
...
@@ -97,6 +98,7 @@ export default defineComponent({
...
@@ -97,6 +98,7 @@ export default defineComponent({
height
+=
fullHeaderHeight
;
height
+=
fullHeaderHeight
;
fullHeaderHeightRef
.
value
=
fullHeaderHeight
;
fullHeaderHeightRef
.
value
=
fullHeaderHeight
;
}
}
placeholderHeightRef
.
value
=
height
;
placeholderHeightRef
.
value
=
height
;
});
});
},
},
...
@@ -114,7 +116,7 @@ export default defineComponent({
...
@@ -114,7 +116,7 @@ export default defineComponent({
class=
{
[
'multiple-tab-header'
,
unref
(
getHeaderTheme
),
{
fixed
:
unref
(
getIsFixed
)
}]
}
class=
{
[
'multiple-tab-header'
,
unref
(
getHeaderTheme
),
{
fixed
:
unref
(
getIsFixed
)
}]
}
>
>
{
unref
(
getShowInsetHeaderRef
)
&&
<
LayoutHeader
ref=
{
headerElRef
}
/>
}
{
unref
(
getShowInsetHeaderRef
)
&&
<
LayoutHeader
ref=
{
headerElRef
}
/>
}
{
unref
(
showTabsRef
)
&&
<
MultipleTabs
ref=
{
tabElRef
}
/>
}
{
unref
(
getShowTabs
)
&&
<
MultipleTabs
ref=
{
tabElRef
}
/>
}
</
div
>
</
div
>
</>
</>
);
);
...
...
src/layouts/default/header/UserDropdown.tsx
deleted
100644 → 0
浏览文件 @
ec7efcf0
// components
import
{
Dropdown
,
Menu
}
from
'ant-design-vue'
;
import
{
defineComponent
,
computed
,
unref
}
from
'vue'
;
// res
import
headerImg
from
'/@/assets/images/header.jpg'
;
import
Icon
from
'/@/components/Icon/index'
;
import
{
userStore
}
from
'/@/store/modules/user'
;
import
{
DOC_URL
}
from
'/@/settings/siteSetting'
;
import
{
openWindow
}
from
'/@/utils'
;
import
{
useHeaderSetting
}
from
'/@/hooks/setting/useHeaderSetting'
;
import
{
FunctionalComponent
}
from
'vue'
;
import
{
useI18n
}
from
'/@/hooks/web/useI18n'
;
type
MenuEvent
=
'loginOut'
|
'doc'
;
interface
MenuItemProps
{
icon
:
string
;
text
:
string
;
key
:
MenuEvent
;
}
const
prefixCls
=
'user-dropdown'
;
const
MenuItem
:
FunctionalComponent
<
MenuItemProps
>
=
(
props
)
=>
{
const
{
key
,
icon
,
text
}
=
props
;
return
(
<
Menu
.
Item
key=
{
key
}
>
{
()
=>
(
<
span
class=
"flex items-center"
>
<
Icon
icon=
{
icon
}
class=
"mr-1"
/>
<
span
>
{
text
}
</
span
>
</
span
>
)
}
</
Menu
.
Item
>
);
};
export
default
defineComponent
({
name
:
'UserDropdown'
,
setup
()
{
const
{
t
}
=
useI18n
();
const
{
getShowDoc
}
=
useHeaderSetting
();
const
getUserInfo
=
computed
(()
=>
{
const
{
realName
=
''
,
desc
}
=
userStore
.
getUserInfoState
||
{};
return
{
realName
,
desc
};
});
// login out
function
handleLoginOut
()
{
userStore
.
confirmLoginOut
();
}
// open doc
function
openDoc
()
{
openWindow
(
DOC_URL
);
}
function
handleMenuClick
(
e
:
{
key
:
MenuEvent
})
{
switch
(
e
.
key
)
{
case
'loginOut'
:
handleLoginOut
();
break
;
case
'doc'
:
openDoc
();
break
;
}
}
function
renderSlotsDefault
()
{
const
{
realName
}
=
unref
(
getUserInfo
);
return
(
<
section
class=
{
prefixCls
}
>
<
img
class=
{
`${prefixCls}__header`
}
src=
{
headerImg
}
/>
<
section
class=
{
`${prefixCls}__info`
}
>
<
section
class=
{
`${prefixCls}__name`
}
>
{
realName
}
</
section
>
</
section
>
</
section
>
);
}
function
renderSlotOverlay
()
{
const
showDoc
=
unref
(
getShowDoc
);
return
(
<
Menu
onClick=
{
handleMenuClick
}
>
{
()
=>
(
<>
{
showDoc
&&
(
<
MenuItem
key=
"doc"
text=
{
t
(
'layout.header.dropdownItemDoc'
)
}
icon=
"gg:loadbar-doc"
/>
)
}
{
/* @ts-ignore */
}
{
showDoc
&&
<
Menu
.
Divider
/>
}
<
MenuItem
key=
"loginOut"
text=
{
t
(
'layout.header.dropdownItemLoginOut'
)
}
icon=
"carbon:power"
/>
</>
)
}
</
Menu
>
);
}
return
()
=>
{
return
(
<
Dropdown
placement=
"bottomLeft"
overlayClassName=
"app-layout-header-user-dropdown-overlay"
>
{
{
default
:
()
=>
renderSlotsDefault
(),
overlay
:
()
=>
renderSlotOverlay
(),
}
}
</
Dropdown
>
);
};
},
});
src/layouts/default/header/
Layout
Breadcrumb.vue
→
src/layouts/default/header/
components/
Breadcrumb.vue
浏览文件 @
a65ad9ed
<
template
>
<
template
>
<div
class=
"layout-breadcrumb
"
>
<div
:class=
"[prefixCls, `$
{prefixCls}--${theme}`]
">
<a-breadcrumb
:routes=
"routes"
>
<a-breadcrumb
:routes=
"routes"
>
<template
#
itemRender=
"
{ route, routes }">
<template
#
itemRender=
"
{ route, routes }">
<Icon
:icon=
"route.meta.icon"
v-if=
"
show
Icon && route.meta.icon"
/>
<Icon
:icon=
"route.meta.icon"
v-if=
"
getShowBreadCrumb
Icon && route.meta.icon"
/>
<span
v-if=
"routes.indexOf(route) === routes.length - 1"
>
<span
v-if=
"routes.indexOf(route) === routes.length - 1"
>
{{
t
(
route
.
meta
.
title
)
}}
{{
t
(
route
.
meta
.
title
)
}}
</span>
</span>
...
@@ -14,7 +14,6 @@
...
@@ -14,7 +14,6 @@
</div>
</div>
</template>
</template>
<
script
lang=
"ts"
>
<
script
lang=
"ts"
>
import
{
PropType
}
from
'vue'
;
import
{
defineComponent
,
ref
,
toRaw
,
watchEffect
}
from
'vue'
;
import
{
defineComponent
,
ref
,
toRaw
,
watchEffect
}
from
'vue'
;
import
{
useI18n
}
from
'vue-i18n'
;
import
{
useI18n
}
from
'vue-i18n'
;
...
@@ -26,18 +25,23 @@
...
@@ -26,18 +25,23 @@
import
{
HomeOutlined
}
from
'@ant-design/icons-vue'
;
import
{
HomeOutlined
}
from
'@ant-design/icons-vue'
;
import
{
PageEnum
}
from
'/@/enums/pageEnum'
;
import
{
PageEnum
}
from
'/@/enums/pageEnum'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
import
{
useRootSetting
}
from
'/@/hooks/setting/useRootSetting'
;
import
{
propTypes
}
from
'/@/utils/propTypes'
;
export
default
defineComponent
({
export
default
defineComponent
({
name
:
'LayoutBreadcrumb'
,
name
:
'LayoutBreadcrumb'
,
components
:
{
HomeOutlined
,
Icon
},
components
:
{
HomeOutlined
,
Icon
},
props
:
{
props
:
{
showIcon
:
{
theme
:
propTypes
.
oneOf
([
'dark'
,
'light'
]),
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
false
,
},
},
},
setup
()
{
setup
()
{
const
routes
=
ref
<
RouteLocationMatched
[]
>
([]);
const
routes
=
ref
<
RouteLocationMatched
[]
>
([]);
const
{
currentRoute
}
=
useRouter
();
const
{
currentRoute
}
=
useRouter
();
const
{
prefixCls
}
=
useDesign
(
'layout-breadcrumb'
);
const
{
getShowBreadCrumbIcon
}
=
useRootSetting
();
const
{
t
}
=
useI18n
();
const
{
t
}
=
useI18n
();
watchEffect
(()
=>
{
watchEffect
(()
=>
{
...
@@ -63,17 +67,71 @@
...
@@ -63,17 +67,71 @@
);
);
if
(
filterBreadcrumbList
.
length
===
breadcrumbList
.
length
)
{
if
(
filterBreadcrumbList
.
length
===
breadcrumbList
.
length
)
{
filterBreadcrumbList
.
unshift
({
filterBreadcrumbList
.
unshift
(
(
{
path
:
PageEnum
.
BASE_HOME
,
path
:
PageEnum
.
BASE_HOME
,
meta
:
{
meta
:
{
title
:
t
(
'layout.header.home'
),
title
:
t
(
'layout.header.home'
),
},
},
});
}
as
unknown
)
as
RouteLocationMatched
);
}
}
routes
.
value
=
filterBreadcrumbList
;
routes
.
value
=
filterBreadcrumbList
.
length
===
1
?
[]
:
filterBreadcrumbList
;
});
});
return
{
routes
,
t
};
return
{
routes
,
t
,
prefixCls
,
getShowBreadCrumbIcon
};
},
},
});
});
</
script
>
</
script
>
<
style
lang=
"less"
>
@import
(
reference
)
'../../../../design/index.less'
;
@prefix-cls
:
~
'@{namespace}-layout-breadcrumb'
;
.@
{
prefix-cls
}
{
display
:
flex
;
padding
:
0
8px
;
align-items
:
center
;
.ant-breadcrumb-link
{
.anticon
{
margin-right
:
4px
;
margin-bottom
:
2px
;
}
}
&
--light
{
.ant-breadcrumb-link
{
color
:
@
breadcrumb-item-normal-color
;
a
{
color
:
@
text-color-base
;
&:hover
{
color
:
@
primary-color
;
}
}
}
.ant-breadcrumb-separator
{
color
:
@
breadcrumb-item-normal-color
;
}
}
&
--dark
{
.ant-breadcrumb-link
{
color
:
rgba
(
255
,
255
,
255
,
0.6
);
a
{
color
:
rgba
(
255
,
255
,
255
,
0.8
);
&:hover
{
color
:
@
white
;
}
}
}
.ant-breadcrumb-separator
,
.anticon
{
color
:
rgba
(
255
,
255
,
255
,
0.8
);
}
}
}
</
style
>
src/layouts/default/header/components/ErrorAction.vue
0 → 100644
浏览文件 @
a65ad9ed
<
template
>
<Tooltip
:title=
"t('layout.header.tooltipErrorLog')"
placement=
"bottom"
:mouseEnterDelay=
"0.5"
@
click=
"handleToErrorList"
>
<Badge
:count=
"getCount"
:offset=
"[0, 10]"
dot
:overflowCount=
"99"
>
<BugOutlined
/>
</Badge>
</Tooltip>
</
template
>
<
script
lang=
"ts"
>
import
{
defineComponent
,
computed
}
from
'vue'
;
import
{
Tooltip
,
Badge
}
from
'ant-design-vue'
;
import
{
useI18n
}
from
'/@/hooks/web/useI18n'
;
import
{
BugOutlined
}
from
'@ant-design/icons-vue'
;
import
{
errorStore
}
from
'/@/store/modules/error'
;
import
{
PageEnum
}
from
'/@/enums/pageEnum'
;
import
{
useRouter
}
from
'vue-router'
;
export
default
defineComponent
({
name
:
'ErrorAction'
,
components
:
{
BugOutlined
,
Tooltip
,
Badge
},
setup
()
{
const
{
t
}
=
useI18n
();
const
{
push
}
=
useRouter
();
const
getCount
=
computed
(()
=>
{
return
errorStore
.
getErrorListCountState
;
});
function
handleToErrorList
()
{
push
(
PageEnum
.
ERROR_LOG_PAGE
).
then
(()
=>
{
errorStore
.
commitErrorListCountState
(
0
);
});
}
return
{
t
,
getCount
,
handleToErrorList
,
};
},
});
</
script
>
src/layouts/default/header/components/FullScreen.vue
0 → 100644
浏览文件 @
a65ad9ed
<
template
>
<Tooltip
:title=
"getTitle"
placement=
"bottom"
:mouseEnterDelay=
"0.5"
>
<span
@
click=
"toggleFullscreen"
>
<FullscreenOutlined
v-if=
"!isFullscreen"
/>
<FullscreenExitOutlined
v-else
/>
</span>
</Tooltip>
</
template
>
<
script
lang=
"ts"
>
import
{
defineComponent
,
computed
,
unref
}
from
'vue'
;
import
{
Tooltip
}
from
'ant-design-vue'
;
import
{
useI18n
}
from
'/@/hooks/web/useI18n'
;
import
{
useFullscreen
}
from
'/@/hooks/web/useFullScreen'
;
import
{
FullscreenExitOutlined
,
FullscreenOutlined
}
from
'@ant-design/icons-vue'
;
export
default
defineComponent
({
name
:
'FullScreen'
,
components
:
{
FullscreenExitOutlined
,
FullscreenOutlined
,
Tooltip
},
setup
()
{
const
{
t
}
=
useI18n
();
const
{
toggleFullscreen
,
isFullscreenRef
}
=
useFullscreen
();
const
getTitle
=
computed
(()
=>
{
return
unref
(
isFullscreenRef
)
?
t
(
'layout.header.tooltipExitFull'
)
:
t
(
'layout.header.tooltipEntryFull'
);
});
return
{
getTitle
,
isFullscreen
:
isFullscreenRef
,
toggleFullscreen
,
};
},
});
</
script
>
src/layouts/default/header/components/index.ts
0 → 100644
浏览文件 @
a65ad9ed
import
{
createAsyncComponent
}
from
'/@/utils/factory/createAsyncComponent'
;
export
const
UserDropDown
=
createAsyncComponent
(()
=>
import
(
'./user-dropdown/index.vue'
),
{
loading
:
true
,
});
export
const
LayoutBreadcrumb
=
createAsyncComponent
(()
=>
import
(
'./Breadcrumb.vue'
));
export
const
FullScreen
=
createAsyncComponent
(()
=>
import
(
'./FullScreen.vue'
));
export
const
Notify
=
createAsyncComponent
(()
=>
import
(
'./notify/index.vue'
));
export
const
LockItem
=
createAsyncComponent
(()
=>
import
(
'./lock/index.vue'
));
export
const
ErrorAction
=
createAsyncComponent
(()
=>
import
(
'./ErrorAction.vue'
));
src/layouts/default/header/
actions
/LockAction.less
→
src/layouts/default/header/
components/lock
/LockAction.less
浏览文件 @
a65ad9ed
File moved
src/layouts/default/header/
actions
/LockAction.tsx
→
src/layouts/default/header/
components/lock
/LockAction.tsx
浏览文件 @
a65ad9ed
File moved
src/layouts/default/header/components/lock/LockModal.vue
0 → 100644
浏览文件 @
a65ad9ed
<
template
>
<BasicModal
:footer=
"null"
:title=
"t('layout.header.lockScreen')"
v-bind=
"$attrs"
:class=
"prefixCls"
@
register=
"register"
>
<div
:class=
"`$
{prefixCls}__entry`">
<div
:class=
"`$
{prefixCls}__header`">
<img
src=
"/@/assets/images/header.jpg"
:class=
"`$
{prefixCls}__header-img`" />
<p
:class=
"`$
{prefixCls}__header-name`">
{{
getRealName
}}
</p>
</div>
<BasicForm
@
register=
"registerForm"
layout=
"vertical"
/>
<div
:class=
"`$
{prefixCls}__footer`">
<a-button
type=
"primary"
block
class=
"mt-2"
@
click=
"handleLock"
>
{{
t
(
'layout.header.lockScreenBtn'
)
}}
</a-button>
</div>
</div>
</BasicModal>
</
template
>
<
script
lang=
"ts"
>
import
{
defineComponent
,
computed
}
from
'vue'
;
import
{
useI18n
}
from
'/@/hooks/web/useI18n'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
import
{
BasicModal
,
useModalInner
}
from
'/@/components/Modal/index'
;
import
{
BasicForm
,
useForm
}
from
'/@/components/Form/index'
;
import
{
userStore
}
from
'/@/store/modules/user'
;
import
{
lockStore
}
from
'/@/store/modules/lock'
;
export
default
defineComponent
({
name
:
'LockModal'
,
components
:
{
BasicModal
,
BasicForm
},
setup
()
{
const
{
t
}
=
useI18n
();
const
{
prefixCls
}
=
useDesign
(
'header-lock-modal'
);
const
getRealName
=
computed
(()
=>
{
return
userStore
.
getUserInfoState
?.
realName
;
});
const
[
register
,
{
closeModal
}]
=
useModalInner
();
const
[
registerForm
,
{
validateFields
,
resetFields
}]
=
useForm
({
showActionButtonGroup
:
false
,
schemas
:
[
{
field
:
'password'
,
label
:
t
(
'layout.header.lockScreenPassword'
),
component
:
'InputPassword'
,
required
:
true
,
},
],
});
async
function
handleLock
()
{
const
values
=
(
await
validateFields
())
as
any
;
const
password
:
string
|
undefined
=
values
.
password
;
closeModal
();
lockStore
.
commitLockInfoState
({
isLock
:
true
,
pwd
:
password
,
});
await
resetFields
();
}
return
{
t
,
prefixCls
,
getRealName
,
register
,
registerForm
,
handleLock
,
};
},
});
</
script
>
<
style
lang=
"less"
>
@import
(
reference
)
'../../../../../design/index.less'
;
@prefix-cls
:
~
'@{namespace}-header-lock-modal'
;
.@
{
prefix-cls
}
{
&__entry
{
position
:
relative
;
height
:
240px
;
padding
:
130px
30px
60px
30px
;
background
:
#fff
;
border-radius
:
10px
;
}
&
__header
{
position
:
absolute
;
top
:
0
;
left
:
calc
(
50%
-
45px
);
width
:
auto
;
text-align
:
center
;
&-img
{
width
:
70px
;
border-radius
:
50%
;
}
&
-name
{
margin-top
:
5px
;
}
}
&
__footer
{
text-align
:
center
;
}
}
</
style
>
src/layouts/default/header/components/lock/index.vue
0 → 100644
浏览文件 @
a65ad9ed
<
template
>
<span
@
click=
"handleLock"
>
<Tooltip
:title=
"t('layout.header.tooltipLock')"
placement=
"bottom"
:mouseEnterDelay=
"0.5"
>
<LockOutlined
/>
</Tooltip>
<LockAction
@
register=
"register"
/>
</span>
</
template
>
<
script
lang=
"ts"
>
import
{
defineComponent
}
from
'vue'
;
import
{
Tooltip
}
from
'ant-design-vue'
;
import
{
useI18n
}
from
'/@/hooks/web/useI18n'
;
import
{
LockOutlined
}
from
'@ant-design/icons-vue'
;
import
{
useModal
}
from
'/@/components/Modal'
;
import
{
createAsyncComponent
}
from
'/@/utils/factory/createAsyncComponent'
;
export
default
defineComponent
({
name
:
'FullScreen'
,
components
:
{
LockOutlined
,
Tooltip
,
LockAction
:
createAsyncComponent
(()
=>
import
(
'./LockModal.vue'
)),
},
setup
()
{
const
{
t
}
=
useI18n
();
const
[
register
,
{
openModal
}]
=
useModal
();
function
handleLock
()
{
openModal
(
true
);
}
return
{
t
,
register
,
handleLock
,
};
},
});
</
script
>
src/layouts/default/header/
notice
/NoticeList.vue
→
src/layouts/default/header/
components/notify
/NoticeList.vue
浏览文件 @
a65ad9ed
<
template
>
<
template
>
<a-list
class=
"list
"
>
<a-list
:class=
"prefixCls
"
>
<template
v-for=
"item in list"
:key=
"item.id"
>
<template
v-for=
"item in list"
:key=
"item.id"
>
<a-list-item
class=
"list-item"
>
<a-list-item
class=
"list-item"
>
<a-list-item-meta>
<a-list-item-meta>
...
@@ -33,6 +33,7 @@
...
@@ -33,6 +33,7 @@
<
script
lang=
"ts"
>
<
script
lang=
"ts"
>
import
{
defineComponent
,
PropType
}
from
'vue'
;
import
{
defineComponent
,
PropType
}
from
'vue'
;
import
{
ListItem
}
from
'./data'
;
import
{
ListItem
}
from
'./data'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
export
default
defineComponent
({
export
default
defineComponent
({
props
:
{
props
:
{
...
@@ -41,10 +42,17 @@
...
@@ -41,10 +42,17 @@
default
:
()
=>
[],
default
:
()
=>
[],
},
},
},
},
setup
()
{
const
{
prefixCls
}
=
useDesign
(
'header-notify-list'
);
return
{
prefixCls
};
},
});
});
</
script
>
</
script
>
<
style
lang=
"less"
scoped
>
<
style
lang=
"less"
scoped
>
.list
{
@import
(
reference
)
'../../../../../design/index.less'
;
@prefix-cls
:
~
'@{namespace}-header-notify-list'
;
.@
{
prefix-cls
}
{
&::-webkit-scrollbar
{
&::-webkit-scrollbar
{
display
:
none
;
display
:
none
;
}
}
...
...
src/layouts/default/header/
notice
/data.ts
→
src/layouts/default/header/
components/notify
/data.ts
浏览文件 @
a65ad9ed
File moved
src/layouts/default/header/
notice/NoticeActionItem
.vue
→
src/layouts/default/header/
components/notify/index
.vue
浏览文件 @
a65ad9ed
<
template
>
<
template
>
<div
class=
"layout-header__action-item notify-action
"
>
<div
:class=
"prefixCls
"
>
<Popover
title=
""
trigger=
"click"
overlayClassName=
"layout-header__notify-action
"
>
<Popover
title=
""
trigger=
"click"
:overlayClassName=
"`$
{prefixCls}__overlay`
">
<Badge
:count=
"count"
dot
:numberStyle=
"numberStyle"
>
<Badge
:count=
"count"
dot
:numberStyle=
"numberStyle"
>
<BellOutlined
class=
"layout-header__action-icon"
/>
<BellOutlined
/>
</Badge>
</Badge>
<template
#
content
>
<template
#
content
>
<Tabs>
<Tabs>
...
@@ -26,10 +26,13 @@
...
@@ -26,10 +26,13 @@
import
{
BellOutlined
}
from
'@ant-design/icons-vue'
;
import
{
BellOutlined
}
from
'@ant-design/icons-vue'
;
import
{
tabListData
}
from
'./data'
;
import
{
tabListData
}
from
'./data'
;
import
NoticeList
from
'./NoticeList.vue'
;
import
NoticeList
from
'./NoticeList.vue'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
export
default
defineComponent
({
export
default
defineComponent
({
components
:
{
Popover
,
BellOutlined
,
Tabs
,
TabPane
:
Tabs
.
TabPane
,
Badge
,
NoticeList
},
components
:
{
Popover
,
BellOutlined
,
Tabs
,
TabPane
:
Tabs
.
TabPane
,
Badge
,
NoticeList
},
setup
()
{
setup
()
{
const
{
prefixCls
}
=
useDesign
(
'header-notify'
);
let
count
=
0
;
let
count
=
0
;
for
(
let
i
=
0
;
i
<
tabListData
.
length
;
i
++
)
{
for
(
let
i
=
0
;
i
<
tabListData
.
length
;
i
++
)
{
...
@@ -37,6 +40,7 @@
...
@@ -37,6 +40,7 @@
}
}
return
{
return
{
prefixCls
,
tabListData
,
tabListData
,
count
,
count
,
numberStyle
:
{},
numberStyle
:
{},
...
@@ -45,13 +49,16 @@
...
@@ -45,13 +49,16 @@
});
});
</
script
>
</
script
>
<
style
lang=
"less"
>
<
style
lang=
"less"
>
.layout-header__notify-action
{
@import
(
reference
)
'../../../../../design/index.less'
;
max-width
:
360px
;
@prefix-cls
:
~
'@{namespace}-header-notify'
;
}
.
notify-action
{
.
@
{
prefix-cls
}
{
padding-top
:
2px
;
padding-top
:
2px
;
&__overlay
{
max-width
:
360px
;
}
.ant-tabs-content
{
.ant-tabs-content
{
width
:
300px
;
width
:
300px
;
}
}
...
...
src/layouts/default/header/components/user-dropdown/DropMenuItem.vue
0 → 100644
浏览文件 @
a65ad9ed
<
template
>
<MenuItem
:key=
"key"
>
<span
class=
"flex items-center"
>
<Icon
:icon=
"icon"
class=
"mr-1"
/>
<span>
{{
text
}}
</span>
</span>
</MenuItem>
</
template
>
<
script
lang=
"ts"
>
// components
import
{
Menu
}
from
'ant-design-vue'
;
import
{
defineComponent
}
from
'vue'
;
import
Icon
from
'/@/components/Icon/index'
;
import
{
propTypes
}
from
'/@/utils/propTypes'
;
export
default
defineComponent
({
name
:
'DropdownMenuItem'
,
components
:
{
MenuItem
:
Menu
.
Item
,
Icon
},
props
:
{
key
:
propTypes
.
string
,
text
:
propTypes
.
string
,
icon
:
propTypes
.
string
,
},
});
</
script
>
src/layouts/default/header/components/user-dropdown/index.vue
0 → 100644
浏览文件 @
a65ad9ed
<
template
>
<Dropdown
placement=
"bottomLeft"
:overlayClassName=
"`$
{prefixCls}-dropdown-overlay`">
<span
:class=
"[prefixCls, `$
{prefixCls}--${theme}`]">
<img
:class=
"`$
{prefixCls}__header`" src="/@/assets/images/header.jpg" />
<span
:class=
"`$
{prefixCls}__info`">
<span
:class=
"`$
{prefixCls}__name anticon`">
{{
getUserInfo
.
realName
}}
</span>
</span>
</span>
<template
#
overlay
>
<Menu
@
click=
"handleMenuClick"
>
<MenuItem
key=
"doc"
:text=
"t('layout.header.dropdownItemDoc')"
icon=
"gg:loadbar-doc"
/>
<MenuDivider
v-if=
"getShowDoc"
/>
<MenuItem
key=
"loginOut"
:text=
"t('layout.header.dropdownItemLoginOut')"
icon=
"carbon:power"
/>
</Menu>
</
template
>
</Dropdown>
</template>
<
script
lang=
"ts"
>
// components
import
{
Dropdown
,
Menu
}
from
'ant-design-vue'
;
import
{
defineComponent
,
computed
}
from
'vue'
;
// res
import
Icon
from
'/@/components/Icon/index'
;
import
{
userStore
}
from
'/@/store/modules/user'
;
import
{
DOC_URL
}
from
'/@/settings/siteSetting'
;
import
{
openWindow
}
from
'/@/utils'
;
import
{
useHeaderSetting
}
from
'/@/hooks/setting/useHeaderSetting'
;
import
{
useI18n
}
from
'/@/hooks/web/useI18n'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
import
{
createAsyncComponent
}
from
'/@/utils/factory/createAsyncComponent'
;
import
{
propTypes
}
from
'/@/utils/propTypes'
;
type
MenuEvent
=
'loginOut'
|
'doc'
;
export
default
defineComponent
({
name
:
'UserDropdown'
,
components
:
{
Dropdown
,
Menu
,
MenuItem
:
createAsyncComponent
(()
=>
import
(
'./DropMenuItem.vue'
)),
MenuDivider
:
Menu
.
Divider
,
Icon
,
},
props
:
{
theme
:
propTypes
.
oneOf
([
'dark'
,
'light'
]),
},
setup
()
{
const
{
prefixCls
}
=
useDesign
(
'header-user-dropdown'
);
const
{
t
}
=
useI18n
();
const
{
getShowDoc
}
=
useHeaderSetting
();
const
getUserInfo
=
computed
(()
=>
{
const
{
realName
=
''
,
desc
}
=
userStore
.
getUserInfoState
||
{};
return
{
realName
,
desc
};
});
// login out
function
handleLoginOut
()
{
userStore
.
confirmLoginOut
();
}
// open doc
function
openDoc
()
{
openWindow
(
DOC_URL
);
}
function
handleMenuClick
(
e
:
{
key
:
MenuEvent
})
{
switch
(
e
.
key
)
{
case
'loginOut'
:
handleLoginOut
();
break
;
case
'doc'
:
openDoc
();
break
;
}
}
return
{
prefixCls
,
t
,
getUserInfo
,
handleMenuClick
,
getShowDoc
,
};
},
});
</
script
>
<
style
lang=
"less"
>
@import
(
reference
)
'../../../../../design/index.less'
;
@prefix-cls
:
~
'@{namespace}-header-user-dropdown'
;
.@
{
prefix-cls
}
{
display
:
flex
;
height
:
@
header-height
;
min-width
:
100px
;
padding
:
0
0
0
10px
;
padding-right
:
10px
;
overflow
:
hidden
;
font-size
:
12px
;
cursor
:
pointer
;
align-items
:
center
;
&:hover
{
background
:
@
header-light-bg-hover-color
;
}
img
{
width
:
26px
;
height
:
26px
;
margin-right
:
12px
;
}
&
__header
{
border-radius
:
50%
;
}
&
__name
{
font-size
:
14px
;
}
&
--dark
{
&:hover
{
background
:
@
header-dark-bg-hover-color
;
}
}
&
--light
{
.@{prefix-cls
}
__name
{
color
:
@
text-color-base
;
}
.@
{
prefix-cls
}
__desc
{
color
:
@
header-light-desc-color
;
}
}
&
-dropdown-overlay
{
.ant-dropdown-menu-item
{
min-width
:
160px
;
}
}
}
</
style
>
src/layouts/default/header/index.less
浏览文件 @
a65ad9ed
@import (reference) '../../../design/index.less';
@import (reference) '../../../design/index.less';
@header-trigger-prefix-cls: ~'@{namespace}-layout-header-trigger';
@header-trigger-prefix-cls: ~'@{namespace}-layout-header-trigger';
@header-prefix-cls: ~'@{namespace}-layout-header';
@locale-prefix-cls: ~'@{namespace}-app-locale-picker';
.
layout-header
{
.
@{header-prefix-cls}
{
display: flex;
display: flex;
height: @header-height;
height: @header-height;
padding: 0
20px 0 0
;
padding: 0;
margin-left: -1px;
margin-left: -1px;
line-height: @header-height;
line-height: @header-height;
color: @white;
color: @white;
...
@@ -12,15 +14,28 @@
...
@@ -12,15 +14,28 @@
align-items: center;
align-items: center;
justify-content: space-between;
justify-content: space-between;
&
.
fixed {
&
--
fixed {
position: fixed;
position: fixed;
top: 0;
top: 0;
left: 0;
left: 0;
z-index:
1000
;
z-index:
@layout-header-fixed-z-index
;
width: 100%;
width: 100%;
}
}
&__left {
&-logo {
height: @header-height;
min-width: 192px;
padding: 0 10px;
font-size: 14px;
img {
width: @logo-width;
height: @logo-width;
margin-right: 2px;
}
}
&-left {
display: flex;
display: flex;
height: 100%;
height: 100%;
align-items: center;
align-items: center;
...
@@ -33,7 +48,7 @@
...
@@ -33,7 +48,7 @@
align-items: center;
align-items: center;
.anticon {
.anticon {
font-size: 1
7
px;
font-size: 1
6
px;
}
}
&.light {
&.light {
...
@@ -52,82 +67,65 @@
...
@@ -52,82 +67,65 @@
}
}
}
}
}
}
.layout-breadcrumb {
display: flex;
padding: 0 8px;
align-items: center;
.ant-breadcrumb-link {
.anticon {
margin-right: 4px;
margin-bottom: 2px;
}
}
}
}
}
&__content {
&-menu {
display: flex;
height: 100%;
height: 100%;
flex-grow: 1;
min-width: 0;
flex: 1;
align-items: center;
align-items: center;
}
}
&__header--light {
&-action {
background: @white;
display: flex;
border-bottom: 1px solid @header-light-bottom-border-color;
min-width: 200px;
padding-right: 12px;
align-items: center;
.layout-header__menu {
&__item {
height: calc(@header-height - 1px);
display: flex;
height: @header-height;
padding: 0 2px;
font-size: 1.2em;
cursor: pointer;
align-items: center;
.ant-
menu-submenu
{
.ant-
badge
{
height: @header-height;
height: @header-height;
line-height: @header-height;
line-height: @header-height;
}
}
}
.layout-breadcrumb {
.ant-breadcrumb-link {
color: @breadcrumb-item-normal-color;
a {
.ant-badge-dot {
color: @text-color-base;
top: 10px;
right: 2px;
&:hover {
color: @primary-color;
}
}
}
}
}
.ant-breadcrumb-separator {
span[role='img'] {
color: @breadcrumb-item-normal-color;
padding: 0 8px;
}
}
}
}
.layout-header__logo
{
&--light
{
height: @header-height
;
background: @white
;
color: @text-color-base
;
border-bottom: 1px solid @header-light-bottom-border-color
;
img {
.@{header-prefix-cls}-logo {
width: @logo-width;
color: @text-color-base;
height: @logo-width;
margin-right: 6px;
}
&:hover {
&:hover {
background: @header-light-bg-hover-color;
background: @header-light-bg-hover-color;
}
}
}
}
.
layout-header__
action {
.
@{header-prefix-cls}-
action {
&
-
item {
&
__
item {
&:hover {
&:hover {
background: @header-light-bg-hover-color;
background: @header-light-bg-hover-color;
}
}
&.locale
{
.@{locale-prefix-cls}
{
padding: 0
10
px;
padding: 0
6
px;
color: rgba(0, 0, 0, 0.65);
color: rgba(0, 0, 0, 0.65);
}
}
}
}
...
@@ -137,134 +135,23 @@
...
@@ -137,134 +135,23 @@
color: @text-color-base;
color: @text-color-base;
}
}
}
}
.layout-header__user-dropdown {
&:hover {
background: @header-light-bg-hover-color;
}
}
.user-dropdown {
&__name {
color: @text-color-base;
}
&__desc {
color: @header-light-desc-color;
}
}
}
}
&
__header
--dark {
&--dark {
background: @header-dark-bg-color;
background: @header-dark-bg-color;
.layout-header__action {
.@{header-prefix-cls}-logo {
&-item {
&:hover {
background: @header-dark-bg-hover-color;
}
}
}
.layout-header__logo {
height: @header-height;
img {
width: @logo-width;
height: @logo-width;
margin-right: 10px;
}
&:hover {
background: @header-dark-bg-hover-color;
}
}
.layout-header__user-dropdown {
&:hover {
&:hover {
background: @header-dark-bg-hover-color;
background: @header-dark-bg-hover-color;
}
}
}
}
.layout-breadcrumb {
.@{header-prefix-cls}-action {
.ant-breadcrumb-link {
&__item {
color: rgba(255, 255, 255, 0.6);
&:hover {
background: @header-dark-bg-hover-color;
a {
color: rgba(255, 255, 255, 0.8);
&:hover {
color: @white;
}
}
}
}
}
.ant-breadcrumb-separator,
.anticon {
color: rgba(255, 255, 255, 0.8);
}
}
}
&__logo {
padding: 0 10px;
}
&__bread {
display: none;
flex: 1;
}
&__action {
display: flex;
align-items: center;
&-item {
display: flex;
height: @header-height;
padding: 0 2px;
font-size: 1.2em;
cursor: pointer;
align-items: center;
}
&-icon {
padding: 0 8px;
}
}
&__menu {
margin-left: 4px;
overflow: hidden;
align-items: center;
}
&__user-dropdown {
height: @header-height;
padding: 0 0 0 10px;
}
.user-dropdown {
display: flex;
padding-right: 10px;
font-size: 12px;
cursor: pointer;
align-items: center;
img {
width: 26px;
height: 26px;
margin-right: 12px;
}
&__header {
border-radius: 50%;
}
}
}
}
}
}
.app-layout-header-user-dropdown-overlay {
.ant-dropdown-menu-item {
min-width: 160px;
}
}
src/layouts/default/header/index.vue
0 → 100644
浏览文件 @
a65ad9ed
<
template
>
<Header
:class=
"getHeaderClass"
>
<!-- left start -->
<div
:class=
"`$
{prefixCls}-left`">
<!-- logo -->
<AppLogo
v-if=
"getShowHeaderLogo"
:class=
"`$
{prefixCls}-logo`" :theme="getHeaderTheme" />
<LayoutTrigger
v-if=
"getShowContent && getShowHeaderTrigger"
:theme=
"getHeaderTheme"
:sider=
"false"
/>
<LayoutBreadcrumb
v-if=
"getShowContent && getShowBread && !getIsMobile"
:theme=
"getHeaderTheme"
/>
</div>
<!-- left end -->
<!-- menu start -->
<div
:class=
"`$
{prefixCls}-menu`" v-if="getShowTopMenu
&&
!getIsMobile">
<LayoutMenu
:isHorizontal=
"true"
:theme=
"getHeaderTheme"
:splitType=
"getSplitType"
:menuMode=
"getMenuMode"
/>
</div>
<!-- menu-end -->
<!-- action -->
<div
:class=
"`$
{prefixCls}-action`">
<AppSearch
v-if=
"!getIsMobile"
:class=
"`$
{prefixCls}-action__item`" />
<ErrorAction
v-if=
"getUseErrorHandle && !getIsMobile"
:class=
"`$
{prefixCls}-action__item`" />
<LockItem
v-if=
"getUseLockPage && !getIsMobile"
:class=
"`$
{prefixCls}-action__item`" />
<Notify
v-if=
"getShowNotice && !getIsMobile"
:class=
"`$
{prefixCls}-action__item`" />
<FullScreen
v-if=
"getShowFullScreen && !getIsMobile"
:class=
"`$
{prefixCls}-action__item`" />
<UserDropDown
:theme=
"getHeaderTheme"
/>
<AppLocalePicker
v-if=
"getShowLocale"
:reload=
"true"
:showText=
"false"
:class=
"`$
{prefixCls}-action__item`"
/>
</div>
</Header>
</
template
>
<
script
lang=
"ts"
>
import
{
defineComponent
,
unref
,
computed
}
from
'vue'
;
import
{
propTypes
}
from
'/@/utils/propTypes'
;
import
{
Layout
}
from
'ant-design-vue'
;
import
{
AppLogo
}
from
'/@/components/Application'
;
import
LayoutMenu
from
'../menu'
;
import
LayoutTrigger
from
'../trigger/index.vue'
;
import
{
AppSearch
}
from
'/@/components/Application'
;
import
{
useHeaderSetting
}
from
'/@/hooks/setting/useHeaderSetting'
;
import
{
useMenuSetting
}
from
'/@/hooks/setting/useMenuSetting'
;
import
{
useRootSetting
}
from
'/@/hooks/setting/useRootSetting'
;
import
{
useLocaleSetting
}
from
'/@/hooks/setting/useLocaleSetting'
;
import
{
MenuModeEnum
,
MenuSplitTyeEnum
}
from
'/@/enums/menuEnum'
;
import
{
AppLocalePicker
}
from
'/@/components/Application'
;
import
{
UserDropDown
,
LayoutBreadcrumb
,
FullScreen
,
Notify
,
LockItem
,
ErrorAction
,
}
from
'./components'
;
import
{
useAppInject
}
from
'/@/hooks/web/useAppInject'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
export
default
defineComponent
({
name
:
'LayoutHeader'
,
components
:
{
Header
:
Layout
.
Header
,
AppLogo
,
LayoutTrigger
,
LayoutBreadcrumb
,
LayoutMenu
,
UserDropDown
,
AppLocalePicker
,
FullScreen
,
Notify
,
LockItem
,
AppSearch
,
ErrorAction
,
},
props
:
{
fixed
:
propTypes
.
bool
,
},
setup
(
props
)
{
const
{
prefixCls
}
=
useDesign
(
'layout-header'
);
const
{
getShowTopMenu
,
getShowHeaderTrigger
,
getSplit
}
=
useMenuSetting
();
const
{
getShowLocale
}
=
useLocaleSetting
();
const
{
getUseErrorHandle
}
=
useRootSetting
();
const
{
getHeaderTheme
,
getUseLockPage
,
getShowFullScreen
,
getShowNotice
,
getShowContent
,
getShowBread
,
getShowHeaderLogo
,
}
=
useHeaderSetting
();
const
{
getIsMobile
}
=
useAppInject
();
const
getHeaderClass
=
computed
(()
=>
{
const
theme
=
unref
(
getHeaderTheme
);
return
[
prefixCls
,
{
[
`
${
prefixCls
}
--fixed`
]:
props
.
fixed
,
[
`
${
prefixCls
}
--
${
theme
}
`
]:
theme
},
];
});
const
getSplitType
=
computed
(()
=>
{
return
unref
(
getSplit
)
?
MenuSplitTyeEnum
.
TOP
:
MenuSplitTyeEnum
.
NONE
;
});
const
getMenuMode
=
computed
(()
=>
{
return
unref
(
getSplit
)
?
MenuModeEnum
.
HORIZONTAL
:
null
;
});
return
{
prefixCls
,
getHeaderClass
,
getShowHeaderLogo
,
getHeaderTheme
,
getShowHeaderTrigger
,
getIsMobile
,
getShowBread
,
getShowContent
,
getSplitType
,
getMenuMode
,
getShowTopMenu
,
getShowLocale
,
getShowFullScreen
,
getShowNotice
,
getUseLockPage
,
getUseErrorHandle
,
};
},
});
</
script
>
<
style
lang=
"less"
>
@import
'./index.less'
;
</
style
>
src/layouts/default/index.vue
浏览文件 @
a65ad9ed
...
@@ -18,7 +18,7 @@
...
@@ -18,7 +18,7 @@
import
{
Layout
}
from
'ant-design-vue'
;
import
{
Layout
}
from
'ant-design-vue'
;
import
{
createAsyncComponent
}
from
'/@/utils/factory/createAsyncComponent'
;
import
{
createAsyncComponent
}
from
'/@/utils/factory/createAsyncComponent'
;
import
LayoutHeader
from
'./header/
LayoutHeader
'
;
import
LayoutHeader
from
'./header/
index.vue
'
;
import
LayoutContent
from
'./content/index.vue'
;
import
LayoutContent
from
'./content/index.vue'
;
import
LayoutSideBar
from
'./sider'
;
import
LayoutSideBar
from
'./sider'
;
import
LayoutMultipleHeader
from
'./header/LayoutMultipleHeader'
;
import
LayoutMultipleHeader
from
'./header/LayoutMultipleHeader'
;
...
@@ -29,8 +29,6 @@
...
@@ -29,8 +29,6 @@
import
{
createLayoutContext
}
from
'./useLayoutContext'
;
import
{
createLayoutContext
}
from
'./useLayoutContext'
;
import
{
registerGlobComp
}
from
'/@/components/registerGlobComp'
;
import
{
registerGlobComp
}
from
'/@/components/registerGlobComp'
;
import
{
createBreakpointListen
}
from
'/@/hooks/event/useBreakpoint'
;
import
{
isMobile
}
from
'/@/utils/is'
;
export
default
defineComponent
({
export
default
defineComponent
({
name
:
'DefaultLayout'
,
name
:
'DefaultLayout'
,
...
@@ -44,22 +42,17 @@
...
@@ -44,22 +42,17 @@
Layout
,
Layout
,
},
},
setup
()
{
setup
()
{
const
headerRef
=
ref
<
ComponentRef
>
(
null
);
const
isMobileRef
=
ref
(
false
);
const
{
prefixCls
}
=
useDesign
(
'default-layout'
);
createLayoutContext
({
fullHeader
:
headerRef
,
isMobile
:
isMobileRef
});
createBreakpointListen
(()
=>
{
isMobileRef
.
value
=
isMobile
();
});
// ! Only register global components here
// ! Only register global components here
// ! Can reduce the size of the first screen code
// ! Can reduce the size of the first screen code
// default layout It is loaded after login. So it won’t be packaged to the first screen
// default layout It is loaded after login. So it won’t be packaged to the first screen
registerGlobComp
();
registerGlobComp
();
const
headerRef
=
ref
<
ComponentRef
>
(
null
);
const
{
prefixCls
}
=
useDesign
(
'default-layout'
);
createLayoutContext
({
fullHeader
:
headerRef
});
const
{
getShowFullHeaderRef
}
=
useHeaderSetting
();
const
{
getShowFullHeaderRef
}
=
useHeaderSetting
();
const
{
getShowSidebar
}
=
useMenuSetting
();
const
{
getShowSidebar
}
=
useMenuSetting
();
...
...
src/layouts/default/menu/index.tsx
浏览文件 @
a65ad9ed
...
@@ -9,6 +9,7 @@ import { AppLogo } from '/@/components/Application';
...
@@ -9,6 +9,7 @@ import { AppLogo } from '/@/components/Application';
import
{
MenuModeEnum
,
MenuSplitTyeEnum
}
from
'/@/enums/menuEnum'
;
import
{
MenuModeEnum
,
MenuSplitTyeEnum
}
from
'/@/enums/menuEnum'
;
import
{
useMenuSetting
}
from
'/@/hooks/setting/useMenuSetting'
;
import
{
useMenuSetting
}
from
'/@/hooks/setting/useMenuSetting'
;
import
{
ScrollContainer
}
from
'/@/components/Container'
;
import
{
useGo
}
from
'/@/hooks/web/usePage'
;
import
{
useGo
}
from
'/@/hooks/web/usePage'
;
import
{
useSplitMenu
}
from
'./useLayoutMenu'
;
import
{
useSplitMenu
}
from
'./useLayoutMenu'
;
...
@@ -16,6 +17,7 @@ import { openWindow } from '/@/utils';
...
@@ -16,6 +17,7 @@ import { openWindow } from '/@/utils';
import
{
propTypes
}
from
'/@/utils/propTypes'
;
import
{
propTypes
}
from
'/@/utils/propTypes'
;
import
{
isUrl
}
from
'/@/utils/is'
;
import
{
isUrl
}
from
'/@/utils/is'
;
import
{
useRootSetting
}
from
'/@/hooks/setting/useRootSetting'
;
import
{
useRootSetting
}
from
'/@/hooks/setting/useRootSetting'
;
import
{
CSSProperties
}
from
'vue'
;
export
default
defineComponent
({
export
default
defineComponent
({
name
:
'LayoutMenu'
,
name
:
'LayoutMenu'
,
...
@@ -53,12 +55,25 @@ export default defineComponent({
...
@@ -53,12 +55,25 @@ export default defineComponent({
const
getComputedMenuMode
=
computed
(()
=>
props
.
menuMode
||
unref
(
getMenuMode
));
const
getComputedMenuMode
=
computed
(()
=>
props
.
menuMode
||
unref
(
getMenuMode
));
const
getComputedMenuTheme
=
computed
(()
=>
props
.
theme
||
unref
(
getMenuTheme
));
const
getComputedMenuTheme
=
computed
(()
=>
props
.
theme
||
unref
(
getMenuTheme
));
const
showLogo
=
computed
(()
=>
unref
(
getShowLogo
)
&&
unref
(
getIsSidebarType
));
const
appendClass
=
computed
(()
=>
props
.
splitType
===
MenuSplitTyeEnum
.
TOP
);
const
getIsShowLogo
=
computed
(()
=>
unref
(
getShowLogo
)
&&
unref
(
getIsSidebarType
));
const
getUseScroll
=
computed
(()
=>
{
return
unref
(
getIsSidebarType
)
||
props
.
splitType
===
MenuSplitTyeEnum
.
LEFT
;
});
const
getWrapperStyle
=
computed
(
():
CSSProperties
=>
{
return
{
height
:
`calc(100% -
${
unref
(
getIsShowLogo
)
?
'48px'
:
'0px'
}
)`
,
};
}
);
/**
/**
* click menu
* click menu
* @param menu
* @param menu
*/
*/
function
handleMenuClick
(
path
:
string
)
{
function
handleMenuClick
(
path
:
string
)
{
go
(
path
);
go
(
path
);
}
}
...
@@ -76,7 +91,7 @@ export default defineComponent({
...
@@ -76,7 +91,7 @@ export default defineComponent({
}
}
function
renderHeader
()
{
function
renderHeader
()
{
if
(
!
unref
(
s
howLogo
))
return
null
;
if
(
!
unref
(
getIsS
howLogo
))
return
null
;
return
(
return
(
<
AppLogo
<
AppLogo
...
@@ -87,7 +102,7 @@ export default defineComponent({
...
@@ -87,7 +102,7 @@ export default defineComponent({
);
);
}
}
return
()
=>
{
function
renderMenu
()
{
return
(
return
(
<
BasicMenu
<
BasicMenu
beforeClickFn=
{
beforeMenuClickFn
}
beforeClickFn=
{
beforeMenuClickFn
}
...
@@ -99,13 +114,22 @@ export default defineComponent({
...
@@ -99,13 +114,22 @@ export default defineComponent({
items=
{
unref
(
menusRef
)
}
items=
{
unref
(
menusRef
)
}
accordion=
{
unref
(
getAccordion
)
}
accordion=
{
unref
(
getAccordion
)
}
onMenuClick=
{
handleMenuClick
}
onMenuClick=
{
handleMenuClick
}
appendClass=
{
unref
(
appendClass
)
}
showLogo=
{
unref
(
getIsShowLogo
)
}
showLogo=
{
unref
(
showLogo
)
}
/>
>
);
{
{
}
header
:
()
=>
renderHeader
(),
}
}
return
()
=>
{
</
BasicMenu
>
return
(
<>
{
renderHeader
()
}
{
unref
(
getUseScroll
)
?
(
<
ScrollContainer
style=
{
unref
(
getWrapperStyle
)
}
>
{
()
=>
renderMenu
()
}
</
ScrollContainer
>
)
:
(
renderMenu
()
)
}
;
</>
);
);
};
};
},
},
...
...
src/layouts/default/menu/useLayoutMenu.ts
浏览文件 @
a65ad9ed
...
@@ -14,9 +14,7 @@ import { permissionStore } from '/@/store/modules/permission';
...
@@ -14,9 +14,7 @@ import { permissionStore } from '/@/store/modules/permission';
export
function
useSplitMenu
(
splitType
:
Ref
<
MenuSplitTyeEnum
>
)
{
export
function
useSplitMenu
(
splitType
:
Ref
<
MenuSplitTyeEnum
>
)
{
// Menu array
// Menu array
const
menusRef
=
ref
<
Menu
[]
>
([]);
const
menusRef
=
ref
<
Menu
[]
>
([]);
const
{
currentRoute
}
=
useRouter
();
const
{
currentRoute
}
=
useRouter
();
const
{
setMenuSetting
,
getIsHorizontal
,
getSplit
}
=
useMenuSetting
();
const
{
setMenuSetting
,
getIsHorizontal
,
getSplit
}
=
useMenuSetting
();
const
[
throttleHandleSplitLeftMenu
]
=
useThrottle
(
handleSplitLeftMenu
,
50
);
const
[
throttleHandleSplitLeftMenu
]
=
useThrottle
(
handleSplitLeftMenu
,
50
);
...
@@ -25,9 +23,11 @@ export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
...
@@ -25,9 +23,11 @@ export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
()
=>
unref
(
splitType
)
!==
MenuSplitTyeEnum
.
LEFT
&&
!
unref
(
getIsHorizontal
)
()
=>
unref
(
splitType
)
!==
MenuSplitTyeEnum
.
LEFT
&&
!
unref
(
getIsHorizontal
)
);
);
const
splitLeft
=
computed
(()
=>
!
unref
(
getSplit
)
||
unref
(
splitType
)
!==
MenuSplitTyeEnum
.
LEFT
);
const
getSplitLeft
=
computed
(
()
=>
!
unref
(
getSplit
)
||
unref
(
splitType
)
!==
MenuSplitTyeEnum
.
LEFT
);
const
s
piltTop
=
computed
(()
=>
unref
(
splitType
)
===
MenuSplitTyeEnum
.
TOP
);
const
getS
piltTop
=
computed
(()
=>
unref
(
splitType
)
===
MenuSplitTyeEnum
.
TOP
);
const
normalType
=
computed
(()
=>
{
const
normalType
=
computed
(()
=>
{
return
unref
(
splitType
)
===
MenuSplitTyeEnum
.
NONE
||
!
unref
(
getSplit
);
return
unref
(
splitType
)
===
MenuSplitTyeEnum
.
NONE
||
!
unref
(
getSplit
);
...
@@ -65,7 +65,7 @@ export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
...
@@ -65,7 +65,7 @@ export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
// Handle left menu split
// Handle left menu split
async
function
handleSplitLeftMenu
(
parentPath
:
string
)
{
async
function
handleSplitLeftMenu
(
parentPath
:
string
)
{
if
(
unref
(
s
plitLeft
))
return
;
if
(
unref
(
getS
plitLeft
))
return
;
// spilt mode left
// spilt mode left
const
children
=
await
getChildrenMenus
(
parentPath
);
const
children
=
await
getChildrenMenus
(
parentPath
);
...
@@ -88,7 +88,7 @@ export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
...
@@ -88,7 +88,7 @@ export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
}
}
// split-top
// split-top
if
(
unref
(
s
piltTop
))
{
if
(
unref
(
getS
piltTop
))
{
const
shallowMenus
=
await
getShallowMenus
();
const
shallowMenus
=
await
getShallowMenus
();
menusRef
.
value
=
shallowMenus
;
menusRef
.
value
=
shallowMenus
;
...
...
src/layouts/default/setting/SettingDrawer.tsx
浏览文件 @
a65ad9ed
...
@@ -80,7 +80,7 @@ export default defineComponent({
...
@@ -80,7 +80,7 @@ export default defineComponent({
getShowSearch
,
getShowSearch
,
}
=
useHeaderSetting
();
}
=
useHeaderSetting
();
const
{
getShowMultipleTab
,
getShowQuick
}
=
useMultipleTabSetting
();
const
{
getShowMultipleTab
,
getShowQuick
,
getShowRedo
}
=
useMultipleTabSetting
();
const
getShowMenuRef
=
computed
(()
=>
{
const
getShowMenuRef
=
computed
(()
=>
{
return
unref
(
getShowMenu
)
&&
!
unref
(
getIsHorizontal
);
return
unref
(
getShowMenu
)
&&
!
unref
(
getIsHorizontal
);
...
@@ -247,6 +247,13 @@ export default defineComponent({
...
@@ -247,6 +247,13 @@ export default defineComponent({
/>
/>
<
SwitchItem
<
SwitchItem
title=
{
t
(
'layout.setting.tabsRedoBtn'
)
}
event=
{
HandlerEnum
.
TABS_SHOW_REDO
}
def=
{
unref
(
getShowRedo
)
}
disabled=
{
!
unref
(
getShowMultipleTab
)
}
/>
<
SwitchItem
title=
{
t
(
'layout.setting.tabsQuickBtn'
)
}
title=
{
t
(
'layout.setting.tabsQuickBtn'
)
}
event=
{
HandlerEnum
.
TABS_SHOW_QUICK
}
event=
{
HandlerEnum
.
TABS_SHOW_QUICK
}
def=
{
unref
(
getShowQuick
)
}
def=
{
unref
(
getShowQuick
)
}
...
...
src/layouts/default/setting/enum.ts
浏览文件 @
a65ad9ed
...
@@ -31,6 +31,7 @@ export enum HandlerEnum {
...
@@ -31,6 +31,7 @@ export enum HandlerEnum {
HEADER_SEARCH
,
HEADER_SEARCH
,
TABS_SHOW_QUICK
,
TABS_SHOW_QUICK
,
TABS_SHOW_REDO
,
TABS_SHOW
,
TABS_SHOW
,
LOCK_TIME
,
LOCK_TIME
,
...
...
src/layouts/default/setting/handler.ts
浏览文件 @
a65ad9ed
...
@@ -113,6 +113,8 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf
...
@@ -113,6 +113,8 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf
case
HandlerEnum
.
TABS_SHOW
:
case
HandlerEnum
.
TABS_SHOW
:
return
{
multiTabsSetting
:
{
show
:
value
}
};
return
{
multiTabsSetting
:
{
show
:
value
}
};
case
HandlerEnum
.
TABS_SHOW_REDO
:
return
{
multiTabsSetting
:
{
showRedo
:
value
}
};
// ============header==================
// ============header==================
case
HandlerEnum
.
HEADER_THEME
:
case
HandlerEnum
.
HEADER_THEME
:
...
...
src/layouts/default/sider/index.less
浏览文件 @
a65ad9ed
@import
(
reference
)
'../../../design/index.less'
;
@import
(
reference
)
'../../../design/index.less'
;
@prefix
-cls:
~'
@{namespace}-layout-sideBar'
;
.
layout-sidebar
{
.
@{prefix-cls}
{
// overflow: hidden
;
z-index:
@layout-sider-fixed-z-index
;
&
.
fixed {
&
--
fixed
{
position:
fixed
;
position:
fixed
;
top:
0
;
top:
0
;
left:
0
;
left:
0
;
height:
100
%
;
height:
100
%
;
}
}
&--mix
{
top:
@header-height
;
height:
calc
(
100
%
-
@header-height)
;
}
&
.
ant-layout-sider-dark
{
&
.
ant-layout-sider-dark
{
background:
@sider-dark-bg-color
;
background:
@sider-dark-bg-color
;
...
...
src/layouts/default/sider/index.tsx
浏览文件 @
a65ad9ed
import
'./index.less'
;
import
'./index.less'
;
import
{
computed
,
defineComponent
,
ref
,
unref
,
watch
,
nextTick
,
CSSProperties
}
from
'vue'
;
import
{
computed
,
defineComponent
,
ref
,
unref
,
CSSProperties
}
from
'vue'
;
import
{
Layout
}
from
'ant-design-vue'
;
import
{
Layout
}
from
'ant-design-vue'
;
import
LayoutMenu
from
'../menu'
;
import
LayoutMenu
from
'../menu'
;
...
@@ -8,14 +8,13 @@ import LayoutMenu from '../menu';
...
@@ -8,14 +8,13 @@ import LayoutMenu from '../menu';
import
{
MenuModeEnum
,
MenuSplitTyeEnum
}
from
'/@/enums/menuEnum'
;
import
{
MenuModeEnum
,
MenuSplitTyeEnum
}
from
'/@/enums/menuEnum'
;
import
{
useMenuSetting
}
from
'/@/hooks/setting/useMenuSetting'
;
import
{
useMenuSetting
}
from
'/@/hooks/setting/useMenuSetting'
;
import
{
useHeaderSetting
}
from
'/@/hooks/setting/useHeaderSetting'
;
import
{
useTrigger
,
useDragLine
,
useSiderEvent
}
from
'./useLayoutSider'
;
import
{
useTrigger
,
useDragLine
,
useSiderEvent
}
from
'./useLayoutSider'
;
import
{
useLayoutContext
}
from
'../useLayoutContext'
;
import
{
useAppInject
}
from
'/@/hooks/web/useAppInject'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
export
default
defineComponent
({
export
default
defineComponent
({
name
:
'LayoutSideBar'
,
name
:
'LayoutSideBar'
,
setup
()
{
setup
()
{
const
topRef
=
ref
(
0
);
const
dragBarRef
=
ref
<
ElRef
>
(
null
);
const
dragBarRef
=
ref
<
ElRef
>
(
null
);
const
sideRef
=
ref
<
ElRef
>
(
null
);
const
sideRef
=
ref
<
ElRef
>
(
null
);
...
@@ -27,22 +26,18 @@ export default defineComponent({
...
@@ -27,22 +26,18 @@ export default defineComponent({
getRealWidth
,
getRealWidth
,
getMenuHidden
,
getMenuHidden
,
getMenuFixed
,
getMenuFixed
,
getIsMixMode
,
}
=
useMenuSetting
();
}
=
useMenuSetting
();
const
{
getShowFullHeaderRef
,
getUnFixedAndFull
}
=
useHeaderSetting
();
const
{
prefixCls
}
=
useDesign
(
'layout-sideBar'
);
const
injectValue
=
useLayoutContext
();
const
{
getTriggerAttr
,
getTriggerSlot
}
=
useTrigger
();
const
{
getTriggerAttr
,
getTriggerSlot
}
=
useTrigger
();
const
{
getIsMobile
}
=
useAppInject
();
const
{
renderDragLine
}
=
useDragLine
(
sideRef
,
dragBarRef
);
const
{
renderDragLine
}
=
useDragLine
(
sideRef
,
dragBarRef
);
const
{
const
{
getCollapsedWidth
,
onBreakpointChange
,
onCollapseChange
}
=
useSiderEvent
();
getCollapsedWidth
,
onBreakpointChange
,
onCollapseChange
,
onSiderClick
,
}
=
useSiderEvent
();
const
getMode
=
computed
(()
=>
{
const
getMode
=
computed
(()
=>
{
return
unref
(
getSplit
)
?
MenuModeEnum
.
INLINE
:
null
;
return
unref
(
getSplit
)
?
MenuModeEnum
.
INLINE
:
null
;
...
@@ -57,40 +52,16 @@ export default defineComponent({
...
@@ -57,40 +52,16 @@ export default defineComponent({
});
});
const
getSiderClass
=
computed
(()
=>
{
const
getSiderClass
=
computed
(()
=>
{
return
{
return
[
'layout-sidebar'
:
true
,
prefixCls
,
fixed
:
unref
(
getMenuFixed
),
{
hidden
:
!
unref
(
showClassSideBarRef
),
[
`
${
prefixCls
}
--fixed`
]:
unref
(
getMenuFixed
),
};
hidden
:
!
unref
(
showClassSideBarRef
),
[
`
${
prefixCls
}
--mix`
]:
unref
(
getIsMixMode
),
},
];
});
});
const
getSiderStyle
=
computed
(()
=>
{
const
top
=
`
${
unref
(
topRef
)}
px`
;
if
(
!
unref
(
getMenuFixed
))
{
return
{
top
};
}
return
{
top
,
height
:
`calc(100% -
${
top
}
)`
,
};
});
watch
(
()
=>
getShowFullHeaderRef
.
value
,
()
=>
{
topRef
.
value
=
0
;
if
(
unref
(
getUnFixedAndFull
))
return
;
nextTick
(()
=>
{
const
fullHeaderEl
=
unref
(
injectValue
.
fullHeader
)?.
$el
;
if
(
!
fullHeaderEl
)
return
;
topRef
.
value
=
fullHeaderEl
.
offsetHeight
;
});
},
{
immediate
:
true
,
}
);
const
getHiddenDomStyle
=
computed
(
const
getHiddenDomStyle
=
computed
(
():
CSSProperties
=>
{
():
CSSProperties
=>
{
const
width
=
`
${
unref
(
getRealWidth
)}
px`
;
const
width
=
`
${
unref
(
getRealWidth
)}
px`
;
...
@@ -121,7 +92,7 @@ export default defineComponent({
...
@@ -121,7 +92,7 @@ export default defineComponent({
return
()
=>
{
return
()
=>
{
return
(
return
(
<>
<>
{
unref
(
getMenuFixed
)
&&
!
unref
(
injectValue
.
i
sMobile
)
&&
(
{
unref
(
getMenuFixed
)
&&
!
unref
(
getI
sMobile
)
&&
(
<
div
style=
{
unref
(
getHiddenDomStyle
)
}
class=
{
{
hidden
:
!
unref
(
showClassSideBarRef
)
}
}
/>
<
div
style=
{
unref
(
getHiddenDomStyle
)
}
class=
{
{
hidden
:
!
unref
(
showClassSideBarRef
)
}
}
/>
)
}
)
}
<
Layout
.
Sider
<
Layout
.
Sider
...
@@ -129,12 +100,10 @@ export default defineComponent({
...
@@ -129,12 +100,10 @@ export default defineComponent({
breakpoint=
"lg"
breakpoint=
"lg"
collapsible
collapsible
class=
{
unref
(
getSiderClass
)
}
class=
{
unref
(
getSiderClass
)
}
style=
{
unref
(
getSiderStyle
)
}
width=
{
unref
(
getMenuWidth
)
}
width=
{
unref
(
getMenuWidth
)
}
collapsed=
{
unref
(
getCollapsed
)
}
collapsed=
{
unref
(
getCollapsed
)
}
collapsedWidth=
{
unref
(
getCollapsedWidth
)
}
collapsedWidth=
{
unref
(
getCollapsedWidth
)
}
theme=
{
unref
(
getMenuTheme
)
}
theme=
{
unref
(
getMenuTheme
)
}
onClick=
{
onSiderClick
}
onCollapse=
{
onCollapseChange
}
onCollapse=
{
onCollapseChange
}
onBreakpoint=
{
onBreakpointChange
}
onBreakpoint=
{
onBreakpointChange
}
{
...
unref
(
getTriggerAttr
)}
{
...
unref
(
getTriggerAttr
)}
...
...
src/layouts/default/sider/useLayoutSider.tsx
浏览文件 @
a65ad9ed
...
@@ -16,7 +16,7 @@ export function useSiderEvent() {
...
@@ -16,7 +16,7 @@ export function useSiderEvent() {
const
brokenRef
=
ref
(
false
);
const
brokenRef
=
ref
(
false
);
const
collapseRef
=
ref
(
true
);
const
collapseRef
=
ref
(
true
);
const
{
setMenuSetting
,
getCollapsed
,
getMiniWidthNumber
,
getShowMenu
}
=
useMenuSetting
();
const
{
setMenuSetting
,
getCollapsed
,
getMiniWidthNumber
}
=
useMenuSetting
();
const
getCollapsedWidth
=
computed
(()
=>
{
const
getCollapsedWidth
=
computed
(()
=>
{
return
unref
(
brokenRef
)
?
0
:
unref
(
getMiniWidthNumber
);
return
unref
(
brokenRef
)
?
0
:
unref
(
getMiniWidthNumber
);
...
@@ -36,12 +36,7 @@ export function useSiderEvent() {
...
@@ -36,12 +36,7 @@ export function useSiderEvent() {
brokenRef
.
value
=
broken
;
brokenRef
.
value
=
broken
;
}
}
function
onSiderClick
(
e
:
ChangeEvent
)
{
return
{
getCollapsedWidth
,
onCollapseChange
,
onBreakpointChange
};
if
(
!
e
||
!
e
.
target
||
e
.
target
.
className
!==
'basic-menu__content'
)
return
;
if
(
!
unref
(
getCollapsed
)
||
!
unref
(
getShowMenu
))
return
;
setMenuSetting
({
collapsed
:
false
});
}
return
{
getCollapsedWidth
,
onCollapseChange
,
onBreakpointChange
,
onSiderClick
};
}
}
/**
/**
...
...
src/layouts/default/tabs/components/TabContent.vue
浏览文件 @
a65ad9ed
...
@@ -4,7 +4,7 @@
...
@@ -4,7 +4,7 @@
<span
class=
"ml-1"
>
{{
getTitle
}}
</span>
<span
class=
"ml-1"
>
{{
getTitle
}}
</span>
</div>
</div>
<span
:class=
"`$
{prefixCls}__extra
`" v-else
>
<span
:class=
"`$
{prefixCls}__extra
-quick`" v-else @click="handleContext"
>
<RightOutlined
/>
<RightOutlined
/>
</span>
</span>
</Dropdown>
</Dropdown>
...
...
src/layouts/default/tabs/components/TabRedo.vue
0 → 100644
浏览文件 @
a65ad9ed
<
template
>
<Tooltip
:title=
"t('layout.multipleTab.tooltipRedo')"
placement=
"bottom"
:mouseEnterDelay=
"0.5"
>
<span
:class=
"`$
{prefixCls}__extra-redo`" @click="handleRedo">
<RedoOutlined
:spin=
"loading"
/>
</span>
</Tooltip>
</
template
>
<
script
lang=
"ts"
>
import
{
defineComponent
,
ref
}
from
'vue'
;
import
{
RedoOutlined
}
from
'@ant-design/icons-vue'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
import
{
Tooltip
}
from
'ant-design-vue'
;
import
{
useI18n
}
from
'/@/hooks/web/useI18n'
;
import
{
useTabs
}
from
'/@/hooks/web/useTabs'
;
export
default
defineComponent
({
name
:
'TabContent'
,
components
:
{
RedoOutlined
,
Tooltip
},
setup
()
{
const
loading
=
ref
(
false
);
const
{
prefixCls
}
=
useDesign
(
'multiple-tabs-content'
);
const
{
t
}
=
useI18n
();
const
{
refreshPage
}
=
useTabs
();
async
function
handleRedo
()
{
loading
.
value
=
true
;
await
refreshPage
();
setTimeout
(()
=>
{
loading
.
value
=
false
;
// Animation execution time
},
1000
);
}
return
{
prefixCls
,
t
,
handleRedo
,
loading
};
},
});
</
script
>
src/layouts/default/tabs/index.less
浏览文件 @
a65ad9ed
...
@@ -34,30 +34,30 @@
...
@@ -34,30 +34,30 @@
border:
1
px
solid
darken
(
@border-color-light
,
6
%
);
border:
1
px
solid
darken
(
@border-color-light
,
6
%
);
transition:
none
;
transition:
none
;
&:
not
(.
ant-tabs-tab-active
)
::
after
{
//
&:
not
(.
ant-tabs-tab-active
)
::
before
{
position:
absolute
;
//
position:
absolute
;
bottom
:
-1
px
;
//
top
:
-1
px
;
left:
50
%
;
//
left:
50
%
;
width:
100
%
;
//
width:
100
%
;
height:
2
px
;
//
height:
2
px
;
background-color:
@primary-color
;
//
background-color:
@primary-color
;
content:
''
;
//
content:
''
;
opacity:
0
;
//
opacity:
0
;
transform:
translate
(
-50
%,
0
)
scaleX
(
0
);
//
transform:
translate
(
-50
%,
0
)
scaleX
(
0
);
transform-origin:
center
;
//
transform-origin:
center
;
transition:
none
;
//
transition:
none
;
}
//
}
&:
hover
{
&:
hover
{
.
ant-tabs-close-x
{
.
ant-tabs-close-x
{
opacity:
1
;
opacity:
1
;
}
}
&:
not
(.
ant-tabs-tab-active
)
::
after
{
//
&:
not
(.
ant-tabs-tab-active
)
::
before
{
opacity:
1
;
//
opacity:
1
;
transform:
translate
(
-50
%,
0
)
scaleX
(
1
);
//
transform:
translate
(
-50
%,
0
)
scaleX
(
1
);
transition:
all
0.3
s
ease-in-out
;
//
transition:
all
0.3
s
ease-in-out
;
}
//
}
}
}
.
ant-tabs-close-x
{
.
ant-tabs-close-x
{
...
@@ -152,12 +152,13 @@
...
@@ -152,12 +152,13 @@
}
}
&-content
{
&-content
{
&__extra
{
&__extra-quick,
&__extra-redo
{
display:
inline-block
;
display:
inline-block
;
width:
@multiple-height
;
width:
36
px
;
height:
@multiple-height
;
height:
@multiple-height
;
line-height:
@multiple-height
;
line-height:
@multiple-height
;
color:
#
999
;
color:
#
666
;
text-align:
center
;
text-align:
center
;
cursor:
pointer
;
cursor:
pointer
;
border-left:
1
px
solid
#eee;
border-left:
1
px
solid
#eee;
...
@@ -171,6 +172,12 @@
...
@@ -171,6 +172,12 @@
}
}
}
}
&__extra-redo
{
span
[
role='img'
]
{
transform:
rotate
(
0
deg
);
}
}
&__info
{
&__info
{
display:
inline-block
;
display:
inline-block
;
width:
100
%
;
width:
100
%
;
...
...
src/layouts/default/tabs/index.vue
浏览文件 @
a65ad9ed
...
@@ -17,14 +17,16 @@
...
@@ -17,14 +17,16 @@
</
template
>
</
template
>
</TabPane>
</TabPane>
</template>
</template>
<
template
#
tabBarExtraContent
>
<QuickButton
/>
<
template
#
tabBarExtraContent
v-if=
"getShowRedo || getShowQuick"
>
<TabRedo
v-if=
"getShowRedo"
/>
<QuickButton
v-if=
"getShowQuick"
/>
</
template
>
</
template
>
</Tabs>
</Tabs>
</div>
</div>
</template>
</template>
<
script
lang=
"ts"
>
<
script
lang=
"ts"
>
import
{
defineComponent
,
watch
,
computed
,
unref
,
ref
}
from
'vue'
;
import
{
defineComponent
,
computed
,
unref
,
ref
}
from
'vue'
;
import
{
Tabs
}
from
'ant-design-vue'
;
import
{
Tabs
}
from
'ant-design-vue'
;
import
TabContent
from
'./components/TabContent.vue'
;
import
TabContent
from
'./components/TabContent.vue'
;
...
@@ -38,61 +40,52 @@
...
@@ -38,61 +40,52 @@
import
{
REDIRECT_NAME
}
from
'/@/router/constant'
;
import
{
REDIRECT_NAME
}
from
'/@/router/constant'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
import
{
createAsyncComponent
}
from
'/@/utils/factory/createAsyncComponent'
;
import
{
createAsyncComponent
}
from
'/@/utils/factory/createAsyncComponent'
;
import
{
listenerLastChangeTab
}
from
'/@/logics/mitt/tabChange'
;
import
{
useMultipleTabSetting
}
from
'/@/hooks/setting/useMultipleTabSetting'
;
export
default
defineComponent
({
export
default
defineComponent
({
name
:
'MultipleTabs'
,
name
:
'MultipleTabs'
,
components
:
{
components
:
{
QuickButton
:
createAsyncComponent
(()
=>
import
(
'./components/QuickButton.vue'
)),
QuickButton
:
createAsyncComponent
(()
=>
import
(
'./components/QuickButton.vue'
)),
TabRedo
:
createAsyncComponent
(()
=>
import
(
'./components/TabRedo.vue'
)),
Tabs
,
Tabs
,
TabPane
:
Tabs
.
TabPane
,
TabPane
:
Tabs
.
TabPane
,
TabContent
,
TabContent
,
},
},
setup
()
{
setup
()
{
const
affixTextList
=
initAffixTabs
();
const
affixTextList
=
initAffixTabs
();
const
activeKeyRef
=
ref
(
''
);
const
activeKeyRef
=
ref
(
''
);
useTabsDrag
(
affixTextList
);
useTabsDrag
(
affixTextList
);
const
{
prefixCls
}
=
useDesign
(
'multiple-tabs'
);
const
{
prefixCls
}
=
useDesign
(
'multiple-tabs'
);
const
go
=
useGo
();
const
go
=
useGo
();
const
{
getShowQuick
,
getShowRedo
}
=
useMultipleTabSetting
();
const
getTabsState
=
computed
(()
=>
tabStore
.
getTabsState
);
const
getTabsState
=
computed
(()
=>
tabStore
.
getTabsState
);
const
unClose
=
computed
(()
=>
{
const
unClose
=
computed
(()
=>
unref
(
getTabsState
).
length
===
1
);
return
getTabsState
.
value
.
length
===
1
;
});
const
getWrapClass
=
computed
(()
=>
{
const
getWrapClass
=
computed
(()
=>
{
return
[
return
[
prefixCls
,
prefixCls
,
{
{
[
`
${
prefixCls
}
--hide-close`
]:
un
Close
,
[
`
${
prefixCls
}
--hide-close`
]:
un
ref
(
unClose
)
,
},
},
];
];
});
});
watch
(
listenerLastChangeTab
((
route
)
=>
{
()
=>
tabStore
.
getLastChangeRouteState
?.
path
,
const
{
name
}
=
route
;
()
=>
{
if
(
name
===
REDIRECT_NAME
||
!
route
||
!
userStore
.
getTokenState
)
return
;
if
(
tabStore
.
getLastChangeRouteState
?.
name
===
REDIRECT_NAME
)
{
return
;
const
{
path
,
fullPath
}
=
route
;
}
const
p
=
fullPath
||
path
;
const
lastChangeRoute
=
unref
(
tabStore
.
getLastChangeRouteState
);
if
(
!
lastChangeRoute
||
!
userStore
.
getTokenState
)
return
;
if
(
activeKeyRef
.
value
!==
p
)
{
activeKeyRef
.
value
=
p
;
const
{
path
,
fullPath
}
=
lastChangeRoute
;
const
p
=
fullPath
||
path
;
if
(
activeKeyRef
.
value
!==
p
)
{
activeKeyRef
.
value
=
p
;
}
tabStore
.
addTabAction
(
lastChangeRoute
);
},
{
immediate
:
true
,
}
}
);
tabStore
.
addTabAction
(
unref
(
route
));
});
function
handleChange
(
activeKey
:
any
)
{
function
handleChange
(
activeKey
:
any
)
{
activeKeyRef
.
value
=
activeKey
;
activeKeyRef
.
value
=
activeKey
;
...
@@ -114,6 +107,8 @@
...
@@ -114,6 +107,8 @@
handleChange
,
handleChange
,
activeKeyRef
,
activeKeyRef
,
getTabsState
,
getTabsState
,
getShowQuick
,
getShowRedo
,
};
};
},
},
});
});
...
...
src/layouts/default/tabs/useTabDropdown.ts
浏览文件 @
a65ad9ed
...
@@ -10,7 +10,6 @@ import { useTabs } from '/@/hooks/web/useTabs';
...
@@ -10,7 +10,6 @@ import { useTabs } from '/@/hooks/web/useTabs';
import
{
useI18n
}
from
'/@/hooks/web/useI18n'
;
import
{
useI18n
}
from
'/@/hooks/web/useI18n'
;
import
{
useHeaderSetting
}
from
'/@/hooks/setting/useHeaderSetting'
;
import
{
useHeaderSetting
}
from
'/@/hooks/setting/useHeaderSetting'
;
import
{
useMenuSetting
}
from
'/@/hooks/setting/useMenuSetting'
;
import
{
useMenuSetting
}
from
'/@/hooks/setting/useMenuSetting'
;
import
{
useMultipleTabSetting
}
from
'/@/hooks/setting/useMultipleTabSetting'
;
const
{
t
}
=
useI18n
();
const
{
t
}
=
useI18n
();
...
@@ -24,11 +23,8 @@ export function useTabDropdown(tabContentProps: TabContentProps) {
...
@@ -24,11 +23,8 @@ export function useTabDropdown(tabContentProps: TabContentProps) {
const
{
getShowMenu
,
setMenuSetting
}
=
useMenuSetting
();
const
{
getShowMenu
,
setMenuSetting
}
=
useMenuSetting
();
const
{
getShowHeader
,
setHeaderSetting
}
=
useHeaderSetting
();
const
{
getShowHeader
,
setHeaderSetting
}
=
useHeaderSetting
();
const
{
getShowQuick
}
=
useMultipleTabSetting
();
const
isTabs
=
computed
(()
=>
const
isTabs
=
computed
(()
=>
tabContentProps
.
type
===
TabContentEnum
.
TAB_TYPE
);
!
unref
(
getShowQuick
)
?
true
:
tabContentProps
.
type
===
TabContentEnum
.
TAB_TYPE
);
const
getCurrentTab
=
computed
(
const
getCurrentTab
=
computed
(
():
RouteLocationNormalized
=>
{
():
RouteLocationNormalized
=>
{
...
...
src/layouts/default/useLayoutContext.ts
浏览文件 @
a65ad9ed
...
@@ -3,7 +3,6 @@ import { createContext, useContext } from '/@/hooks/core/useContext';
...
@@ -3,7 +3,6 @@ import { createContext, useContext } from '/@/hooks/core/useContext';
export
interface
LayoutContextProps
{
export
interface
LayoutContextProps
{
fullHeader
:
Ref
<
ComponentRef
>
;
fullHeader
:
Ref
<
ComponentRef
>
;
isMobile
:
Ref
<
boolean
>
;
}
}
const
key
:
InjectionKey
<
LayoutContextProps
>
=
Symbol
();
const
key
:
InjectionKey
<
LayoutContextProps
>
=
Symbol
();
...
...
src/locales/lang/en/layout/header.ts
浏览文件 @
a65ad9ed
...
@@ -7,7 +7,7 @@ export default {
...
@@ -7,7 +7,7 @@ export default {
tooltipErrorLog
:
'Error log'
,
tooltipErrorLog
:
'Error log'
,
tooltipLock
:
'Lock screen'
,
tooltipLock
:
'Lock screen'
,
tooltipNotify
:
'Notification'
,
tooltipNotify
:
'Notification'
,
tooltipRedo
:
'Refresh'
,
tooltipEntryFull
:
'Full Screen'
,
tooltipEntryFull
:
'Full Screen'
,
tooltipExitFull
:
'Exit Full Screen'
,
tooltipExitFull
:
'Exit Full Screen'
,
...
...
src/locales/lang/en/layout/multipleTab.ts
浏览文件 @
a65ad9ed
...
@@ -7,4 +7,5 @@ export default {
...
@@ -7,4 +7,5 @@ export default {
closeAll
:
'Close All'
,
closeAll
:
'Close All'
,
putAway
:
'PutAway'
,
putAway
:
'PutAway'
,
unfold
:
'Unfold'
,
unfold
:
'Unfold'
,
tooltipRedo
:
'Refresh'
,
};
};
src/locales/lang/en/layout/setting.ts
浏览文件 @
a65ad9ed
...
@@ -53,6 +53,7 @@ export default {
...
@@ -53,6 +53,7 @@ export default {
breadcrumbIcon
:
'Breadcrumbs Icon'
,
breadcrumbIcon
:
'Breadcrumbs Icon'
,
tabs
:
'Tabs'
,
tabs
:
'Tabs'
,
tabsQuickBtn
:
'Tabs quick button'
,
tabsQuickBtn
:
'Tabs quick button'
,
tabsRedoBtn
:
'Tabs redo button'
,
sidebar
:
'Sidebar'
,
sidebar
:
'Sidebar'
,
header
:
'Header'
,
header
:
'Header'
,
footer
:
'Footer'
,
footer
:
'Footer'
,
...
...
src/locales/lang/zh_CN/layout/header.ts
浏览文件 @
a65ad9ed
...
@@ -8,7 +8,7 @@ export default {
...
@@ -8,7 +8,7 @@ export default {
tooltipErrorLog
:
'错误日志'
,
tooltipErrorLog
:
'错误日志'
,
tooltipLock
:
'锁定屏幕'
,
tooltipLock
:
'锁定屏幕'
,
tooltipNotify
:
'消息通知'
,
tooltipNotify
:
'消息通知'
,
tooltipRedo
:
'刷新'
,
tooltipEntryFull
:
'全屏'
,
tooltipEntryFull
:
'全屏'
,
tooltipExitFull
:
'退出全屏'
,
tooltipExitFull
:
'退出全屏'
,
...
...
src/locales/lang/zh_CN/layout/multipleTab.ts
浏览文件 @
a65ad9ed
...
@@ -7,4 +7,5 @@ export default {
...
@@ -7,4 +7,5 @@ export default {
closeAll
:
'关闭全部'
,
closeAll
:
'关闭全部'
,
putAway
:
'收起'
,
putAway
:
'收起'
,
unfold
:
'展开'
,
unfold
:
'展开'
,
tooltipRedo
:
'刷新'
,
};
};
src/locales/lang/zh_CN/layout/setting.ts
浏览文件 @
a65ad9ed
...
@@ -52,6 +52,7 @@ export default {
...
@@ -52,6 +52,7 @@ export default {
breadcrumbIcon
:
'面包屑图标'
,
breadcrumbIcon
:
'面包屑图标'
,
tabs
:
'标签页'
,
tabs
:
'标签页'
,
tabsQuickBtn
:
'标签页快捷按钮'
,
tabsQuickBtn
:
'标签页快捷按钮'
,
tabsRedoBtn
:
'标签页刷新按钮'
,
sidebar
:
'左侧菜单'
,
sidebar
:
'左侧菜单'
,
header
:
'顶栏'
,
header
:
'顶栏'
,
footer
:
'页脚'
,
footer
:
'页脚'
,
...
...
src/logics/mitt/tabChange.ts
0 → 100644
浏览文件 @
a65ad9ed
/**
* Used to monitor routing changes to change the status of menus and tabs. There is no need to monitor the route, because the route status change is affected by the page rendering time, which will be slow
*/
import
Mitt
from
'/@/utils/mitt'
;
import
type
{
RouteLocationNormalized
}
from
'vue-router'
;
import
{
getRoute
}
from
'/@/router/helper/routeHelper'
;
const
mitt
=
new
Mitt
();
const
key
=
Symbol
();
let
lastChangeTab
:
RouteLocationNormalized
;
export
function
setLastChangeTab
(
lastChangeRoute
:
RouteLocationNormalized
)
{
mitt
.
emit
(
key
,
getRoute
(
lastChangeRoute
));
lastChangeTab
=
getRoute
(
lastChangeRoute
);
}
export
function
listenerLastChangeTab
(
callback
:
(
route
:
RouteLocationNormalized
)
=>
void
,
immediate
=
true
)
{
mitt
.
on
(
key
,
callback
);
if
(
immediate
)
{
callback
(
lastChangeTab
);
}
}
src/router/guard/index.ts
浏览文件 @
a65ad9ed
...
@@ -8,13 +8,12 @@ import { createPageLoadingGuard } from './pageLoadingGuard';
...
@@ -8,13 +8,12 @@ import { createPageLoadingGuard } from './pageLoadingGuard';
import
{
useGlobSetting
,
useProjectSetting
}
from
'/@/hooks/setting'
;
import
{
useGlobSetting
,
useProjectSetting
}
from
'/@/hooks/setting'
;
import
{
getRoute
}
from
'/@/router/helper/routeHelper'
;
import
{
setTitle
}
from
'/@/utils/browser'
;
import
{
setTitle
}
from
'/@/utils/browser'
;
import
{
AxiosCanceler
}
from
'/@/utils/http/axios/axiosCancel'
;
import
{
AxiosCanceler
}
from
'/@/utils/http/axios/axiosCancel'
;
import
{
tabStore
}
from
'/@/store/modules/tab'
;
import
{
useI18n
}
from
'/@/hooks/web/useI18n'
;
import
{
useI18n
}
from
'/@/hooks/web/useI18n'
;
import
{
REDIRECT_NAME
}
from
'/@/router/constant'
;
import
{
REDIRECT_NAME
}
from
'/@/router/constant'
;
import
{
setLastChangeTab
}
from
'/@/logics/mitt/tabChange'
;
const
{
closeMessageOnSwitch
,
removeAllHttpPending
}
=
useProjectSetting
();
const
{
closeMessageOnSwitch
,
removeAllHttpPending
}
=
useProjectSetting
();
const
globSetting
=
useGlobSetting
();
const
globSetting
=
useGlobSetting
();
...
@@ -35,8 +34,7 @@ export function createGuard(router: Router) {
...
@@ -35,8 +34,7 @@ export function createGuard(router: Router) {
router
.
beforeEach
(
async
(
to
)
=>
{
router
.
beforeEach
(
async
(
to
)
=>
{
to
.
meta
.
loaded
=
!!
loadedPageMap
.
get
(
to
.
path
);
to
.
meta
.
loaded
=
!!
loadedPageMap
.
get
(
to
.
path
);
// Notify routing changes
// Notify routing changes
tabStore
.
commitLastChangeRouteState
(
getRoute
(
to
));
setLastChangeTab
(
to
);
try
{
try
{
if
(
closeMessageOnSwitch
)
{
if
(
closeMessageOnSwitch
)
{
Modal
.
destroyAll
();
Modal
.
destroyAll
();
...
...
src/router/menus/index.ts
浏览文件 @
a65ad9ed
...
@@ -68,6 +68,7 @@ export async function getCurrentParentPath(currentPath: string) {
...
@@ -68,6 +68,7 @@ export async function getCurrentParentPath(currentPath: string) {
export
async
function
getShallowMenus
():
Promise
<
Menu
[]
>
{
export
async
function
getShallowMenus
():
Promise
<
Menu
[]
>
{
const
menus
=
await
getAsyncMenus
();
const
menus
=
await
getAsyncMenus
();
const
routes
=
router
.
getRoutes
();
const
routes
=
router
.
getRoutes
();
const
shallowMenuList
=
menus
.
map
((
item
)
=>
({
...
item
,
children
:
undefined
}));
const
shallowMenuList
=
menus
.
map
((
item
)
=>
({
...
item
,
children
:
undefined
}));
return
!
isBackMode
()
?
shallowMenuList
.
filter
(
basicFilter
(
routes
))
:
shallowMenuList
;
return
!
isBackMode
()
?
shallowMenuList
.
filter
(
basicFilter
(
routes
))
:
shallowMenuList
;
}
}
...
...
src/settings/projectSetting.ts
浏览文件 @
a65ad9ed
...
@@ -62,8 +62,7 @@ const setting: ProjectConfig = {
...
@@ -62,8 +62,7 @@ const setting: ProjectConfig = {
theme
:
ThemeEnum
.
LIGHT
,
theme
:
ThemeEnum
.
LIGHT
,
// Whether to enable the lock screen function
// Whether to enable the lock screen function
useLockPage
:
true
,
useLockPage
:
true
,
// Whether to show the refresh button
showRedo
:
true
,
// Whether to show the full screen button
// Whether to show the full screen button
showFullScreen
:
true
,
showFullScreen
:
true
,
// Whether to show the document button
// Whether to show the document button
...
@@ -117,6 +116,9 @@ const setting: ProjectConfig = {
...
@@ -117,6 +116,9 @@ const setting: ProjectConfig = {
canDrag
:
true
,
canDrag
:
true
,
// Turn on quick actions
// Turn on quick actions
showQuick
:
true
,
showQuick
:
true
,
// Whether to show the refresh button
showRedo
:
true
,
},
},
// Transition Setting
// Transition Setting
...
...
src/store/modules/tab.ts
浏览文件 @
a65ad9ed
...
@@ -5,7 +5,6 @@ import { Action, Module, Mutation, VuexModule, getModule } from 'vuex-module-dec
...
@@ -5,7 +5,6 @@ import { Action, Module, Mutation, VuexModule, getModule } from 'vuex-module-dec
import
{
hotModuleUnregisterModule
}
from
'/@/utils/helper/vuexHelper'
;
import
{
hotModuleUnregisterModule
}
from
'/@/utils/helper/vuexHelper'
;
import
{
PageEnum
}
from
'/@/enums/pageEnum'
;
import
{
PageEnum
}
from
'/@/enums/pageEnum'
;
import
{
userStore
}
from
'./user'
;
import
store
from
'/@/store'
;
import
store
from
'/@/store'
;
import
router
from
'/@/router'
;
import
router
from
'/@/router'
;
...
@@ -13,8 +12,7 @@ import { PAGE_NOT_FOUND_ROUTE, REDIRECT_ROUTE } from '/@/router/constant';
...
@@ -13,8 +12,7 @@ import { PAGE_NOT_FOUND_ROUTE, REDIRECT_ROUTE } from '/@/router/constant';
import
{
RouteLocationNormalized
,
RouteLocationRaw
}
from
'vue-router'
;
import
{
RouteLocationNormalized
,
RouteLocationRaw
}
from
'vue-router'
;
import
{
getRoute
}
from
'/@/router/helper/routeHelper'
;
import
{
getRoute
}
from
'/@/router/helper/routeHelper'
;
import
{
useGo
,
useRedo
}
from
'/@/hooks/web/usePage'
;
import
{
useGo
,
useRedo
}
from
'/@/hooks/web/usePage'
;
import
{
cloneDeep
}
from
'lodash-es'
;
// declare namespace TabsStore {
const
NAME
=
'tab'
;
const
NAME
=
'tab'
;
...
@@ -34,19 +32,12 @@ class Tab extends VuexModule {
...
@@ -34,19 +32,12 @@ class Tab extends VuexModule {
// tab list
// tab list
tabsState
:
RouteLocationNormalized
[]
=
[];
tabsState
:
RouteLocationNormalized
[]
=
[];
// Last route change
lastChangeRouteState
:
RouteLocationNormalized
|
null
=
null
;
lastDragEndIndexState
=
0
;
lastDragEndIndexState
=
0
;
get
getTabsState
()
{
get
getTabsState
()
{
return
this
.
tabsState
;
return
this
.
tabsState
;
}
}
get
getLastChangeRouteState
()
{
return
this
.
lastChangeRouteState
;
}
get
getCurrentTab
():
RouteLocationNormalized
{
get
getCurrentTab
():
RouteLocationNormalized
{
const
route
=
unref
(
router
.
currentRoute
);
const
route
=
unref
(
router
.
currentRoute
);
return
this
.
tabsState
.
find
((
item
)
=>
item
.
path
===
route
.
path
)
!
;
return
this
.
tabsState
.
find
((
item
)
=>
item
.
path
===
route
.
path
)
!
;
...
@@ -61,12 +52,6 @@ class Tab extends VuexModule {
...
@@ -61,12 +52,6 @@ class Tab extends VuexModule {
}
}
@
Mutation
@
Mutation
commitLastChangeRouteState
(
route
:
RouteLocationNormalized
):
void
{
if
(
!
userStore
.
getTokenState
)
return
;
this
.
lastChangeRouteState
=
route
;
}
@
Mutation
commitClearCache
():
void
{
commitClearCache
():
void
{
this
.
cachedMapState
=
new
Map
();
this
.
cachedMapState
=
new
Map
();
}
}
...
@@ -152,7 +137,7 @@ class Tab extends VuexModule {
...
@@ -152,7 +137,7 @@ class Tab extends VuexModule {
this
.
tabsState
.
splice
(
updateIndex
,
1
,
curTab
);
this
.
tabsState
.
splice
(
updateIndex
,
1
,
curTab
);
return
;
return
;
}
}
this
.
tabsState
.
push
(
route
);
this
.
tabsState
=
cloneDeep
([...
this
.
tabsState
,
route
]
);
}
}
/**
/**
...
@@ -210,7 +195,7 @@ class Tab extends VuexModule {
...
@@ -210,7 +195,7 @@ class Tab extends VuexModule {
}
}
@
Mutation
@
Mutation
commitRedoPage
()
{
async
commitRedoPage
()
{
const
route
=
router
.
currentRoute
.
value
;
const
route
=
router
.
currentRoute
.
value
;
for
(
const
[
key
,
value
]
of
this
.
cachedMapState
)
{
for
(
const
[
key
,
value
]
of
this
.
cachedMapState
)
{
const
index
=
value
.
findIndex
((
item
)
=>
item
===
(
route
.
name
as
string
));
const
index
=
value
.
findIndex
((
item
)
=>
item
===
(
route
.
name
as
string
));
...
@@ -225,7 +210,7 @@ class Tab extends VuexModule {
...
@@ -225,7 +210,7 @@ class Tab extends VuexModule {
this
.
cachedMapState
.
set
(
key
,
value
);
this
.
cachedMapState
.
set
(
key
,
value
);
}
}
const
redo
=
useRedo
();
const
redo
=
useRedo
();
redo
();
await
redo
();
}
}
@
Action
@
Action
...
...
src/types/config.d.ts
浏览文件 @
a65ad9ed
...
@@ -27,6 +27,9 @@ export interface MultiTabsSetting {
...
@@ -27,6 +27,9 @@ export interface MultiTabsSetting {
// 开启快速操作
// 开启快速操作
showQuick
:
boolean
;
showQuick
:
boolean
;
canDrag
:
boolean
;
canDrag
:
boolean
;
// 显示刷新按钮
showRedo
:
boolean
;
}
}
export
interface
HeaderSetting
{
export
interface
HeaderSetting
{
...
@@ -34,8 +37,7 @@ export interface HeaderSetting {
...
@@ -34,8 +37,7 @@ export interface HeaderSetting {
fixed
:
boolean
;
fixed
:
boolean
;
show
:
boolean
;
show
:
boolean
;
theme
:
ThemeEnum
;
theme
:
ThemeEnum
;
// 显示刷新按钮
showRedo
:
boolean
;
// 显示全屏按钮
// 显示全屏按钮
showFullScreen
:
boolean
;
showFullScreen
:
boolean
;
// 开启全屏功能
// 开启全屏功能
...
...
src/utils/mitt.ts
浏览文件 @
a65ad9ed
...
@@ -6,13 +6,13 @@
...
@@ -6,13 +6,13 @@
* @returns {Function} The function's instance
* @returns {Function} The function's instance
*/
*/
export
default
class
Mitt
{
export
default
class
Mitt
{
private
cache
:
Map
<
string
,
Array
<
(
data
:
any
)
=>
void
>>
;
private
cache
:
Map
<
string
|
Symbol
,
Array
<
(...
data
:
any
)
=>
void
>>
;
constructor
(
all
=
[])
{
constructor
(
all
=
[])
{
// A Map of event names to registered handler functions.
// A Map of event names to registered handler functions.
this
.
cache
=
new
Map
(
all
);
this
.
cache
=
new
Map
(
all
);
}
}
once
(
type
:
string
,
handler
:
Fn
)
{
once
(
type
:
string
|
Symbol
,
handler
:
Fn
)
{
const
decor
=
(...
args
:
any
[])
=>
{
const
decor
=
(...
args
:
any
[])
=>
{
handler
&&
handler
.
apply
(
this
,
args
);
handler
&&
handler
.
apply
(
this
,
args
);
this
.
off
(
type
,
decor
);
this
.
off
(
type
,
decor
);
...
@@ -27,7 +27,7 @@ export default class Mitt {
...
@@ -27,7 +27,7 @@ export default class Mitt {
* @param {string|symbol} type Type of event to listen for, or `"*"` for all events
* @param {string|symbol} type Type of event to listen for, or `"*"` for all events
* @param {Function} handler Function to call in response to given event
* @param {Function} handler Function to call in response to given event
*/
*/
on
(
type
:
string
,
handler
:
Fn
)
{
on
(
type
:
string
|
Symbol
,
handler
:
Fn
)
{
const
handlers
=
this
.
cache
.
get
(
type
);
const
handlers
=
this
.
cache
.
get
(
type
);
const
added
=
handlers
&&
handlers
.
push
(
handler
);
const
added
=
handlers
&&
handlers
.
push
(
handler
);
if
(
!
added
)
{
if
(
!
added
)
{
...
@@ -41,7 +41,7 @@ export default class Mitt {
...
@@ -41,7 +41,7 @@ export default class Mitt {
* @param {string|symbol} type Type of event to unregister `handler` from, or `"*"`
* @param {string|symbol} type Type of event to unregister `handler` from, or `"*"`
* @param {Function} handler Handler function to remove
* @param {Function} handler Handler function to remove
*/
*/
off
(
type
:
string
,
handler
:
Fn
)
{
off
(
type
:
string
|
Symbol
,
handler
:
Fn
)
{
const
handlers
=
this
.
cache
.
get
(
type
);
const
handlers
=
this
.
cache
.
get
(
type
);
if
(
handlers
)
{
if
(
handlers
)
{
handlers
.
splice
(
handlers
.
indexOf
(
handler
)
>>>
0
,
1
);
handlers
.
splice
(
handlers
.
indexOf
(
handler
)
>>>
0
,
1
);
...
@@ -57,7 +57,7 @@ export default class Mitt {
...
@@ -57,7 +57,7 @@ export default class Mitt {
* @param {string|symbol} type The event type to invoke
* @param {string|symbol} type The event type to invoke
* @param {*} [evt] Any value (object is recommended and powerful), passed to each handler
* @param {*} [evt] Any value (object is recommended and powerful), passed to each handler
*/
*/
emit
(
type
:
string
,
evt
:
any
)
{
emit
(
type
:
string
|
Symbol
,
evt
:
any
)
{
for
(
const
handler
of
(
this
.
cache
.
get
(
type
)
||
[]).
slice
())
handler
(
evt
);
for
(
const
handler
of
(
this
.
cache
.
get
(
type
)
||
[]).
slice
())
handler
(
evt
);
for
(
const
handler
of
(
this
.
cache
.
get
(
'*'
)
||
[]).
slice
())
handler
(
type
,
evt
);
for
(
const
handler
of
(
this
.
cache
.
get
(
'*'
)
||
[]).
slice
())
handler
(
type
,
evt
);
}
}
...
...
src/views/sys/lock/LockPage.vue
浏览文件 @
a65ad9ed
...
@@ -144,7 +144,7 @@
...
@@ -144,7 +144,7 @@
right
:
0
;
right
:
0
;
bottom
:
0
;
bottom
:
0
;
left
:
0
;
left
:
0
;
z-index
:
3000
;
z-index
:
@
lock-page-z-index
;
display
:
flex
;
display
:
flex
;
width
:
100vw
;
width
:
100vw
;
height
:
100vh
;
height
:
100vh
;
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论