feat: 导航top

Former-commit-id: cc721dfba11eb53d8dc6a082016ef4832d21a516
This commit is contained in:
april
2023-08-11 18:35:18 +08:00
parent b7c3c75906
commit 2478224cff
12 changed files with 332 additions and 278 deletions

View File

@@ -0,0 +1,120 @@
<template>
<!-- 导航栏设置(窄屏隐藏)-->
<div v-if="device !== 'mobile'" class="setting-container">
<!--全屏 -->
<div class="setting-item" @click="toggle">
<svg-icon :icon-class="isFullscreen ? 'exit-fullscreen' : 'fullscreen'" />
</div>
<!-- 布局大小 -->
<el-tooltip content="布局大小" effect="dark" placement="bottom">
<size-select class="setting-item" />
</el-tooltip>
<!--语言选择-->
<lang-select class="setting-item" />
</div>
<!-- 用户头像 -->
<el-dropdown trigger="click">
<div class="avatar-container">
<img :src="userStore.avatar + '?imageView2/1/w/80/h/80'" />
<i-ep-caret-bottom class="w-3 h-3" />
</div>
<template #dropdown>
<el-dropdown-menu>
<router-link to="/">
<el-dropdown-item>{{ $t("navbar.dashboard") }}</el-dropdown-item>
</router-link>
<a
target="_blank"
href="https://github.com/youlaitech/vue3-element-admin"
>
<el-dropdown-item>Github</el-dropdown-item>
</a>
<a target="_blank" href="https://gitee.com/haoxr">
<el-dropdown-item>{{ $t("navbar.gitee") }}</el-dropdown-item>
</a>
<a target="_blank" href="https://juejin.cn/post/7228990409909108793">
<el-dropdown-item>{{ $t("navbar.document") }}</el-dropdown-item>
</a>
<el-dropdown-item divided @click="logout">
{{ $t("navbar.logout") }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
<script setup lang="ts" name="navRight">
import { storeToRefs } from "pinia";
import { useRoute, useRouter } from "vue-router";
import { useAppStore } from "@/store/modules/app";
import { useTagsViewStore } from "@/store/modules/tagsView";
import { useUserStore } from "@/store/modules/user";
const appStore = useAppStore();
const tagsViewStore = useTagsViewStore();
const userStore = useUserStore();
const route = useRoute();
const router = useRouter();
const { device } = storeToRefs(appStore); // 设备类型desktop-宽屏设备 || mobile-窄屏设备
/**
* vueUse 全屏
*/
const { isFullscreen, toggle } = useFullscreen();
/**
* 注销
*/
function logout() {
ElMessageBox.confirm("确定注销并退出系统吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(() => {
userStore
.logout()
.then(() => {
tagsViewStore.delAllViews();
})
.then(() => {
router.push(`/login?redirect=${route.fullPath}`);
});
});
}
</script>
<style lang="scss" scoped>
.setting-container {
display: flex;
align-items: center;
.setting-item {
display: inline-block;
width: 30px;
height: 50px;
line-height: 50px;
color: #5a5e66;
text-align: center;
cursor: pointer;
&:hover {
background: rgb(249 250 251 / 100%);
}
}
}
.avatar-container {
display: flex;
align-items: center;
justify-items: center;
margin: 0 5px;
cursor: pointer;
img {
width: 40px;
height: 40px;
border-radius: 5px;
}
}
</style>

View File

@@ -0,0 +1,42 @@
<script setup lang="ts">
import { useAppStore } from "@/store/modules/app";
const appStore = useAppStore();
/**
* 左侧菜单栏显示/隐藏
*/
function toggleSideBar() {
appStore.toggleSidebar(true);
}
</script>
<template>
<!-- 顶部导航栏 -->
<div class="navbar">
<!-- 左侧面包屑 -->
<div class="flex">
<hamburger
:is-active="appStore.sidebar.opened"
@toggle-click="toggleSideBar"
/>
<breadcrumb />
</div>
<!-- 右侧导航设置 -->
<div class="flex">
<NavRight />
</div>
</div>
</template>
<style lang="scss" scoped>
.navbar {
display: flex;
align-items: center;
justify-content: space-between;
height: 50px;
background-color: #fff;
box-shadow: 0 0 1px #0003;
}
</style>

View File

@@ -1,158 +0,0 @@
<script setup lang="ts">
import { storeToRefs } from "pinia";
import { useRoute, useRouter } from "vue-router";
import { useAppStore } from "@/store/modules/app";
import { useTagsViewStore } from "@/store/modules/tagsView";
import { useUserStore } from "@/store/modules/user";
const appStore = useAppStore();
const tagsViewStore = useTagsViewStore();
const userStore = useUserStore();
const route = useRoute();
const router = useRouter();
const { device } = storeToRefs(appStore); // 设备类型desktop-宽屏设备 || mobile-窄屏设备
/**
* 左侧菜单栏显示/隐藏
*/
function toggleSideBar() {
appStore.toggleSidebar(true);
}
/**
* vueUse 全屏
*/
const { isFullscreen, toggle } = useFullscreen();
/**
* 注销
*/
function logout() {
ElMessageBox.confirm("确定注销并退出系统吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(() => {
userStore
.logout()
.then(() => {
tagsViewStore.delAllViews();
})
.then(() => {
router.push(`/login?redirect=${route.fullPath}`);
});
});
}
</script>
<template>
<!-- 顶部导航栏 -->
<div class="navbar">
<!-- 左侧面包屑 -->
<div class="flex">
<hamburger
:is-active="appStore.sidebar.opened"
@toggle-click="toggleSideBar"
/>
<breadcrumb />
</div>
<!-- 右侧导航设置 -->
<div class="flex">
<!-- 导航栏设置(窄屏隐藏)-->
<div v-if="device !== 'mobile'" class="setting-container">
<!--全屏 -->
<div class="setting-item" @click="toggle">
<svg-icon
:icon-class="isFullscreen ? 'exit-fullscreen' : 'fullscreen'"
/>
</div>
<!-- 布局大小 -->
<el-tooltip content="布局大小" effect="dark" placement="bottom">
<size-select class="setting-item" />
</el-tooltip>
<!--语言选择-->
<lang-select class="setting-item" />
</div>
<!-- 用户头像 -->
<el-dropdown trigger="click">
<div class="avatar-container">
<img :src="userStore.avatar + '?imageView2/1/w/80/h/80'" />
<i-ep-caret-bottom class="w-3 h-3" />
</div>
<template #dropdown>
<el-dropdown-menu>
<router-link to="/">
<el-dropdown-item>{{ $t("navbar.dashboard") }}</el-dropdown-item>
</router-link>
<a
target="_blank"
href="https://github.com/youlaitech/vue3-element-admin"
>
<el-dropdown-item>Github</el-dropdown-item>
</a>
<a target="_blank" href="https://gitee.com/haoxr">
<el-dropdown-item>{{ $t("navbar.gitee") }}</el-dropdown-item>
</a>
<a
target="_blank"
href="https://juejin.cn/post/7228990409909108793"
>
<el-dropdown-item>{{ $t("navbar.document") }}</el-dropdown-item>
</a>
<el-dropdown-item divided @click="logout">
{{ $t("navbar.logout") }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
</template>
<style lang="scss" scoped>
.navbar {
display: flex;
align-items: center;
justify-content: space-between;
height: 50px;
background-color: #fff;
box-shadow: 0 0 1px #0003;
.setting-container {
display: flex;
align-items: center;
.setting-item {
display: inline-block;
width: 30px;
height: 50px;
line-height: 50px;
color: #5a5e66;
text-align: center;
cursor: pointer;
&:hover {
background: rgb(249 250 251 / 100%);
}
}
}
.avatar-container {
display: flex;
align-items: center;
justify-items: center;
margin: 0 5px;
cursor: pointer;
img {
width: 40px;
height: 40px;
border-radius: 5px;
}
}
}
</style>

View File

@@ -34,7 +34,7 @@ const themeColors = ref<string[]>([
*/
function changeThemeColor(color: string) {
document.documentElement.style.setProperty("--el-color-primary", color);
settingsStore.changeSetting({ key: "layout", value: color });
// settingsStore.changeSetting({ key: "layout", value: color });
}
onMounted(() => {
@@ -94,7 +94,7 @@ onMounted(() => {
<li
:class="
'layout-item layout-left ' +
(settingsStore.layout == 'left' ? 'is-active' : '')
(settingsStore.layout === 'left' ? 'is-active' : '')
"
@click="changeLayout('left')"
>
@@ -106,7 +106,7 @@ onMounted(() => {
<li
:class="
'layout-item layout-top ' +
(settingsStore.layout == 'top' ? 'is-active' : '')
(settingsStore.layout === 'top' ? 'is-active' : '')
"
@click="changeLayout('top')"
>
@@ -118,7 +118,7 @@ onMounted(() => {
<li
:class="
'layout-item layout-mix ' +
(settingsStore.layout == 'mix' ? 'is-active' : '')
(settingsStore.layout === 'mix' ? 'is-active' : '')
"
@click="changeLayout('mix')"
>

View File

@@ -14,7 +14,9 @@ const logo = ref(new URL(`../../../assets/logo.png`, import.meta.url).href);
</script>
<template>
<div class="w-full h-[50px] bg-gray-800 dark:bg-[var(--el-bg-color-overlay)]">
<div
class="w-full h-[50px] bg-gray-800 dark:bg-[var(--el-bg-color-overlay)] logo-wrap"
>
<transition name="sidebarLogoFade">
<router-link
v-if="collapse"

View File

@@ -14,21 +14,32 @@ const permissionStore = usePermissionStore();
const appStore = useAppStore();
const currRoute = useRoute();
const { sidebarLogo } = storeToRefs(settingsStore);
const layout = computed(() => settingsStore.layout);
const showContent = ref(true);
watch(
() => layout.value,
() => {
showContent.value = false;
nextTick(() => {
showContent.value = true;
});
}
);
</script>
<template>
<div :class="{ 'has-logo': sidebarLogo }">
<div :class="{ 'has-logo': sidebarLogo }" class="menu-wrap">
<logo v-if="sidebarLogo" :collapse="!appStore.sidebar.opened" />
<el-scrollbar>
<el-scrollbar v-if="showContent">
<el-menu
:default-active="currRoute.path"
:default-active="layout === 'top' ? '-' : currRoute.path"
:collapse="!appStore.sidebar.opened"
:background-color="variables.menuBg"
:text-color="variables.menuText"
:active-text-color="variables.menuActiveText"
:unique-opened="false"
:collapse-transition="false"
mode="vertical"
:mode="layout === 'top' ? 'horizontal' : 'vertical'"
>
<sidebar-item
v-for="route in permissionStore.routes"
@@ -39,5 +50,19 @@ const { sidebarLogo } = storeToRefs(settingsStore);
/>
</el-menu>
</el-scrollbar>
<NavRight v-if="layout === 'top'" />
</div>
</template>
<style lang="scss" scoped>
:deep(.setting-container) {
.setting-item {
color: #fff;
.svg-icon {
margin-right: 0px;
}
&:hover {
color: var(--el-color-primary);
}
}
}
</style>

View File

@@ -1,4 +1,4 @@
export { default as Navbar } from "./Navbar.vue";
export { default as Navbar } from "./Navbar/index.vue";
export { default as AppMain } from "./AppMain.vue";
export { default as Settings } from "./Settings/index.vue";
export { default as TagsView } from "./TagsView/index.vue";