mirror of
https://github.com/jekip/naive-ui-admin.git
synced 2026-02-04 13:42:27 +08:00
更新侧边导航栏移动端显示为modal显示。
This commit is contained in:
@@ -15,7 +15,7 @@ VITE_DROP_CONSOLE = true
|
|||||||
|
|
||||||
# 跨域代理,可以配置多个,请注意不要换行
|
# 跨域代理,可以配置多个,请注意不要换行
|
||||||
#VITE_PROXY = [["/appApi","http://localhost:8001"],["/upload","http://localhost:8001/upload"]]
|
#VITE_PROXY = [["/appApi","http://localhost:8001"],["/upload","http://localhost:8001/upload"]]
|
||||||
# VITE_PROXY=[["/api","https://naive-ui-admin"]]
|
VITE_PROXY=[["/api","https://naive-ui-admin"]]
|
||||||
|
|
||||||
# API 接口地址
|
# API 接口地址
|
||||||
VITE_GLOB_API_URL =
|
VITE_GLOB_API_URL =
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<n-layout class="layout" :position="fixedMenu" has-sider>
|
<n-layout class="layout" :position="fixedMenu" has-sider>
|
||||||
<n-layout-sider
|
<n-layout-sider
|
||||||
v-if="isMixMenuNoneSub && (navMode === 'vertical' || navMode === 'horizontal-mix')"
|
v-if="!isMobile && isMixMenuNoneSub && (navMode === 'vertical' || navMode === 'horizontal-mix')"
|
||||||
show-trigger="bar"
|
show-trigger="bar"
|
||||||
@collapse="collapsed = true"
|
@collapse="collapsed = true"
|
||||||
:position="fixedMenu"
|
:position="fixedMenu"
|
||||||
@@ -18,6 +18,16 @@
|
|||||||
<AsideMenu v-model:collapsed="collapsed" v-model:location="getMenuLocation" />
|
<AsideMenu v-model:collapsed="collapsed" v-model:location="getMenuLocation" />
|
||||||
</n-layout-sider>
|
</n-layout-sider>
|
||||||
|
|
||||||
|
<n-drawer
|
||||||
|
v-model:show="showSideDrawder"
|
||||||
|
:width="menuWidth"
|
||||||
|
:placement="'left'"
|
||||||
|
class="layout-side-drawer"
|
||||||
|
>
|
||||||
|
<Logo :collapsed="collapsed" />
|
||||||
|
<AsideMenu />
|
||||||
|
</n-drawer>
|
||||||
|
|
||||||
<n-layout :inverted="inverted">
|
<n-layout :inverted="inverted">
|
||||||
<n-layout-header :inverted="getHeaderInverted" :position="fixedHeader">
|
<n-layout-header :inverted="getHeaderInverted" :position="fixedHeader">
|
||||||
<PageHeader v-model:collapsed="collapsed" :inverted="inverted" />
|
<PageHeader v-model:collapsed="collapsed" :inverted="inverted" />
|
||||||
@@ -57,170 +67,206 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, unref, computed, onMounted } from 'vue';
|
import { ref, unref, computed, onMounted } from 'vue';
|
||||||
import { Logo } from './components/Logo';
|
import { Logo } from './components/Logo';
|
||||||
import { TabsView } from './components/TagsView';
|
import { TabsView } from './components/TagsView';
|
||||||
import { MainView } from './components/Main';
|
import { MainView } from './components/Main';
|
||||||
import { AsideMenu } from './components/Menu';
|
import { AsideMenu } from './components/Menu';
|
||||||
import { PageHeader } from './components/Header';
|
import { PageHeader } from './components/Header';
|
||||||
import { useProjectSetting } from '@/hooks/setting/useProjectSetting';
|
import { useProjectSetting } from '@/hooks/setting/useProjectSetting';
|
||||||
import { useDesignSetting } from '@/hooks/setting/useDesignSetting';
|
import { useDesignSetting } from '@/hooks/setting/useDesignSetting';
|
||||||
import { useLoadingBar } from 'naive-ui';
|
import { useLoadingBar } from 'naive-ui';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useProjectSettingStore } from '@/store/modules/projectSetting';
|
import { useProjectSettingStore } from '@/store/modules/projectSetting';
|
||||||
|
|
||||||
const { getDarkTheme } = useDesignSetting();
|
const { getDarkTheme } = useDesignSetting();
|
||||||
const {
|
const {
|
||||||
getShowFooter,
|
getShowFooter,
|
||||||
getNavMode,
|
getNavMode,
|
||||||
getNavTheme,
|
getNavTheme,
|
||||||
getHeaderSetting,
|
getHeaderSetting,
|
||||||
getMenuSetting,
|
getMenuSetting,
|
||||||
getMultiTabsSetting,
|
getMultiTabsSetting,
|
||||||
} = useProjectSetting();
|
} = useProjectSetting();
|
||||||
|
|
||||||
const settingStore = useProjectSettingStore();
|
const settingStore = useProjectSettingStore();
|
||||||
|
|
||||||
const navMode = getNavMode;
|
const navMode = getNavMode;
|
||||||
|
|
||||||
const collapsed = ref<boolean>(false);
|
const collapsed = ref<boolean>(false);
|
||||||
|
|
||||||
const fixedHeader = computed(() => {
|
const { mobileWidth, menuWidth } = unref(getMenuSetting);
|
||||||
const { fixed } = unref(getHeaderSetting);
|
|
||||||
return fixed ? 'absolute' : 'static';
|
|
||||||
});
|
|
||||||
|
|
||||||
const isMixMenuNoneSub = computed(() => {
|
const isMobile = ref<boolean>(false);
|
||||||
const mixMenu = settingStore.menuSetting.mixMenu;
|
|
||||||
const currentRoute = useRoute();
|
|
||||||
if (unref(navMode) != 'horizontal-mix') return true;
|
|
||||||
if (unref(navMode) === 'horizontal-mix' && mixMenu && currentRoute.meta.isRoot) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
const fixedMenu = computed(() => {
|
const fixedHeader = computed(() => {
|
||||||
const { fixed } = unref(getHeaderSetting);
|
const { fixed } = unref(getHeaderSetting);
|
||||||
return fixed ? 'absolute' : 'static';
|
return fixed ? 'absolute' : 'static';
|
||||||
});
|
});
|
||||||
|
|
||||||
const isMultiTabs = computed(() => {
|
const isMixMenuNoneSub = computed(() => {
|
||||||
return unref(getMultiTabsSetting).show;
|
const mixMenu = settingStore.menuSetting.mixMenu;
|
||||||
});
|
const currentRoute = useRoute();
|
||||||
|
if (unref(navMode) != 'horizontal-mix') return true;
|
||||||
|
if (unref(navMode) === 'horizontal-mix' && mixMenu && currentRoute.meta.isRoot) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
const fixedMulti = computed(() => {
|
const fixedMenu = computed(() => {
|
||||||
return unref(getMultiTabsSetting).fixed;
|
const { fixed } = unref(getHeaderSetting);
|
||||||
});
|
return fixed ? 'absolute' : 'static';
|
||||||
|
});
|
||||||
|
|
||||||
const inverted = computed(() => {
|
const isMultiTabs = computed(() => {
|
||||||
return ['dark', 'header-dark'].includes(unref(getNavTheme));
|
return unref(getMultiTabsSetting).show;
|
||||||
});
|
});
|
||||||
|
|
||||||
const getHeaderInverted = computed(() => {
|
const fixedMulti = computed(() => {
|
||||||
const navTheme = unref(getNavTheme);
|
return unref(getMultiTabsSetting).fixed;
|
||||||
return ['light', 'header-dark'].includes(navTheme) ? unref(inverted) : !unref(inverted);
|
});
|
||||||
});
|
|
||||||
|
|
||||||
const leftMenuWidth = computed(() => {
|
const inverted = computed(() => {
|
||||||
const { minMenuWidth, menuWidth } = unref(getMenuSetting);
|
return ['dark', 'header-dark'].includes(unref(getNavTheme));
|
||||||
return collapsed.value ? minMenuWidth : menuWidth;
|
});
|
||||||
});
|
|
||||||
|
|
||||||
const getChangeStyle = computed(() => {
|
const getHeaderInverted = computed(() => {
|
||||||
const { minMenuWidth, menuWidth } = unref(getMenuSetting);
|
const navTheme = unref(getNavTheme);
|
||||||
return {
|
return ['light', 'header-dark'].includes(navTheme) ? unref(inverted) : !unref(inverted);
|
||||||
'padding-left': collapsed.value ? `${minMenuWidth}px` : `${menuWidth}px`,
|
});
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const getMenuLocation = computed(() => {
|
const leftMenuWidth = computed(() => {
|
||||||
return 'left';
|
const { minMenuWidth, menuWidth } = unref(getMenuSetting);
|
||||||
});
|
return collapsed.value ? minMenuWidth : menuWidth;
|
||||||
|
});
|
||||||
|
|
||||||
const watchWidth = () => {
|
const getChangeStyle = computed(() => {
|
||||||
const Width = document.body.clientWidth;
|
const { minMenuWidth, menuWidth } = unref(getMenuSetting);
|
||||||
if (Width <= 950) {
|
return {
|
||||||
collapsed.value = true;
|
'padding-left': collapsed.value ? `${minMenuWidth}px` : `${menuWidth}px`,
|
||||||
} else collapsed.value = false;
|
|
||||||
};
|
};
|
||||||
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
const getMenuLocation = computed(() => {
|
||||||
window.addEventListener('resize', watchWidth);
|
return 'left';
|
||||||
//挂载在 window 方便与在js中使用
|
});
|
||||||
window['$loading'] = useLoadingBar();
|
|
||||||
window['$loading'].finish();
|
// 控制显示或隐藏移动端侧边栏
|
||||||
});
|
const showSideDrawder = computed({
|
||||||
|
get: () => isMobile.value && collapsed.value,
|
||||||
|
set: (val) => (collapsed.value = val)
|
||||||
|
});
|
||||||
|
|
||||||
|
//判断是否触发移动端模式
|
||||||
|
const checkMobileMode = () => {
|
||||||
|
if (document.body.clientWidth <= mobileWidth) {
|
||||||
|
isMobile.value = true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
isMobile.value = false;
|
||||||
|
}
|
||||||
|
collapsed.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const watchWidth = () => {
|
||||||
|
const Width = document.body.clientWidth;
|
||||||
|
if (Width <= 950) {
|
||||||
|
collapsed.value = true;
|
||||||
|
} else collapsed.value = false;
|
||||||
|
|
||||||
|
checkMobileMode();
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
checkMobileMode();
|
||||||
|
window.addEventListener('resize', watchWidth);
|
||||||
|
//挂载在 window 方便与在js中使用
|
||||||
|
window['$loading'] = useLoadingBar();
|
||||||
|
window['$loading'].finish();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less">
|
||||||
.layout {
|
.layout-side-drawer {
|
||||||
display: flex;
|
background-color: rgb(0, 20, 40);
|
||||||
flex-direction: row;
|
.layout-sider {
|
||||||
flex: auto;
|
min-height: 100vh;
|
||||||
|
box-shadow: 2px 0 8px 0 rgb(29 35 41 / 5%);
|
||||||
&-default-background {
|
|
||||||
background: #f5f7f9;
|
|
||||||
}
|
|
||||||
|
|
||||||
.layout-sider {
|
|
||||||
min-height: 100vh;
|
|
||||||
box-shadow: 2px 0 8px 0 rgb(29 35 41 / 5%);
|
|
||||||
position: relative;
|
|
||||||
z-index: 13;
|
|
||||||
transition: all 0.2s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.layout-sider-fix {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ant-layout {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.layout-right-fix {
|
|
||||||
overflow-x: hidden;
|
|
||||||
padding-left: 200px;
|
|
||||||
min-height: 100vh;
|
|
||||||
transition: all 0.2s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.layout-content {
|
|
||||||
flex: auto;
|
|
||||||
min-height: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
.n-layout-header.n-layout-header--absolute-positioned {
|
|
||||||
z-index: 11;
|
|
||||||
}
|
|
||||||
|
|
||||||
.n-layout-footer {
|
|
||||||
background: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.layout-content-main {
|
|
||||||
margin: 0 10px 10px;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
padding-top: 64px;
|
z-index: 13;
|
||||||
}
|
transition: all 0.2s ease-in-out;
|
||||||
|
|
||||||
.layout-content-main-fix {
|
|
||||||
padding-top: 64px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fluid-header {
|
|
||||||
padding-top: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-view-fix {
|
|
||||||
padding-top: 44px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.noMultiTabs {
|
|
||||||
padding-top: 0;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.layout {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex: auto;
|
||||||
|
|
||||||
|
&-default-background {
|
||||||
|
background: #f5f7f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout-sider {
|
||||||
|
min-height: 100vh;
|
||||||
|
box-shadow: 2px 0 8px 0 rgb(29 35 41 / 5%);
|
||||||
|
position: relative;
|
||||||
|
z-index: 13;
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout-sider-fix {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-layout {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout-right-fix {
|
||||||
|
overflow-x: hidden;
|
||||||
|
padding-left: 200px;
|
||||||
|
min-height: 100vh;
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout-content {
|
||||||
|
flex: auto;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.n-layout-header.n-layout-header--absolute-positioned {
|
||||||
|
z-index: 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
.n-layout-footer {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout-content-main {
|
||||||
|
margin: 0 10px 10px;
|
||||||
|
position: relative;
|
||||||
|
padding-top: 64px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout-content-main-fix {
|
||||||
|
padding-top: 64px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fluid-header {
|
||||||
|
padding-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-view-fix {
|
||||||
|
padding-top: 44px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.noMultiTabs {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ const setting = {
|
|||||||
fixed: true,
|
fixed: true,
|
||||||
//分割菜单
|
//分割菜单
|
||||||
mixMenu: false,
|
mixMenu: false,
|
||||||
|
//触发移动端侧边栏的宽度
|
||||||
|
mobileWidth: 800
|
||||||
},
|
},
|
||||||
//面包屑
|
//面包屑
|
||||||
crumbsSetting: {
|
crumbsSetting: {
|
||||||
|
|||||||
1
types/config.d.ts
vendored
1
types/config.d.ts
vendored
@@ -33,6 +33,7 @@ export interface ImenuSetting {
|
|||||||
fixed: boolean;
|
fixed: boolean;
|
||||||
mixMenu: boolean;
|
mixMenu: boolean;
|
||||||
collapsed: boolean;
|
collapsed: boolean;
|
||||||
|
mobileWidth: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IcrumbsSetting {
|
export interface IcrumbsSetting {
|
||||||
|
|||||||
Reference in New Issue
Block a user