commit
e3a9c77fd1
@ -11,6 +11,7 @@
|
||||
:sider-collapsed-width="siderCollapsedWidth"
|
||||
:sider-collapse="app.siderCollapse"
|
||||
:fixed-footer="theme.footer.fixed"
|
||||
:footer-visible="theme.footer.visible"
|
||||
@update:sider-collapse="app.setSiderCollapse"
|
||||
>
|
||||
<template #header>
|
||||
|
@ -23,6 +23,8 @@ interface Props {
|
||||
visible?: boolean;
|
||||
/** 当前路由路径 */
|
||||
currentPath?: string;
|
||||
/** 是否固定在tab卡不可关闭 */
|
||||
affix?: boolean;
|
||||
/** 鼠标x坐标 */
|
||||
x: number;
|
||||
/** 鼠标y坐标 */
|
||||
@ -72,7 +74,7 @@ const options = computed<Option[]>(() => [
|
||||
{
|
||||
label: '关闭',
|
||||
key: 'close-current',
|
||||
disabled: props.currentPath === tab.homeTab.fullPath,
|
||||
disabled: props.currentPath === tab.homeTab.fullPath || Boolean(props.affix),
|
||||
icon: iconRender({ icon: 'ant-design:close-outlined' })
|
||||
},
|
||||
{
|
||||
|
@ -6,12 +6,12 @@
|
||||
:key="item.fullPath"
|
||||
:is-active="tab.activeTab === item.fullPath"
|
||||
:primary-color="theme.themeColor"
|
||||
:closable="item.name !== tab.homeTab.name"
|
||||
:closable="!(item.name === tab.homeTab.name || item.meta.affix)"
|
||||
:dark-mode="theme.darkMode"
|
||||
:class="{ '!mr-0': isChromeMode && index === tab.tabs.length - 1, 'mr-10px': !isChromeMode }"
|
||||
@click="tab.handleClickTab(item.fullPath)"
|
||||
@close="tab.removeTab(item.fullPath)"
|
||||
@contextmenu="handleContextMenu($event, item.fullPath)"
|
||||
@contextmenu="handleContextMenu($event, item.fullPath, item.meta.affix)"
|
||||
>
|
||||
<svg-icon
|
||||
:icon="item.meta.icon"
|
||||
@ -24,6 +24,7 @@
|
||||
<context-menu
|
||||
:visible="dropdown.visible"
|
||||
:current-path="dropdown.currentPath"
|
||||
:affix="dropdown.affix"
|
||||
:x="dropdown.x"
|
||||
:y="dropdown.y"
|
||||
@update:visible="handleDropdownVisible"
|
||||
@ -66,6 +67,7 @@ async function getActiveTabClientX() {
|
||||
|
||||
const dropdown = reactive({
|
||||
visible: false,
|
||||
affix: false,
|
||||
x: 0,
|
||||
y: 0,
|
||||
currentPath: ''
|
||||
@ -76,8 +78,8 @@ function showDropdown() {
|
||||
function hideDropdown() {
|
||||
dropdown.visible = false;
|
||||
}
|
||||
function setDropdown(x: number, y: number, currentPath: string) {
|
||||
Object.assign(dropdown, { x, y, currentPath });
|
||||
function setDropdown(x: number, y: number, currentPath: string, affix?: boolean) {
|
||||
Object.assign(dropdown, { x, y, currentPath, affix });
|
||||
}
|
||||
|
||||
let isClickContextMenu = false;
|
||||
@ -89,7 +91,7 @@ function handleDropdownVisible(visible: boolean) {
|
||||
}
|
||||
|
||||
/** 点击右键菜单 */
|
||||
async function handleContextMenu(e: MouseEvent, fullPath: string) {
|
||||
async function handleContextMenu(e: MouseEvent, fullPath: string, affix?: boolean) {
|
||||
e.preventDefault();
|
||||
|
||||
const { clientX, clientY } = e;
|
||||
@ -101,7 +103,7 @@ async function handleContextMenu(e: MouseEvent, fullPath: string) {
|
||||
hideDropdown();
|
||||
|
||||
setTimeout(() => {
|
||||
setDropdown(clientX, clientY, fullPath);
|
||||
setDropdown(clientX, clientY, fullPath, affix);
|
||||
showDropdown();
|
||||
isClickContextMenu = false;
|
||||
}, DURATION);
|
||||
|
@ -61,6 +61,9 @@
|
||||
<setting-menu label="固定底部">
|
||||
<n-switch :value="theme.footer.fixed" @update:value="theme.setFooterIsFixed" />
|
||||
</setting-menu>
|
||||
<setting-menu label="显示底部">
|
||||
<n-switch :value="theme.footer.visible" @update:value="theme.setFooterVisible" />
|
||||
</setting-menu>
|
||||
</n-space>
|
||||
</template>
|
||||
|
||||
|
@ -110,7 +110,8 @@
|
||||
},
|
||||
"footer": {
|
||||
"fixed": false,
|
||||
"height": 48
|
||||
"height": 48,
|
||||
"visible": true
|
||||
},
|
||||
"page": {
|
||||
"animate": true,
|
||||
|
@ -88,7 +88,8 @@ const defaultThemeSetting: Theme.Setting = {
|
||||
},
|
||||
footer: {
|
||||
fixed: false,
|
||||
height: 48
|
||||
height: 48,
|
||||
visible: true
|
||||
},
|
||||
page: {
|
||||
animate: true,
|
||||
|
@ -149,6 +149,10 @@ export const useThemeStore = defineStore('theme-store', {
|
||||
setFooterHeight(height: number) {
|
||||
this.footer.height = height;
|
||||
},
|
||||
/** 设置底部是否显示 */
|
||||
setFooterVisible(isVisible: boolean) {
|
||||
this.footer.visible = isVisible;
|
||||
},
|
||||
/** 设置切换页面时是否过渡动画 */
|
||||
setPageIsAnimate(animate: boolean) {
|
||||
this.page.animate = animate;
|
||||
|
2
src/typings/route.d.ts
vendored
2
src/typings/route.d.ts
vendored
@ -60,6 +60,8 @@ declare namespace AuthRoute {
|
||||
activeMenu?: RouteKey;
|
||||
/** 表示是否是多级路由的中间级路由(用于转换路由数据时筛选多级路由的标识,定义路由时不用填写) */
|
||||
multi?: boolean;
|
||||
/** 是否固定在tab卡不可关闭 */
|
||||
affix?: boolean;
|
||||
}
|
||||
|
||||
type Route<K extends AllRouteKey = AllRouteKey> = K extends AllRouteKey
|
||||
|
2
src/typings/system.d.ts
vendored
2
src/typings/system.d.ts
vendored
@ -236,6 +236,8 @@ declare namespace Theme {
|
||||
fixed: boolean;
|
||||
/** 底部高度 */
|
||||
height: number;
|
||||
/* 底部是否可见 */
|
||||
visible: boolean;
|
||||
}
|
||||
|
||||
/** 页面样式 */
|
||||
|
Loading…
Reference in New Issue
Block a user