refactor: ♻️ 侧边栏和页签样式重构

This commit is contained in:
hxr 2024-01-15 00:32:03 +08:00
parent cd6dd5b6f1
commit 5a650c6830
9 changed files with 119 additions and 167 deletions

View File

@ -15,7 +15,6 @@
<script setup lang="ts">
import { PropType } from "vue";
import { scrollTo } from "@/utils/scroll-to";
const props = defineProps({
total: {
@ -63,17 +62,11 @@ const pageSize = useVModel(props, "limit", emit);
function handleSizeChange(val: number) {
emit("pagination", { page: currentPage, limit: val });
if (props.autoScroll) {
scrollTo(0, 800);
}
}
function handleCurrentChange(val: number) {
currentPage.value = val;
emit("pagination", { page: val, limit: props.limit });
if (props.autoScroll) {
scrollTo(0, 800);
}
}
</script>

View File

@ -1,7 +1,7 @@
<template>
<el-scrollbar>
<el-menu
:default-active="currentRoute.path"
:default-active="activeMenu"
:collapse-transition="false"
:collapse="!appStore.sidebarOpen"
:unique-opened="false"
@ -17,7 +17,7 @@
import { useAppStore } from "@/store";
import router from "@/router";
defineProps({
const props = defineProps({
menus: {
required: true,
default: () => {
@ -28,7 +28,9 @@ defineProps({
});
const appStore = useAppStore();
const currentRoute = useRoute(); //
const activeMenu = computed(() => {
return router.currentRoute.value.path;
});
/**
* 菜单激活回调

View File

@ -1,14 +1,14 @@
<template>
<!-- 当前路由没有子菜单 -->
<el-menu-item v-if="showMenuItem" :index="item.path">
<!-- 没有子菜单 -->
<el-menu-item v-if="showMenuItem" :index="item.path" :key="item.path">
<menu-title
:icon="onlyOneChild.meta?.icon"
:title="onlyOneChild.meta?.title"
/>
</el-menu-item>
<!-- 当前路由有子菜单 -->
<el-sub-menu :index="item.path" v-else-if="!item.meta?.hidden">
<!-- 有子菜单 -->
<el-sub-menu v-else-if="!item.meta?.hidden" :index="item.path">
<template #title>
<menu-title :icon="item.meta?.icon" :title="item.meta?.title" />
</template>
@ -35,7 +35,7 @@ const showMenuItem = computed(() => {
);
});
// ( item chidren onlyOneChild )
//
const onlyOneChild = ref<any>(null);
/**
@ -45,7 +45,7 @@ function hasSingleShowingChild(
children: RouteRecordRaw[] = [],
parent: RouteRecordRaw
) {
//
//
const showingChildren = children.filter((route: RouteRecordRaw) => {
if (route.meta?.hidden) {
return false;

View File

@ -1,6 +1,6 @@
<template>
<svg-icon v-if="icon" :icon-name="icon" />
<span v-if="title" class="ml-1">{{ translateRouteTitle(title) }}</span>
<span class="title" v-if="title">{{ translateRouteTitle(title) }}</span>
</template>
<script setup lang="ts">
@ -17,3 +17,17 @@ defineProps({
},
});
</script>
<style scoped lang="scss">
.el-menu {
.title {
margin-left: 5px;
}
&--collapse {
.title {
margin-left: 0;
}
}
}
</style>

View File

@ -1,6 +1,6 @@
<!--侧边栏 -->
<template>
<el-aside class="flex flex-col" :width="sideBarWidth">
<el-aside class="sidebar-container" :width="sideBarWidth">
<Logo
v-if="settingsStore.showSidebarLogo"
:collapse="!appStore.sidebarOpen"
@ -20,7 +20,79 @@ const sideBarWidth = computed(() => {
if (appStore.isMobile) {
return appStore.sidebarOpen ? "210px" : "0";
} else {
return appStore.sidebarOpen ? "210px" : "54px";
return appStore.sidebarOpen ? "210px" : "64px";
}
});
</script>
<style lang="scss">
.sidebar-container {
display: flex;
flex-direction: column;
.el-menu {
--el-menu-hover-bg-color: transparent;
--el-menu-bg-color: transparent;
&--collapse {
.el-sub-menu,
.el-menu-item {
justify-content: center;
&__title {
justify-content: center;
}
}
}
.el-sub-menu {
&.is-active > .el-sub-menu__title {
color: var(--el-color-primary);
}
.el-sub-menu__title {
& > * {
z-index: 1;
}
&:hover::before {
position: absolute;
inset: 2px 5px;
clear: both;
content: "";
background: var(--el-fill-color);
border-radius: 4px;
}
}
}
.el-menu-item {
& > * {
z-index: 1;
}
&.is-active > * {
color: var(--el-color-primary);
}
&:hover::before {
position: absolute;
inset: 2px 5px;
clear: both;
content: "";
background: var(--el-fill-color);
border-radius: 4px;
}
&.is-active::before {
position: absolute;
inset: 2px 5px;
clear: both;
content: "";
background: var(--el-color-primary-light-8);
border-radius: 4px;
}
}
}
}
</style>

View File

@ -7,13 +7,15 @@
:name="item.fullPath"
>
<template #label>
<div @contextmenu.prevent="openContextmenu($event, item)">
<span>{{ item.title }}</span>
<div
@contextmenu.prevent="openContextmenu($event, item)"
class="flex flex-center"
>
<span>{{ translateRouteTitle(item.title) }}</span>
<el-icon
v-if="!item.affix"
:size="12"
class="mt-[5px] ml-[5px] hover:bg-primary rounded-full hover:color-white"
class="ml-1 hover:bg-primary rounded-full hover:color-white"
@click.stop="closeTag(item)"
>
<i-ep-close />
@ -23,13 +25,13 @@
</el-tab-pane>
</el-tabs>
<div
<!-- <div
class="flex-center border border-gray-300 cursor-pointer w-[40px]"
@click="refreshSelectedTag(selectedTag)"
>
<svg-icon icon-name="refresh" />
</div>
-->
<!-- tag标签操作菜单 -->
<ul
v-show="contextmenuVisible"
@ -68,6 +70,7 @@
import { useTagsViewStore, usePermissionStore } from "@/store";
import { RouteRecordRaw } from "vue-router";
import { TabPaneName } from "element-plus";
import { translateRouteTitle } from "@/utils/i18n";
const router = useRouter();
const route = useRoute();
@ -94,7 +97,7 @@ watch(
activeName.value = newFullPath;
},
{
immediate: true, //
immediate: true,
}
);
@ -184,10 +187,10 @@ function closeTag(view: TagView) {
/**
* 切换页签
*
* @param targetFullPath
* @param targetPath
*/
function changeTag(targetFullPath: TabPaneName) {
router.push(targetFullPath as string);
function changeTag(targetPath: TabPaneName) {
router.push(targetPath as string);
}
/**
@ -379,14 +382,15 @@ onMounted(() => {
</script>
<style lang="scss" scoped>
:deep(.el-tabs) {
width: calc(100% - 40px);
width: 100%;
.el-tabs__header {
margin: 0;
.el-tabs__item {
height: 30px;
padding: 0 2px;
margin-top: 4px;
margin-left: 8px;
padding: 0 8px !important;
margin: 4px 0 0 5px;
border: 1px solid var(--el-border-color-light);
border-radius: 2px;
@ -395,10 +399,6 @@ onMounted(() => {
}
}
.is-icon-close:hover {
background-color: var(--el-color-primary);
}
.is-active {
background: var(--el-color-primary-light-8);
border-color: var(--el-color-primary-light-3);

View File

@ -31,8 +31,7 @@ export const constantRoutes: RouteRecordRaw[] = [
{
path: "/dashboard",
component: () => import("@/views/dashboard/index.vue"),
name: "Dashboard", // 用于 keep-alive, 必须与SFC自动推导或者显示声明的组件name一致
// https://cn.vuejs.org/guide/built-ins/keep-alive.html#include-exclude
name: "Dashboard", // 用于 keep-alive, 必须与SFC自动推导或者显示声明的组件name一致 https://cn.vuejs.org/guide/built-ins/keep-alive.html#include-exclude
meta: {
title: "dashboard",
icon: "homepage",

View File

@ -1,59 +0,0 @@
.el-menu {
--el-menu-hover-bg-color: transparent;
--el-menu-bg-color: transparent;
.el-sub-menu {
&.is-active > .el-sub-menu__title {
color: var(--el-color-primary);
}
.el-sub-menu__title {
height: 50px;
line-height: 50px;
& > * {
z-index: 1;
}
&:hover::before {
position: absolute;
inset: 2px 12px;
clear: both;
content: "";
background: var(--el-fill-color);
border-radius: 4px;
}
}
}
.el-menu-item {
height: 50px;
line-height: 50px;
& > * {
z-index: 1;
}
&.is-active > * {
color: var(--el-color-primary);
}
&:hover::before {
position: absolute;
inset: 2px 12px;
clear: both;
content: "";
background: var(--el-fill-color);
border-radius: 4px;
}
&.is-active::before {
position: absolute;
inset: 2px 12px;
clear: both;
content: "";
background: var(--el-color-primary-light-8);
border-radius: 4px;
}
}
}

View File

@ -1,69 +0,0 @@
const easeInOutQuad = (t: number, b: number, c: number, d: number) => {
t /= d / 2;
if (t < 1) {
return (c / 2) * t * t + b;
}
t--;
return (-c / 2) * (t * (t - 2) - 1) + b;
};
// requestAnimationFrame for Smart Animating http://goo.gl/sx5sts
const requestAnimFrame = (function () {
return (
window.requestAnimationFrame ||
(window as any).webkitRequestAnimationFrame ||
(window as any).mozRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
}
);
})();
/**
* Because it's so fucking difficult to detect the scrolling element, just move them all
* @param {number} amount
*/
const move = (amount: number) => {
document.documentElement.scrollTop = amount;
(document.body.parentNode as HTMLElement).scrollTop = amount;
document.body.scrollTop = amount;
};
const position = () => {
return (
document.documentElement.scrollTop ||
(document.body.parentNode as HTMLElement).scrollTop ||
document.body.scrollTop
);
};
/**
* @param {number} to
* @param {number} duration
* @param {Function} callback
*/
export const scrollTo = (to: number, duration: number, callback?: any) => {
const start = position();
const change = to - start;
const increment = 20;
let currentTime = 0;
duration = typeof duration === "undefined" ? 500 : duration;
const animateScroll = function () {
// increment the time
currentTime += increment;
// find the value with the quadratic in-out easing function
const val = easeInOutQuad(currentTime, start, change, duration);
// move the document.body
move(val);
// do the animation unless its over
if (currentTime < duration) {
requestAnimFrame(animateScroll);
} else {
if (callback && typeof callback === "function") {
// the animation is done so lets callback
callback();
}
}
};
animateScroll();
};