refactor(components): blankLayout引入GlobalContent

This commit is contained in:
Soybean
2021-11-24 23:44:39 +08:00
parent 32aa5ee75a
commit 1ffb75afce
63 changed files with 64 additions and 50 deletions

View File

@ -0,0 +1,14 @@
<template>
<hover-container class="w-40px h-full" tooltip-content="全屏" @click="toggle">
<icon-gridicons-fullscreen-exit v-if="isFullscreen" class="text-16px" />
<icon-gridicons-fullscreen v-else class="text-16px" />
</hover-container>
</template>
<script lang="ts" setup>
import { useFullscreen } from '@vueuse/core';
import { HoverContainer } from '@/components';
const { isFullscreen, toggle } = useFullscreen();
</script>
<style scoped></style>

View File

@ -0,0 +1,12 @@
<template>
<hover-container tooltip-content="github" class="w-40px h-full">
<a href="https://github.com/honghuangdc/soybean-admin" target="_blank" class="flex-center">
<icon-mdi-github class="text-20px text-[#666]" />
</a>
</hover-container>
</template>
<script lang="ts" setup>
import { HoverContainer } from '@/components';
</script>
<style scoped></style>

View File

@ -0,0 +1,91 @@
<template>
<n-breadcrumb class="px-12px">
<template v-for="breadcrumb in breadcrumbList" :key="breadcrumb.key">
<n-breadcrumb-item>
<n-dropdown v-if="breadcrumb.hasChildren" :options="breadcrumb.children" @select="dropdownSelect">
<span>
<Icon
v-if="theme.crumbsStyle.showIcon && breadcrumb.iconName"
:icon="breadcrumb.iconName"
class="inline-block mr-4px text-16px"
/>
<span>{{ breadcrumb.label }}</span>
</span>
</n-dropdown>
<template v-else>
<Icon
v-if="theme.crumbsStyle.showIcon && breadcrumb.iconName"
:icon="breadcrumb.iconName"
class="inline-block mr-4px text-16px"
/>
<span>{{ breadcrumb.label }}</span>
</template>
</n-breadcrumb-item>
</template>
</n-breadcrumb>
</template>
<script lang="ts" setup>
import { computed } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import type { RouteLocationMatched } from 'vue-router';
import { NBreadcrumb, NBreadcrumbItem, NDropdown } from 'naive-ui';
import type { DropdownOption } from 'naive-ui';
import { Icon } from '@iconify/vue';
import { routePath } from '@/router';
import { useThemeStore } from '@/store';
import type { RouteKey } from '@/interface';
type Breadcrumb = DropdownOption & {
key: string;
label: string;
disabled: boolean;
routeName: RouteKey;
hasChildren: boolean;
iconName?: string;
children?: Breadcrumb[];
};
const theme = useThemeStore();
const route = useRoute();
const router = useRouter();
const breadcrumbList = computed<Breadcrumb[]>(() => generateBreadcrumb());
function generateBreadcrumb() {
const { matched } = route;
return recursionBreadcrumb(matched);
}
/** 递归匹配路由获取面包屑数据 */
function recursionBreadcrumb(routeMatched: RouteLocationMatched[]) {
const list: Breadcrumb[] = [];
routeMatched.forEach(item => {
if (!item.meta?.isNotMenu) {
const routeName = item.name as RouteKey;
const breadcrumItem: Breadcrumb = {
key: routeName,
label: (item.meta?.title as string) || '',
disabled: item.path === routePath('root'),
routeName,
hasChildren: false
};
if (item.meta?.icon) {
breadcrumItem.iconName = item.meta.icon as string;
}
if (item.children && item.children.length) {
breadcrumItem.hasChildren = true;
breadcrumItem.children = recursionBreadcrumb(item.children as RouteLocationMatched[]);
}
list.push(breadcrumItem);
}
});
return list;
}
function dropdownSelect(optionKey: string) {
const key = optionKey as RouteKey;
router.push({ name: key });
}
</script>
<style scoped></style>

View File

@ -0,0 +1,27 @@
<template>
<n-menu :value="activeKey" mode="horizontal" :options="menus" @update:value="handleUpdateMenu" />
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import type { MenuOption } from 'naive-ui';
import { NMenu } from 'naive-ui';
import { menus } from '@/router';
import { GlobalMenuOption } from '@/interface';
const router = useRouter();
const route = useRoute();
const activeKey = computed(() => getActiveKey());
function getActiveKey() {
return route.name as string;
}
function handleUpdateMenu(key: string, item: MenuOption) {
const menuItem = item as GlobalMenuOption;
router.push(menuItem.routePath);
}
</script>
<style scoped></style>

View File

@ -0,0 +1,15 @@
<template>
<hover-container class="w-40px h-full" @click="toggleMenu">
<icon-line-md-menu-unfold-left v-if="app.menu.collapsed" class="text-16px" />
<icon-line-md-menu-fold-left v-else class="text-16px" />
</hover-container>
</template>
<script lang="ts" setup>
import { useAppStore } from '@/store';
import { HoverContainer } from '@/components';
const app = useAppStore();
const { toggleMenu } = useAppStore();
</script>
<style scoped></style>

View File

@ -0,0 +1,13 @@
<template>
<hover-container class="w-40px h-full" tooltip-content="项目配置" placement="bottom-end" @click="openSettingDrawer">
<icon-mdi-light-cog class="text-16px" />
</hover-container>
</template>
<script lang="ts" setup>
import { useAppStore } from '@/store';
import { HoverContainer } from '@/components';
const { openSettingDrawer } = useAppStore();
</script>
<style scoped></style>

View File

@ -0,0 +1,15 @@
<template>
<hover-container class="w-40px" content-class="hover:text-primary" tooltip-content="主题模式" @click="toggleDarkMode">
<icon-mdi-moon-waning-crescent v-if="theme.darkMode" class="text-14px" />
<icon-mdi-white-balance-sunny v-else class="text-14px" />
</hover-container>
</template>
<script lang="ts" setup>
import { HoverContainer } from '@/components';
import { useThemeStore } from '@/store';
const theme = useThemeStore();
const { toggleDarkMode } = useThemeStore();
</script>
<style scoped></style>

View File

@ -0,0 +1,55 @@
<template>
<n-dropdown :options="options" @select="handleDropdown">
<hover-container class="px-12px">
<img :src="avatar" class="w-32px h-32px" />
<span class="pl-8px text-16px font-medium">Soybean</span>
</hover-container>
</n-dropdown>
</template>
<script lang="ts" setup>
import { NDropdown, useDialog } from 'naive-ui';
import { HoverContainer } from '@/components';
import { useRouterPush } from '@/composables';
import { iconifyRender, resetAuthStorage } from '@/utils';
import avatar from '@/assets/svg/avatar/avatar01.svg';
type DropdownKey = 'user-center' | 'logout';
const { toLogin } = useRouterPush();
const dialog = useDialog();
const options = [
{
label: '用户中心',
key: 'user-center',
icon: iconifyRender('carbon:user-avatar')
},
{
type: 'divider',
key: 'divider'
},
{
label: '退出登录',
key: 'logout',
icon: iconifyRender('carbon:logout')
}
];
function handleDropdown(optionKey: string) {
const key = optionKey as DropdownKey;
if (key === 'logout') {
dialog.info({
title: '提示',
content: '您确定要退出登录吗?',
positiveText: '确定',
negativeText: '取消',
onPositiveClick: () => {
resetAuthStorage();
toLogin('pwd-login', 'current');
}
});
}
}
</script>
<style scoped></style>

View File

@ -0,0 +1,19 @@
import HeaderMenu from './HeaderMenu.vue';
import GlobalBreadcrumb from './GlobalBreadcrumb.vue';
import UserAvatar from './UserAvatar.vue';
import MenuCollapse from './MenuCollapse.vue';
import ThemeMode from './ThemeMode.vue';
import FullScreen from './FullScreen.vue';
import SettingDrawerButton from './SettingDrawerButton.vue';
import GithubSite from './GithubSite.vue';
export {
HeaderMenu,
GlobalBreadcrumb,
UserAvatar,
MenuCollapse,
ThemeMode,
FullScreen,
SettingDrawerButton,
GithubSite
};