wip(Layout): Layout developing

This commit is contained in:
陈凯龙
2022-01-13 17:26:06 +08:00
parent 66e8d0e41c
commit 2fe9543b84
27 changed files with 282 additions and 35 deletions

View File

@@ -0,0 +1,3 @@
import Breadcrumb from './src/Breadcrumb.vue'
export { Breadcrumb }

View File

@@ -0,0 +1,3 @@
import Collapse from './src/Collapse.vue'
export { Collapse }

View File

@@ -0,0 +1,25 @@
<script setup lang="ts">
import { computed, unref } from 'vue'
import { Icon } from '@/components/Icon'
import { useAppStore } from '@/store/modules/app'
const appStore = useAppStore()
const collapse = computed(() => appStore.getCollapse)
function toggleCollapse() {
const collapsed = unref(collapse)
appStore.setCollapse(!collapsed)
}
</script>
<template>
<div>
<Icon
:size="18"
:icon="collapse ? 'ant-design:menu-unfold-outlined' : 'ant-design:menu-fold-outlined'"
class="cursor-pointer"
@click="toggleCollapse"
/>
</div>
</template>

View File

@@ -25,6 +25,7 @@ function setLang(lang: LocaleType) {
<template>
<ElDropdown trigger="click" @command="setLang">
<Icon
:size="18"
icon="ion:language-sharp"
color="var(--el-text-color-primary)"
class="cursor-pointer"

View File

@@ -22,8 +22,8 @@ export default defineComponent({
const preFixCls = getPrefixCls('menu')
const menuMode = computed(() => {
// 水平模式
const menuMode = computed((): 'vertical' | 'horizontal' => {
//
const vertical: LayoutType[] = ['classic']
if (vertical.includes(appStore.getLayout)) {
@@ -77,7 +77,7 @@ export default defineComponent({
>
{{
default: () => {
const { renderMenuItem } = useRenderMenuItem(routers.value)
const { renderMenuItem } = useRenderMenuItem(routers.value, menuMode.value)
return renderMenuItem()
}
}}
@@ -93,7 +93,10 @@ export default defineComponent({
@prefix-cls: ~'@{namespace}-menu';
.@{prefix-cls} {
transition: width var(--transition-time-02);
:deep(.el-menu) {
width: 100% !important;
border-right: none;
// 设置选中时子标题的颜色
@@ -132,8 +135,55 @@ export default defineComponent({
}
}
// 折叠时的最小宽度
:deep(.el-menu--collapse) {
width: var(--left-menu-min-width);
& > .is-active,
& > .is-active > .el-sub-menu__title {
background-color: var(--left-menu-collapse-bg-active-color) !important;
}
}
// 折叠动画的时候,就需要把文字给隐藏掉
:deep(.horizontal-collapse-transition) {
transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out !important;
.@{prefix-cls}__title {
display: none;
}
}
}
</style>
<style lang="less">
@prefix-cls: ~'@{namespace}-menu-popper';
.@{prefix-cls} {
&--vertical {
// 设置选中时子标题的颜色
.is-active {
& > .el-sub-menu__title {
color: var(--left-menu-text-active-color) !important;
}
}
// 设置子菜单悬停的高亮和背景色
.el-sub-menu__title,
.el-menu-item {
&:hover {
color: var(--left-menu-text-active-color) !important;
background-color: var(--left-menu-bg-color) !important;
}
}
// 设置选中时的高亮背景
.el-menu-item.is-active {
background-color: var(--left-menu-bg-active-color) !important;
&:hover {
background-color: var(--left-menu-bg-active-color) !important;
}
}
}
}
</style>

View File

@@ -3,8 +3,13 @@ import type { RouteMeta } from 'vue-router'
import { getAllParentPath, hasOneShowingChild } from '../helper'
import { isUrl } from '@/utils/is'
import { useRenderMenuTitle } from './useRenderMenuTitle'
import { useDesign } from '@/hooks/web/useDesign'
import { pathResolve } from '@/utils/routerHelper'
export function useRenderMenuItem(allRouters: AppRouteRecordRaw[] = []) {
export function useRenderMenuItem(
allRouters: AppRouteRecordRaw[] = [],
menuMode: 'vertical' | 'horizontal'
) {
function renderMenuItem(routers?: AppRouteRecordRaw[]) {
return (routers || allRouters).map((v) => {
const meta = (v.meta ?? {}) as RouteMeta
@@ -23,15 +28,23 @@ export function useRenderMenuItem(allRouters: AppRouteRecordRaw[] = []) {
!meta?.alwaysShow
) {
return (
<ElMenuItem index={fullPath}>
<ElMenuItem index={onlyOneChild ? pathResolve(fullPath, onlyOneChild.path) : fullPath}>
{{
default: () => renderMenuTitle(meta)
default: () => renderMenuTitle(onlyOneChild ? onlyOneChild?.meta : meta)
}}
</ElMenuItem>
)
} else {
const { getPrefixCls } = useDesign()
const preFixCls = getPrefixCls('menu-popper')
return (
<ElSubMenu index={fullPath}>
<ElSubMenu
index={fullPath}
popperClass={
menuMode === 'vertical' ? `${preFixCls}--vertical` : `${preFixCls}--horizontal`
}
>
{{
title: () => renderMenuTitle(meta),
default: () => renderMenuItem(v.children)

View File

@@ -10,10 +10,10 @@ export function useRenderMenuTitle() {
return icon ? (
<>
<Icon icon={meta.icon}></Icon>
{t(title as string)}
<span>{t(title as string)}</span>
</>
) : (
t(title as string)
<span>{t(title as string)}</span>
)
}

View File

@@ -0,0 +1,3 @@
import Screenfull from './src/Screenfull.vue'
export { Screenfull }

View File

@@ -0,0 +1,16 @@
<script setup lang="ts">
import { Icon } from '@/components/Icon'
import { useFullscreen } from '@vueuse/core'
const { toggle, isFullscreen } = useFullscreen()
function toggleFullscreen() {
toggle()
}
</script>
<template>
<div @click="toggleFullscreen">
<Icon :size="18" :icon="isFullscreen ? 'zmdi:fullscreen-exit' : 'zmdi:fullscreen'" />
</div>
</template>

View File

@@ -16,7 +16,12 @@ function setSize(size: ElememtPlusSzie) {
<template>
<ElDropdown trigger="click" @command="setSize">
<Icon icon="mdi:format-size" color="var(--el-text-color-primary)" class="cursor-pointer" />
<Icon
:size="18"
icon="mdi:format-size"
color="var(--el-text-color-primary)"
class="cursor-pointer"
/>
<template #dropdown>
<ElDropdownMenu>
<ElDropdownItem v-for="item in sizeMap" :key="item" :command="item">

View File

@@ -0,0 +1,3 @@
import UserInfo from './src/UserInfo.vue'
export { UserInfo }

View File

@@ -0,0 +1,46 @@
<script setup lang="ts">
import { ElDropdown, ElDropdownMenu, ElDropdownItem, ElMessageBox } from 'element-plus'
import { useI18n } from '@/hooks/web/useI18n'
import { useCache } from '@/hooks/web/useCache'
import { resetRouter } from '@/router'
import { useRouter } from 'vue-router'
const { t } = useI18n()
const { wsCache } = useCache()
const { replace } = useRouter()
function loginOut() {
ElMessageBox.confirm(t('common.loginOutMessage'), t('common.reminder'), {
confirmButtonText: t('common.ok'),
cancelButtonText: t('common.cancel'),
type: 'warning'
})
.then(() => {
wsCache.clear()
resetRouter() // 重置静态路由表
replace('/login')
})
.catch(() => {})
}
</script>
<template>
<ElDropdown trigger="click">
<div class="flex items-center">
<img src="@/assets/imgs/avatar.png" alt="" class="w-[calc(var(--tags-view-height)-10px)]" />
<span class="<lg:hidden text-14px pl-[5px] text-dark-50">Archer</span>
</div>
<template #dropdown>
<ElDropdownMenu>
<ElDropdownItem>
<div>{{ t('common.document') }}</div>
</ElDropdownItem>
<ElDropdownItem divided>
<div @click="loginOut">{{ t('common.loginOut') }}</div>
</ElDropdownItem>
</ElDropdownMenu>
</template>
</ElDropdown>
</template>