refactor(projects): 路由声明重构,添加composables,BaseLayout进行中,文件夹规范

This commit is contained in:
Soybean
2021-11-19 01:33:36 +08:00
parent 1c5fdca596
commit 1e84d13d54
75 changed files with 668 additions and 565 deletions

View File

@ -1,11 +1,34 @@
<template>
<div>
<div class="flex">
<h3>horizontal</h3>
</div>
<router-view />
</div>
<n-layout class="h-full">
<n-layout-content
:native-scrollbar="false"
:content-style="{ height: routeProps.fullPage ? '100%' : 'auto' }"
class="bg-[#f6f9f8] dark:bg-deep-dark"
>
<n-layout-header :inverted="headerInverted" :position="headerPosition" class="z-11">
<global-header :show-logo="true" :show-menu-collape="false" :show-menu="true" class="relative z-2" />
<global-tab v-if="theme.multiTabStyle.visible" />
</n-layout-header>
<header-placeholder />
<global-content />
<global-footer />
</n-layout-content>
</n-layout>
</template>
<script setup lang="ts"></script>
<style scoped></style>
<script setup lang="ts">
import { NLayout, NLayoutContent, NLayoutHeader } from 'naive-ui';
import { useThemeStore } from '@/store';
import { useRouteProps, useLayoutConfig } from '@/composables';
import { GlobalHeader, GlobalContent, GlobalFooter, GlobalTab, HeaderPlaceholder } from '../common';
const theme = useThemeStore();
const routeProps = useRouteProps();
const { headerInverted, headerPosition } = useLayoutConfig();
</script>
<style scoped>
.global-sider {
box-shadow: 2px 0 8px 0 rgb(29 35 41 / 5%);
}
</style>

View File

@ -1,10 +1,5 @@
<template>
<div>
<div class="flex">
<h3>horizontal-mix</h3>
</div>
<router-view />
</div>
<div></div>
</template>
<script setup lang="ts"></script>

View File

@ -1,18 +1,18 @@
<template>
<n-layout :has-sider="true" class="h-full">
<n-layout-sider
class="global-sider z-12"
:inverted="inverted"
class="global-sider z-12 transition-all duration-200 ease-in-out"
:inverted="siderInverted"
collapse-mode="width"
:collapsed="app.menu.collapsed"
:collapsed-width="theme.menuStyle.collapsedWidth"
:width="menuWidth"
:width="siderMenuWidth"
:native-scrollbar="false"
@collapse="handleMenuCollapse(true)"
@expand="handleMenuCollapse(false)"
>
<global-logo :show-title="!app.menu.collapsed" class="header-height absolute-lt w-full z-2" />
<global-menu class="header-padding" />
<global-logo :show-title="!app.menu.collapsed" class="absolute-lt z-2" />
<global-menu :style="{ paddingTop: headerHeight }" />
</n-layout-sider>
<n-layout-content
:native-scrollbar="false"
@ -20,15 +20,10 @@
class="bg-[#f6f9f8] dark:bg-deep-dark"
>
<n-layout-header :inverted="headerInverted" :position="headerPosition" class="z-11">
<global-header
:show-logo="false"
:show-menu-collape="true"
:show-menu="false"
class="header-height relative z-2"
/>
<global-tab v-if="theme.multiTabStyle.visible" class="tab-height" />
<global-header :show-logo="false" :show-menu-collape="true" :show-menu="false" class="relative z-2" />
<global-tab v-if="theme.multiTabStyle.visible" />
</n-layout-header>
<div v-if="theme.fixedHeaderAndTab" class="header-tab_height"></div>
<header-placeholder />
<global-content />
<global-footer />
</n-layout-content>
@ -36,66 +31,27 @@
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { NLayout, NLayoutSider, NLayoutContent, NLayoutHeader } from 'naive-ui';
import { useThemeStore, useAppStore } from '@/store';
import { useRouteProps } from '@/hooks';
import { GlobalHeader, GlobalContent, GlobalFooter, GlobalTab, GlobalLogo, GlobalMenu } from '../common';
import { useRouteProps, useLayoutConfig } from '@/composables';
import {
GlobalHeader,
GlobalContent,
GlobalFooter,
GlobalTab,
HeaderPlaceholder,
GlobalLogo,
GlobalMenu
} from '../common';
const theme = useThemeStore();
const app = useAppStore();
const routeProps = useRouteProps();
const { handleMenuCollapse } = useAppStore();
const inverted = computed(() => {
return theme.navStyle.theme !== 'light';
});
const menuWidth = computed(() => {
const { collapsed } = app.menu;
const { collapsedWidth, width } = theme.menuStyle;
return collapsed ? collapsedWidth : width;
});
const headerInverted = computed(() => {
return theme.navStyle.theme !== 'dark' ? inverted.value : !inverted.value;
});
const headerPosition = computed(() => (theme.fixedHeaderAndTab ? 'absolute' : 'static'));
const headerHeight = computed(() => {
const { height } = theme.headerStyle;
return `${height}px`;
});
const tabHeight = computed(() => {
const { height } = theme.multiTabStyle;
return `${height}px`;
});
const headerAndTabHeight = computed(() => {
const {
multiTabStyle: { visible, height: tH },
headerStyle: { height: hH }
} = theme;
const height = visible ? tH + hH : hH;
return `${height}px`;
});
const routeProps = useRouteProps();
const { siderInverted, siderMenuWidth, headerInverted, headerPosition, headerHeight } = useLayoutConfig();
</script>
<style scoped>
.global-sider {
transition: all 0.2s ease-in-out;
box-shadow: 2px 0 8px 0 rgb(29 35 41 / 5%);
}
.header-height {
height: v-bind(headerHeight);
}
.header-padding {
padding-top: v-bind(headerHeight);
}
.tab-height {
height: v-bind(tabHeight);
}
.header-tab_height {
height: v-bind(headerAndTabHeight);
}
</style>

View File

@ -1,11 +1,50 @@
<template>
<div>
<div class="flex">
<h3>vertical-mix</h3>
</div>
<router-view />
</div>
<n-layout :has-sider="true" class="h-full">
<n-layout-sider
class="global-sider z-12 transition-all duration-200 ease-in-out"
:inverted="siderInverted"
collapse-mode="width"
:collapsed="app.menu.collapsed"
:collapsed-width="theme.menuStyle.collapsedWidth"
:width="siderMenuWidth"
:native-scrollbar="false"
@collapse="handleMenuCollapse(true)"
@expand="handleMenuCollapse(false)"
>
<global-logo :show-title="!app.menu.collapsed" class="absolute-lt z-2" />
<global-menu :style="{ paddingTop: headerHeight }" />
</n-layout-sider>
<n-layout-content
:native-scrollbar="false"
:content-style="{ height: routeProps.fullPage ? '100%' : 'auto' }"
class="bg-[#f6f9f8] dark:bg-deep-dark"
>
<n-layout-header :inverted="headerInverted" :position="headerPosition" class="z-11">
<global-header :show-logo="false" :show-menu-collape="true" :show-menu="false" class="relative z-2" />
<global-tab v-if="theme.multiTabStyle.visible" />
</n-layout-header>
<div v-if="theme.fixedHeaderAndTab" :style="{ height: headerAndMultiTabHeight }"></div>
<global-content />
<global-footer />
</n-layout-content>
</n-layout>
</template>
<script setup lang="ts"></script>
<style scoped></style>
<script setup lang="ts">
import { NLayout, NLayoutSider, NLayoutContent, NLayoutHeader } from 'naive-ui';
import { useThemeStore, useAppStore } from '@/store';
import { useRouteProps, useLayoutConfig } from '@/composables';
import { GlobalHeader, GlobalContent, GlobalFooter, GlobalTab, GlobalLogo, GlobalMenu } from '../common';
const theme = useThemeStore();
const app = useAppStore();
const { handleMenuCollapse } = useAppStore();
const routeProps = useRouteProps();
const { siderInverted, siderMenuWidth, headerInverted, headerPosition, headerHeight, headerAndMultiTabHeight } =
useLayoutConfig();
</script>
<style scoped>
.global-sider {
box-shadow: 2px 0 8px 0 rgb(29 35 41 / 5%);
}
</style>

View File

@ -15,7 +15,7 @@ import { computed } from 'vue';
import { useThemeStore } from '@/store';
import { useReloadInject } from '@/context';
import { cacheRoutes } from '@/router';
import { useRouteProps } from '@/hooks';
import { useRouteProps } from '@/composables';
const theme = useThemeStore();
const { reload } = useReloadInject();

View File

@ -32,15 +32,15 @@ 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 { EnumRoutePath } from '@/enum';
import { routePath } from '@/router';
import { useThemeStore } from '@/store';
import type { RoutePathKey } from '@/interface';
import type { RouteKey } from '@/interface';
type Breadcrumb = DropdownOption & {
key: string;
label: string;
disabled: boolean;
routeName: RoutePathKey;
routeName: RouteKey;
hasChildren: boolean;
iconName?: string;
children?: Breadcrumb[];
@ -62,11 +62,11 @@ function recursionBreadcrumb(routeMatched: RouteLocationMatched[]) {
const list: Breadcrumb[] = [];
routeMatched.forEach(item => {
if (!item.meta?.isNotMenu) {
const routeName = item.name as RoutePathKey;
const routeName = item.name as RouteKey;
const breadcrumItem: Breadcrumb = {
key: routeName,
label: (item.meta?.title as string) || '',
disabled: item.path === EnumRoutePath.root,
disabled: item.path === routePath('root'),
routeName,
hasChildren: false
};
@ -84,7 +84,7 @@ function recursionBreadcrumb(routeMatched: RouteLocationMatched[]) {
}
function dropdownSelect(optionKey: string) {
const key = optionKey as RoutePathKey;
const key = optionKey as RouteKey;
router.push({ name: key });
}
</script>

View File

@ -10,13 +10,13 @@
<script lang="ts" setup>
import { NDropdown, useDialog } from 'naive-ui';
import { HoverContainer } from '@/components';
import { useRouterChange } from '@/hooks';
import { useRouterPush } from '@/composables';
import { iconifyRender, resetAuthStorage } from '@/utils';
import avatar from '@/assets/svg/avatar/avatar01.svg';
type DropdownKey = 'user-center' | 'logout';
const { toLogin } = useRouterChange();
const { toLogin } = useRouterPush();
const dialog = useDialog();
const options = [

View File

@ -1,12 +1,12 @@
<template>
<div class="global-header flex-y-center w-full">
<div class="global-header flex-y-center w-full" :style="{ height: headerHeight }">
<global-logo v-if="showLogo" :show-title="true" class="h-full" :style="{ width: theme.menuStyle.width + 'px' }" />
<div class="flex-1-hidden flex-y-center h-full">
<div v-if="!showMenu" class="flex-1-hidden flex-y-center h-full">
<menu-collapse v-if="showMenuCollape" />
<global-breadcrumb v-if="theme.crumbsStyle.visible" />
</div>
<div
v-if="showMenu"
v-else
class="flex-1-hidden flex-y-center h-full"
:style="{ justifyContent: theme.menuStyle.horizontalPosition }"
>
@ -24,6 +24,7 @@
<script lang="ts" setup>
import { useThemeStore } from '@/store';
import { useLayoutConfig } from '@/composables';
import {
HeaderMenu,
GlobalBreadcrumb,
@ -48,6 +49,7 @@ interface Props {
defineProps<Props>();
const theme = useThemeStore();
const { headerHeight } = useLayoutConfig();
const showSettingButton = import.meta.env.DEV || import.meta.env.VITE_HTTP_ENV === 'STAGING';
</script>

View File

@ -3,6 +3,7 @@
href="/"
class="
flex-center
w-full
nowrap-hidden
bg-light
dark:bg-dark
@ -11,6 +12,7 @@
ease-in-out
cursor-pointer
"
:style="{ height: headerHeight }"
>
<system-logo class="w-32px h-32px" :color="theme.themeColor" />
<h2 v-show="showTitle" class="text-primary pl-8px text-16px font-bold">{{ title }}</h2>
@ -20,7 +22,7 @@
<script lang="ts" setup>
import { SystemLogo } from '@/components';
import { useThemeStore } from '@/store';
import { useAppTitle } from '@/hooks';
import { useAppTitle, useLayoutConfig } from '@/composables';
interface Props {
/** 显示名字 */
@ -31,5 +33,6 @@ defineProps<Props>();
const theme = useThemeStore();
const title = useAppTitle();
const { headerHeight } = useLayoutConfig();
</script>
<style scoped></style>

View File

@ -1,5 +1,5 @@
<template>
<div class="multi-tab flex-center w-full pl-16px">
<div class="multi-tab flex-center w-full pl-16px" :style="{ height: multiTabHeight }">
<div class="flex-1-hidden h-full">
<better-scroll :options="{ scrollX: true, scrollY: false, click: true }">
<multi-tab />
@ -13,11 +13,13 @@
import { watch } from 'vue';
import { useRoute } from 'vue-router';
import { useAppStore } from '@/store';
import { useLayoutConfig } from '@/composables';
import { BetterScroll } from '@/components';
import { MultiTab, ReloadButton } from './components';
const route = useRoute();
const { initMultiTab, addMultiTab, setActiveMultiTab } = useAppStore();
const { multiTabHeight } = useLayoutConfig();
function init() {
initMultiTab();

View File

@ -0,0 +1,12 @@
<template>
<div v-if="theme.fixedHeaderAndTab" :style="{ height: headerAndMultiTabHeight }"></div>
</template>
<script setup lang="ts">
import { useThemeStore } from '@/store';
import { useLayoutConfig } from '@/composables';
const theme = useThemeStore();
const { headerAndMultiTabHeight } = useLayoutConfig();
</script>
<style scoped></style>

View File

@ -4,6 +4,16 @@ import GlobalFooter from './GlobalFooter/index.vue';
import GlobalLogo from './GlobalLogo/index.vue';
import GlobalMenu from './GlobalMenu/index.vue';
import GlobalTab from './GlobalTab/index.vue';
import HeaderPlaceholder from './HeaderPlaceholder/index.vue';
import SettingDrawer from './SettingDrawer/index.vue';
export { GlobalHeader, GlobalContent, GlobalFooter, GlobalLogo, GlobalMenu, GlobalTab, SettingDrawer };
export {
GlobalHeader,
GlobalContent,
GlobalFooter,
GlobalLogo,
GlobalMenu,
GlobalTab,
HeaderPlaceholder,
SettingDrawer
};

View File

@ -1,6 +1,14 @@
<template>
<div
class="flex-1 flex-col-stretch p-16px bg-[#F6F9F8] dark:bg-black"
class="
flex-1 flex-col-stretch
p-16px
bg-[#f6f9f8]
dark:bg-deep-dark
transition-backgorund-color
duration-300
ease-in-out
"
:class="{ 'overflow-hidden': routeProps.fullPage }"
>
<router-view v-slot="{ Component, route }">
@ -17,7 +25,7 @@
import { useThemeStore } from '@/store';
import { useReloadInject } from '@/context';
import { cacheRoutes } from '@/router';
import { useRouteProps } from '@/hooks';
import { useRouteProps } from '@/composables';
const theme = useThemeStore();
const { reload } = useReloadInject();

View File

@ -32,15 +32,15 @@ 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 { EnumRoutePath } from '@/enum';
import { routePath } from '@/router';
import { useThemeStore } from '@/store';
import type { RoutePathKey } from '@/interface';
import type { RouteKey } from '@/interface';
type Breadcrumb = DropdownOption & {
key: string;
label: string;
disabled: boolean;
routeName: RoutePathKey;
routeName: RouteKey;
hasChildren: boolean;
iconName?: string;
children?: Breadcrumb[];
@ -62,11 +62,11 @@ function recursionBreadcrumb(routeMatched: RouteLocationMatched[]) {
const list: Breadcrumb[] = [];
routeMatched.forEach(item => {
if (!item.meta?.isNotMenu) {
const routeName = item.name as RoutePathKey;
const routeName = item.name as RouteKey;
const breadcrumItem: Breadcrumb = {
key: routeName,
label: (item.meta?.title as string) || '',
disabled: item.path === EnumRoutePath.root,
disabled: item.path === routePath('root'),
routeName,
hasChildren: false
};
@ -84,7 +84,7 @@ function recursionBreadcrumb(routeMatched: RouteLocationMatched[]) {
}
function dropdownSelect(optionKey: string) {
const key = optionKey as RoutePathKey;
const key = optionKey as RouteKey;
router.push({ name: key });
}
</script>

View File

@ -10,13 +10,13 @@
<script lang="ts" setup>
import { NDropdown, useDialog } from 'naive-ui';
import { HoverContainer } from '@/components';
import { useRouterChange } from '@/hooks';
import { useRouterPush } from '@/composables';
import { iconifyRender, resetAuthStorage } from '@/utils';
import avatar from '@/assets/svg/avatar/avatar01.svg';
type DropdownKey = 'user-center' | 'logout';
const { toLogin } = useRouterChange();
const { toLogin } = useRouterPush();
const dialog = useDialog();
const options = [

View File

@ -35,7 +35,7 @@ import { useRouter, useRoute } from 'vue-router';
import { NScrollbar, NMenu } from 'naive-ui';
import type { MenuOption } from 'naive-ui';
import { useThemeStore, useAppStore } from '@/store';
import { useAppTitle } from '@/hooks';
import { useAppTitle } from '@/composables';
import { menus } from '@/router';
import type { GlobalMenuOption } from '@/interface';

View File

@ -1,8 +1,19 @@
<template>
<div v-if="fixedHeaderAndTab && theme.navStyle.mode !== 'horizontal-mix'" class="multi-tab-height w-full"></div>
<div
class="multi-tab flex-center justify-between w-full pl-10px"
:class="[theme.darkMode ? 'bg-[#18181c]' : 'bg-white', { 'multi-tab-top absolute': fixedHeaderAndTab }]"
class="
multi-tab
flex-center
justify-between
w-full
pl-10px
bg-light
dark:bg-dark
transition-backgorund-color
duration-300
ease-in-out
"
:class="{ 'multi-tab-top absolute': fixedHeaderAndTab }"
:style="{ zIndex }"
:align="'center'"
justify="space-between"

View File

@ -9,7 +9,7 @@
import { computed } from 'vue';
import { SystemLogo } from '@/components';
import { useAppStore, useThemeStore } from '@/store';
import { useAppTitle } from '@/hooks';
import { useAppTitle } from '@/composables';
const app = useAppStore();
const theme = useThemeStore();

View File

@ -4,7 +4,7 @@
<global-header v-if="isHorizontalMix" :z-index="14" />
<div class="flex-1-hidden flex h-full">
<global-sider v-if="isHorizontalMix" :z-index="13" />
<n-scrollbar ref="scrollbar" class="h-full" :content-class="routeProps.fullPage ? 'h-full' : ''">
<n-scrollbar class="h-full" :content-class="routeProps.fullPage ? 'h-full' : ''">
<div
class="inline-flex-col-stretch w-full"
:class="[{ 'content-padding': isHorizontalMix }, routeProps.fullPage ? 'h-full' : 'min-h-100vh']"
@ -21,16 +21,13 @@
</template>
<script lang="ts" setup>
import { computed, watch } from 'vue';
import { useRoute } from 'vue-router';
import { computed } from 'vue';
import { NLayout, NScrollbar } from 'naive-ui';
import { useThemeStore } from '@/store';
import { useRouteProps, useScrollBehavior } from '@/hooks';
import { useRouteProps } from '@/composables';
import { GlobalSider, GlobalHeader, GlobalTab, GlobalContent, GlobalFooter, SettingDrawer } from './components';
const route = useRoute();
const theme = useThemeStore();
const { scrollbar, resetScrollBehavior } = useScrollBehavior();
const routeProps = useRouteProps();
const isHorizontalMix = computed(() => theme.navStyle.mode === 'horizontal-mix');
@ -42,13 +39,6 @@ const headerAndMultiTabHeight = computed(() => {
} = theme;
return `${hHeight + mHeight}px`;
});
watch(
() => route.name,
() => {
resetScrollBehavior();
}
);
</script>
<style scoped>
:deep(.n-scrollbar-rail) {

View File

@ -18,26 +18,15 @@
</template>
<script lang="ts" setup>
import { watch } from 'vue';
import { useRoute } from 'vue-router';
import { NScrollbar } from 'naive-ui';
import { useRouteProps, useScrollBehavior } from '@/hooks';
import { useThemeStore } from '@/store';
import { useReloadInject } from '@/context';
import { cacheRoutes } from '@/router';
import { useRouteProps } from '@/composables';
const theme = useThemeStore();
const { reload } = useReloadInject();
const route = useRoute();
const { scrollbar, resetScrollBehavior } = useScrollBehavior();
const routeProps = useRouteProps();
watch(
() => route.name,
() => {
resetScrollBehavior();
}
);
</script>
<style scoped></style>